summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2024-11-25 18:07:39 +0700
committerGitHub <[email protected]>2024-11-25 18:07:39 +0700
commit66741e35c2661ccaa6a8f8cd6d2f6d7aab049f2c (patch)
tree4c7d6bf0ea2986670b812481bacdc8126ae8f7b8
parent2571889061f70b9fd425ee4e4174018bf07c5309 (diff)
parentc09eedaf24ad609a1b12bf9c1c7f631b8374f222 (diff)
Merge pull request #2884 from hathach/esp32p4-dma
More Esp32p4 dma with cache sync
-rw-r--r--.circleci/config2.yml4
-rw-r--r--.github/actions/get_deps/action.yml2
-rw-r--r--.github/actions/setup_toolchain/action.yml4
-rw-r--r--.idea/cmake.xml6
-rw-r--r--examples/build_system/cmake/toolchain/aarch64_gcc.cmake6
-rw-r--r--examples/build_system/cmake/toolchain/arm_clang.cmake6
-rw-r--r--examples/build_system/cmake/toolchain/arm_gcc.cmake6
-rw-r--r--examples/build_system/cmake/toolchain/arm_iar.cmake6
-rw-r--r--examples/build_system/cmake/toolchain/msp430_gcc.cmake6
-rw-r--r--examples/build_system/cmake/toolchain/riscv_gcc.cmake6
-rw-r--r--examples/device/audio_4_channel_mic_freertos/CMakeLists.txt1
-rw-r--r--examples/device/audio_4_channel_mic_freertos/Makefile1
-rw-r--r--examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c115
-rw-r--r--examples/device/audio_test_freertos/CMakeLists.txt1
-rw-r--r--examples/device/audio_test_freertos/Makefile1
-rw-r--r--examples/device/audio_test_freertos/src/freertos_hook.c115
-rw-r--r--examples/device/cdc_msc_freertos/CMakeLists.txt1
-rw-r--r--examples/device/cdc_msc_freertos/Makefile1
-rw-r--r--examples/device/cdc_msc_freertos/src/freertos_hook.c115
-rw-r--r--examples/device/cdc_msc_freertos/src/main.c23
-rw-r--r--examples/device/hid_composite_freertos/CMakeLists.txt1
-rw-r--r--examples/device/hid_composite_freertos/Makefile1
-rw-r--r--examples/device/hid_composite_freertos/src/freertos_hook.c115
-rw-r--r--examples/device/midi_test/CMakeLists.txt12
-rw-r--r--examples/device/midi_test/src/main.c39
-rw-r--r--examples/device/midi_test/src/usb_descriptors.c34
-rw-r--r--examples/device/midi_test_freertos/CMakeLists.txt33
-rw-r--r--examples/device/midi_test_freertos/Makefile40
-rw-r--r--examples/device/midi_test_freertos/skip.txt16
-rw-r--r--examples/device/midi_test_freertos/src/CMakeLists.txt4
-rw-r--r--examples/device/midi_test_freertos/src/main.c239
-rw-r--r--examples/device/midi_test_freertos/src/tusb_config.h108
-rw-r--r--examples/device/midi_test_freertos/src/usb_descriptors.c199
-rw-r--r--examples/host/cdc_msc_hid_freertos/CMakeLists.txt1
-rw-r--r--examples/host/cdc_msc_hid_freertos/Makefile1
-rw-r--r--examples/host/cdc_msc_hid_freertos/src/freertos_hook.c111
-rw-r--r--hw/bsp/board.c88
-rw-r--r--hw/bsp/espressif/boards/espressif_p4_function_ev/board.h2
-rw-r--r--hw/bsp/family_support.cmake1
-rw-r--r--hw/bsp/kinetis_k/FreeRTOSConfig/FreeRTOSConfig.h2
-rw-r--r--hw/bsp/kinetis_k/boards/teensy_35/board.cmake1
-rw-r--r--hw/bsp/kinetis_k/family.cmake1
-rw-r--r--hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h1
-rw-r--r--hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h1
-rw-r--r--hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h6
-rw-r--r--hw/bsp/rx/FreeRTOSConfig/FreeRTOSConfig.h177
-rw-r--r--hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h7
-rw-r--r--lib/networking/rndis_reports.c6
-rwxr-xr-xsrc/class/bth/bth_device.c28
-rw-r--r--src/class/cdc/cdc_device.c122
-rw-r--r--src/class/dfu/dfu_device.c283
-rw-r--r--src/class/dfu/dfu_rt_device.c5
-rw-r--r--src/class/hid/hid_device.c68
-rw-r--r--src/class/midi/midi_device.c157
-rw-r--r--src/class/msc/msc_device.c593
-rw-r--r--src/class/net/ecm_rndis_device.c306
-rw-r--r--src/class/net/ncm.h7
-rw-r--r--src/class/net/ncm_device.c94
-rw-r--r--src/class/usbtmc/usbtmc_device.c65
-rw-r--r--src/class/vendor/vendor_device.c64
-rw-r--r--src/class/video/video_device.c107
-rw-r--r--src/common/tusb_common.h2
-rw-r--r--src/common/tusb_compiler.h5
-rw-r--r--src/common/tusb_mcu.h9
-rw-r--r--src/common/tusb_types.h17
-rw-r--r--src/device/usbd_control.c49
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c33
-rw-r--r--src/portable/synopsys/dwc2/dwc2_esp32.h1
-rw-r--r--src/tusb_option.h34
-rw-r--r--test/hil/tinyusb.json3
70 files changed, 1953 insertions, 1772 deletions
diff --git a/.circleci/config2.yml b/.circleci/config2.yml
index 5e73ab456..e811ef3ed 100644
--- a/.circleci/config2.yml
+++ b/.circleci/config2.yml
@@ -12,8 +12,8 @@ commands:
command: |
TOOLCHAIN_JSON='{
"aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
- "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz",
- "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v12.3.1-1.1/xpack-arm-none-eabi-gcc-12.3.1-1.1-linux-x64.tar.gz",
+ "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
+ "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz",
"msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2",
"riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz",
"rx-gcc": "https://llvm-gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run"
diff --git a/.github/actions/get_deps/action.yml b/.github/actions/get_deps/action.yml
index eea241c6c..ae9e7bbef 100644
--- a/.github/actions/get_deps/action.yml
+++ b/.github/actions/get_deps/action.yml
@@ -13,7 +13,7 @@ runs:
uses: actions/checkout@v4
with:
repository: raspberrypi/pico-sdk
- ref: develop
+ ref: master
path: pico-sdk
- name: Linux dependencies
diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml
index 5b9bc95ce..8406a812d 100644
--- a/.github/actions/setup_toolchain/action.yml
+++ b/.github/actions/setup_toolchain/action.yml
@@ -20,7 +20,7 @@ runs:
if: inputs.toolchain == 'arm-gcc'
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
- release: '12.3.Rel1'
+ release: '13.2.Rel1'
- name: Pull ESP-IDF docker
if: inputs.toolchain == 'esp-idf'
@@ -38,7 +38,7 @@ runs:
run: |
TOOLCHAIN_JSON='{
"aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
- "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz",
+ "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
"msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2",
"riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz",
"rx-gcc": "http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run"
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index 1210c49e7..aa15374b9 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -61,7 +61,7 @@
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
- <configuration PROFILE_NAME="espressif_p4_function_ev-CFG_TUD_DWC2_DMA" ENABLED="false" GENERATION_DIR="cmake-build-espressif_p4_function_ev-CFG_TUD_DWC2_DMA" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_p4_function_ev -DLOG=1 -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA=1&quot;">
+ <configuration PROFILE_NAME="espressif_p4_function_ev-CFG_TUD_DWC2_DMA_ENABLE" ENABLED="false" GENERATION_DIR="cmake-build-espressif_p4_function_ev-CFG_TUD_DWC2_DMA_ENABLE" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_p4_function_ev -DLOG=1 -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA_ENABLE=1&quot;">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ESPBAUD" value="1500000" />
@@ -100,7 +100,7 @@
<configuration PROFILE_NAME="stm32f411disco" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f411disco -DLOG=1 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32f412disco" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f412disco -DLOG=1 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32f723disco" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f723disco -DLOG=0" />
- <configuration PROFILE_NAME="stm32f723disco-CFG_TUD_DWC2_DMA" ENABLED="false" GENERATION_DIR="cmake-build-stm32f723disco-CFG_TUD_DWC2_DMA" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f723disco -DLOG=1 -DLOGGER=RTT -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA=1&quot;" />
+ <configuration PROFILE_NAME="stm32f723disco-CFG_TUD_DWC2_DMA_ENABLE" ENABLED="false" GENERATION_DIR="cmake-build-stm32f723disco-CFG_TUD_DWC2_DMA_ENABLE" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f723disco -DLOG=1 -DLOGGER=RTT -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA_ENABLE=1&quot;" />
<configuration PROFILE_NAME="stm32f723disco_device1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f723disco -DLOG=0 -DRHPORT_DEVICE=1" />
<configuration PROFILE_NAME="stm32f769disco" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32f769disco -DLOG=1 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32g0b1nucleo" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32g0b1nucleo" />
@@ -108,7 +108,7 @@
<configuration PROFILE_NAME="b_g474e_dpow1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=b_g474e_dpow1 -DLOG=1 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32h563nucleo" ENABLED="false" GENERATION_OPTIONS="-DBOARD=stm32h563nucleo -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="stm32h743eval" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32h743eval -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
- <configuration PROFILE_NAME="stm32h743eval-CFG_TUD_DWC2_DMA" ENABLED="false" GENERATION_DIR="cmake-build-stm32h743eval-CFG_TUD_DWC2_DMA" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32h743eval -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1 -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA=1&quot;" />
+ <configuration PROFILE_NAME="stm32h743eval-CFG_TUD_DWC2_DMA_ENABLE" ENABLED="false" GENERATION_DIR="cmake-build-stm32h743eval-CFG_TUD_DWC2_DMA_ENABLE" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32h743eval -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1 -DCFLAGS_CLI=&quot;-DCFG_TUD_DWC2_DMA_ENABLE=1&quot;" />
<configuration PROFILE_NAME="stm32h743eval_host1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32h743eval -DRHPORT_HOST=1 -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="stm32h743nucleo" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32h743nucleo -DLOG=1" />
<configuration PROFILE_NAME="stm32l0538disco" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32l0538disco -DLOG=0 -DLOGGER=RTT" />
diff --git a/examples/build_system/cmake/toolchain/aarch64_gcc.cmake b/examples/build_system/cmake/toolchain/aarch64_gcc.cmake
index 2d30a0b71..ac1e482eb 100644
--- a/examples/build_system/cmake/toolchain/aarch64_gcc.cmake
+++ b/examples/build_system/cmake/toolchain/aarch64_gcc.cmake
@@ -7,9 +7,9 @@ if (NOT DEFINED CMAKE_CXX_COMPILER)
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
-set(CMAKE_SIZE "aarch64-none-elf-size" CACHE FILEPATH "")
-set(CMAKE_OBJCOPY "aarch64-none-elf-objcopy" CACHE FILEPATH "")
-set(CMAKE_OBJDUMP "aarch64-none-elf-objdump" CACHE FILEPATH "")
+find_program(CMAKE_SIZE aarch64-none-elf-size)
+find_program(CMAKE_OBJCOPY aarch64-none-elf-objcopy)
+find_program(CMAKE_OBJDUMP aarch64-none-elf-objdump)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/arm_clang.cmake b/examples/build_system/cmake/toolchain/arm_clang.cmake
index 754d672fd..fe3c2b453 100644
--- a/examples/build_system/cmake/toolchain/arm_clang.cmake
+++ b/examples/build_system/cmake/toolchain/arm_clang.cmake
@@ -7,9 +7,9 @@ if (NOT DEFINED CMAKE_CXX_COMPILER)
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
-set(CMAKE_SIZE "llvm-size" CACHE FILEPATH "")
-set(CMAKE_OBJCOPY "llvm-objcopy" CACHE FILEPATH "")
-set(CMAKE_OBJDUMP "llvm-objdump" CACHE FILEPATH "")
+find_program(CMAKE_SIZE llvm-size)
+find_program(CMAKE_OBJCOPY llvm-objcopy)
+find_program(CMAKE_OBJDUMP llvm-objdump)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/arm_gcc.cmake b/examples/build_system/cmake/toolchain/arm_gcc.cmake
index d3d73c629..0b0949dd8 100644
--- a/examples/build_system/cmake/toolchain/arm_gcc.cmake
+++ b/examples/build_system/cmake/toolchain/arm_gcc.cmake
@@ -7,9 +7,9 @@ if (NOT DEFINED CMAKE_CXX_COMPILER)
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
-set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "")
-set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "")
-set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "")
+find_program(CMAKE_SIZE arm-none-eabi-size)
+find_program(CMAKE_OBJCOPY arm-none-eabi-objcopy)
+find_program(CMAKE_OBJDUMP arm-none-eabi-objdump)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake
index 6d2219ca8..083815715 100644
--- a/examples/build_system/cmake/toolchain/arm_iar.cmake
+++ b/examples/build_system/cmake/toolchain/arm_iar.cmake
@@ -10,8 +10,8 @@ if (NOT DEFINED CMAKE_ASM_COMPILER)
set(CMAKE_ASM_COMPILER "iasmarm")
endif()
-set(CMAKE_SIZE "size" CACHE FILEPATH "")
-set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "")
-set(CMAKE_OBJDUMP "iefdumparm" CACHE FILEPATH "")
+find_program(CMAKE_SIZE size)
+find_program(CMAKE_OBJCOPY ielftool)
+find_program(CMAKE_OBJDUMP iefdumparm)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/msp430_gcc.cmake b/examples/build_system/cmake/toolchain/msp430_gcc.cmake
index 73368adba..799518931 100644
--- a/examples/build_system/cmake/toolchain/msp430_gcc.cmake
+++ b/examples/build_system/cmake/toolchain/msp430_gcc.cmake
@@ -8,8 +8,8 @@ endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
-set(CMAKE_SIZE "msp430-elf-size" CACHE FILEPATH "")
-set(CMAKE_OBJCOPY "msp430-elf-objcopy" CACHE FILEPATH "")
-set(CMAKE_OBJDUMP "msp430-elf-objdump" CACHE FILEPATH "")
+find_program(CMAKE_SIZE msp430-elf-size)
+find_program(CMAKE_OBJCOPY msp430-elf-objcopy)
+find_program(CMAKE_OBJDUMP msp430-elf-objdump)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/build_system/cmake/toolchain/riscv_gcc.cmake b/examples/build_system/cmake/toolchain/riscv_gcc.cmake
index d788df023..60a24528b 100644
--- a/examples/build_system/cmake/toolchain/riscv_gcc.cmake
+++ b/examples/build_system/cmake/toolchain/riscv_gcc.cmake
@@ -16,9 +16,9 @@ if (NOT DEFINED CMAKE_CXX_COMPILER)
endif ()
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
-set(CMAKE_SIZE ${CROSS_COMPILE}size CACHE FILEPATH "")
-set(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy CACHE FILEPATH "")
-set(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump CACHE FILEPATH "")
+find_program(CMAKE_SIZE ${CROSS_COMPILE}size)
+find_program(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy)
+find_program(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump)
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt
index e8ca3751d..285d4490b 100644
--- a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt
+++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt
@@ -19,7 +19,6 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile
index df2cdef4e..0202f631c 100644
--- a/examples/device/audio_4_channel_mic_freertos/Makefile
+++ b/examples/device/audio_4_channel_mic_freertos/Makefile
@@ -12,7 +12,6 @@ INC += \
# Example source
EXAMPLE_SOURCE = \
- src/freertos_hook.c \
src/main.c \
src/usb_descriptors.c
diff --git a/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c b/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c
deleted file mode 100644
index 4920e3fae..000000000
--- a/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "FreeRTOS.h"
-#include "task.h"
-#include "common/tusb_common.h"
-
-
-void vApplicationMallocFailedHook(void)
-{
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
-{
- (void) pxTask;
- (void) pcTaskName;
-
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
- * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
- * used by the Idle task. */
-void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
-{
- /* If the buffers to be provided to the Idle task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xIdleTaskTCB;
- static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
- state will be stored. */
- *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
-
- /* Pass out the array that will be used as the Idle task's stack. */
- *ppxIdleTaskStackBuffer = uxIdleTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configMINIMAL_STACK_SIZE is specified in words, not bytes. */
- *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
-}
-
-/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
- * application must provide an implementation of vApplicationGetTimerTaskMemory()
- * to provide the memory that is used by the Timer service task. */
-void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
-{
- /* If the buffers to be provided to the Timer task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xTimerTaskTCB;
- static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Timer
- task's state will be stored. */
- *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
-
- /* Pass out the array that will be used as the Timer task's stack. */
- *ppxTimerTaskStackBuffer = uxTimerTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
- *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
-}
-
-#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
-#include "iodefine.h"
-void vApplicationSetupTimerInterrupt(void)
-{
- /* Enable CMT0 */
- unsigned short oldPRCR = SYSTEM.PRCR.WORD;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
- MSTP(CMT0) = 0;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
-
- CMT0.CMCNT = 0;
- CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
- CMT0.CMCR.WORD = TU_BIT(6) | 2;
- IR(CMT0, CMI0) = 0;
- IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
- IEN(CMT0, CMI0) = 1;
- CMT.CMSTR0.BIT.STR0 = 1;
-}
-#endif
diff --git a/examples/device/audio_test_freertos/CMakeLists.txt b/examples/device/audio_test_freertos/CMakeLists.txt
index eb22014fb..33f3b915f 100644
--- a/examples/device/audio_test_freertos/CMakeLists.txt
+++ b/examples/device/audio_test_freertos/CMakeLists.txt
@@ -19,7 +19,6 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile
index df2cdef4e..0202f631c 100644
--- a/examples/device/audio_test_freertos/Makefile
+++ b/examples/device/audio_test_freertos/Makefile
@@ -12,7 +12,6 @@ INC += \
# Example source
EXAMPLE_SOURCE = \
- src/freertos_hook.c \
src/main.c \
src/usb_descriptors.c
diff --git a/examples/device/audio_test_freertos/src/freertos_hook.c b/examples/device/audio_test_freertos/src/freertos_hook.c
deleted file mode 100644
index 4920e3fae..000000000
--- a/examples/device/audio_test_freertos/src/freertos_hook.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "FreeRTOS.h"
-#include "task.h"
-#include "common/tusb_common.h"
-
-
-void vApplicationMallocFailedHook(void)
-{
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
-{
- (void) pxTask;
- (void) pcTaskName;
-
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
- * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
- * used by the Idle task. */
-void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
-{
- /* If the buffers to be provided to the Idle task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xIdleTaskTCB;
- static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
- state will be stored. */
- *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
-
- /* Pass out the array that will be used as the Idle task's stack. */
- *ppxIdleTaskStackBuffer = uxIdleTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configMINIMAL_STACK_SIZE is specified in words, not bytes. */
- *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
-}
-
-/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
- * application must provide an implementation of vApplicationGetTimerTaskMemory()
- * to provide the memory that is used by the Timer service task. */
-void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
-{
- /* If the buffers to be provided to the Timer task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xTimerTaskTCB;
- static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Timer
- task's state will be stored. */
- *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
-
- /* Pass out the array that will be used as the Timer task's stack. */
- *ppxTimerTaskStackBuffer = uxTimerTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
- *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
-}
-
-#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
-#include "iodefine.h"
-void vApplicationSetupTimerInterrupt(void)
-{
- /* Enable CMT0 */
- unsigned short oldPRCR = SYSTEM.PRCR.WORD;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
- MSTP(CMT0) = 0;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
-
- CMT0.CMCNT = 0;
- CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
- CMT0.CMCR.WORD = TU_BIT(6) | 2;
- IR(CMT0, CMI0) = 0;
- IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
- IEN(CMT0, CMI0) = 1;
- CMT.CMSTR0.BIT.STR0 = 1;
-}
-#endif
diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt
index 33c7a1ec0..32a9e2930 100644
--- a/examples/device/cdc_msc_freertos/CMakeLists.txt
+++ b/examples/device/cdc_msc_freertos/CMakeLists.txt
@@ -19,7 +19,6 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile
index fe3fb6482..c90922b0c 100644
--- a/examples/device/cdc_msc_freertos/Makefile
+++ b/examples/device/cdc_msc_freertos/Makefile
@@ -12,7 +12,6 @@ INC += \
# Example source
EXAMPLE_SOURCE = \
- src/freertos_hook.c \
src/main.c \
src/msc_disk.c \
src/usb_descriptors.c
diff --git a/examples/device/cdc_msc_freertos/src/freertos_hook.c b/examples/device/cdc_msc_freertos/src/freertos_hook.c
deleted file mode 100644
index 4920e3fae..000000000
--- a/examples/device/cdc_msc_freertos/src/freertos_hook.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "FreeRTOS.h"
-#include "task.h"
-#include "common/tusb_common.h"
-
-
-void vApplicationMallocFailedHook(void)
-{
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
-{
- (void) pxTask;
- (void) pcTaskName;
-
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
- * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
- * used by the Idle task. */
-void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
-{
- /* If the buffers to be provided to the Idle task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xIdleTaskTCB;
- static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
- state will be stored. */
- *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
-
- /* Pass out the array that will be used as the Idle task's stack. */
- *ppxIdleTaskStackBuffer = uxIdleTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configMINIMAL_STACK_SIZE is specified in words, not bytes. */
- *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
-}
-
-/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
- * application must provide an implementation of vApplicationGetTimerTaskMemory()
- * to provide the memory that is used by the Timer service task. */
-void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
-{
- /* If the buffers to be provided to the Timer task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xTimerTaskTCB;
- static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Timer
- task's state will be stored. */
- *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
-
- /* Pass out the array that will be used as the Timer task's stack. */
- *ppxTimerTaskStackBuffer = uxTimerTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
- *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
-}
-
-#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
-#include "iodefine.h"
-void vApplicationSetupTimerInterrupt(void)
-{
- /* Enable CMT0 */
- unsigned short oldPRCR = SYSTEM.PRCR.WORD;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
- MSTP(CMT0) = 0;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
-
- CMT0.CMCNT = 0;
- CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
- CMT0.CMCR.WORD = TU_BIT(6) | 2;
- IR(CMT0, CMI0) = 0;
- IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
- IEN(CMT0, CMI0) = 1;
- CMT.CMSTR0.BIT.STR0 = 1;
-}
-#endif
diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c
index a05ceff58..c51e8ea81 100644
--- a/examples/device/cdc_msc_freertos/src/main.c
+++ b/examples/device/cdc_msc_freertos/src/main.c
@@ -31,23 +31,8 @@
#include "tusb.h"
#if TUSB_MCU_VENDOR_ESPRESSIF
- // ESP-IDF need "freertos/" prefix in include path.
- // CFG_TUSB_OS_INC_PATH should be defined accordingly.
- #include "freertos/FreeRTOS.h"
- #include "freertos/semphr.h"
- #include "freertos/queue.h"
- #include "freertos/task.h"
- #include "freertos/timers.h"
-
#define USBD_STACK_SIZE 4096
#else
-
- #include "FreeRTOS.h"
- #include "semphr.h"
- #include "queue.h"
- #include "task.h"
- #include "timers.h"
-
// Increase stack size when debug log is enabled
#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif
@@ -95,14 +80,10 @@ void cdc_task(void *params);
int main(void) {
board_init();
+ // Create task for: tinyusb, blinky, cdc
#if configSUPPORT_STATIC_ALLOCATION
- // blinky task
xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
-
- // Create a task for tinyusb device stack
xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
-
- // Create CDC task
xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, cdc_stack, &cdc_taskdef);
#else
xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
@@ -110,8 +91,8 @@ int main(void) {
xTaskCreate(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL);
#endif
- // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
#if !TUSB_MCU_VENDOR_ESPRESSIF
+ // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
vTaskStartScheduler();
#endif
diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt
index eb22014fb..33f3b915f 100644
--- a/examples/device/hid_composite_freertos/CMakeLists.txt
+++ b/examples/device/hid_composite_freertos/CMakeLists.txt
@@ -19,7 +19,6 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile
index 88d602393..38d842b3a 100644
--- a/examples/device/hid_composite_freertos/Makefile
+++ b/examples/device/hid_composite_freertos/Makefile
@@ -14,7 +14,6 @@ INC += \
# Example source
EXAMPLE_SOURCE = \
- src/freertos_hook.c \
src/main.c \
src/usb_descriptors.c
diff --git a/examples/device/hid_composite_freertos/src/freertos_hook.c b/examples/device/hid_composite_freertos/src/freertos_hook.c
deleted file mode 100644
index 4920e3fae..000000000
--- a/examples/device/hid_composite_freertos/src/freertos_hook.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "FreeRTOS.h"
-#include "task.h"
-#include "common/tusb_common.h"
-
-
-void vApplicationMallocFailedHook(void)
-{
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
-{
- (void) pxTask;
- (void) pcTaskName;
-
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false, );
-}
-
-/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
- * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
- * used by the Idle task. */
-void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
-{
- /* If the buffers to be provided to the Idle task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xIdleTaskTCB;
- static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
- state will be stored. */
- *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
-
- /* Pass out the array that will be used as the Idle task's stack. */
- *ppxIdleTaskStackBuffer = uxIdleTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configMINIMAL_STACK_SIZE is specified in words, not bytes. */
- *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
-}
-
-/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
- * application must provide an implementation of vApplicationGetTimerTaskMemory()
- * to provide the memory that is used by the Timer service task. */
-void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
-{
- /* If the buffers to be provided to the Timer task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xTimerTaskTCB;
- static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Timer
- task's state will be stored. */
- *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
-
- /* Pass out the array that will be used as the Timer task's stack. */
- *ppxTimerTaskStackBuffer = uxTimerTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
- *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
-}
-
-#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
-#include "iodefine.h"
-void vApplicationSetupTimerInterrupt(void)
-{
- /* Enable CMT0 */
- unsigned short oldPRCR = SYSTEM.PRCR.WORD;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
- MSTP(CMT0) = 0;
- SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
-
- CMT0.CMCNT = 0;
- CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
- CMT0.CMCR.WORD = TU_BIT(6) | 2;
- IR(CMT0, CMI0) = 0;
- IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
- IEN(CMT0, CMI0) = 1;
- CMT.CMSTR0.BIT.STR0 = 1;
-}
-#endif
diff --git a/examples/device/midi_test/CMakeLists.txt b/examples/device/midi_test/CMakeLists.txt
index e51f14c02..f61e1b640 100644
--- a/examples/device/midi_test/CMakeLists.txt
+++ b/examples/device/midi_test/CMakeLists.txt
@@ -9,22 +9,24 @@ project(${PROJECT} C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
# Espressif has its own cmake build system
if(FAMILY STREQUAL "espressif")
return()
endif()
add_executable(${PROJECT})
+
# Example source
target_sources(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
# Example include
target_include_directories(${PROJECT} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- )
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c
index d7849a2c4..e5c47bdb2 100644
--- a/examples/device/midi_test/src/main.c
+++ b/examples/device/midi_test/src/main.c
@@ -58,8 +58,7 @@ void led_blinking_task(void);
void midi_task(void);
/*------------- MAIN -------------*/
-int main(void)
-{
+int main(void) {
board_init();
// init device stack on configured roothub port
@@ -73,8 +72,7 @@ int main(void)
board_init_after_tusb();
}
- while (1)
- {
+ while (1) {
tud_task(); // tinyusb device task
led_blinking_task();
midi_task();
@@ -86,29 +84,25 @@ int main(void)
//--------------------------------------------------------------------+
// Invoked when device is mounted
-void tud_mount_cb(void)
-{
+void tud_mount_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
-void tud_umount_cb(void)
-{
+void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
-void tud_suspend_cb(bool remote_wakeup_en)
-{
+void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
-void tud_resume_cb(void)
-{
+void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
@@ -120,8 +114,7 @@ void tud_resume_cb(void)
uint32_t note_pos = 0;
// Store example melody as an array of note values
-uint8_t note_sequence[] =
-{
+const uint8_t note_sequence[] = {
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
56,61,64,68,74,78,81,86,90,93,98,102
@@ -137,11 +130,15 @@ void midi_task(void)
// The MIDI interface always creates input and output port/jack descriptors
// regardless of these being used or not. Therefore incoming traffic should be read
// (possibly just discarded) to avoid the sender blocking in IO
- uint8_t packet[4];
- while ( tud_midi_available() ) tud_midi_packet_read(packet);
+ while (tud_midi_available()) {
+ uint8_t packet[4];
+ tud_midi_packet_read(packet);
+ }
// send note periodically
- if (board_millis() - start_ms < 286) return; // not enough time
+ if (board_millis() - start_ms < 286) {
+ return; // not enough time
+ }
start_ms += 286;
// Previous positions in the note sequence.
@@ -149,7 +146,9 @@ void midi_task(void)
// If we currently are at position 0, set the
// previous position to the last note in the sequence.
- if (previous < 0) previous = sizeof(note_sequence) - 1;
+ if (previous < 0) {
+ previous = sizeof(note_sequence) - 1;
+ }
// Send Note On for current position at full velocity (127) on channel 1.
uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 };
@@ -163,7 +162,9 @@ void midi_task(void)
note_pos++;
// If we are at the end of the sequence, start over.
- if (note_pos >= sizeof(note_sequence)) note_pos = 0;
+ if (note_pos >= sizeof(note_sequence)) {
+ note_pos = 0;
+ }
}
//--------------------------------------------------------------------+
diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c
index 3870eaaf0..384742ae8 100644
--- a/examples/device/midi_test/src/usb_descriptors.c
+++ b/examples/device/midi_test/src/usb_descriptors.c
@@ -39,8 +39,7 @@
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device =
-{
+tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
@@ -62,18 +61,13 @@ tusb_desc_device_t const desc_device =
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
-uint8_t const * tud_descriptor_device_cb(void)
-{
+uint8_t const * tud_descriptor_device_cb(void) {
return (uint8_t const *) &desc_device;
}
-
-
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
-
-enum
-{
+enum {
ITF_NUM_MIDI = 0,
ITF_NUM_MIDI_STREAMING,
ITF_NUM_TOTAL
@@ -104,8 +98,7 @@ enum
#define EPNUM_MIDI_IN 0x81
#endif
-uint8_t const desc_fs_configuration[] =
-{
+uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -114,8 +107,7 @@ uint8_t const desc_fs_configuration[] =
};
#if TUD_OPT_HIGH_SPEED
-uint8_t const desc_hs_configuration[] =
-{
+uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -127,8 +119,7 @@ uint8_t const desc_hs_configuration[] =
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
-uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
-{
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
#if TUD_OPT_HIGH_SPEED
@@ -152,8 +143,7 @@ enum {
};
// array of pointer to string descriptors
-char const *string_desc_arr[] =
-{
+char const *string_desc_arr[] = {
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
@@ -182,14 +172,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
- if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) {
+ return NULL;
+ }
const char *str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
- size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
- if ( chr_count > max_count ) chr_count = max_count;
+ const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
+ if ( chr_count > max_count ) {
+ chr_count = max_count;
+ }
// Convert ASCII string into UTF-16
for ( size_t i = 0; i < chr_count; i++ ) {
diff --git a/examples/device/midi_test_freertos/CMakeLists.txt b/examples/device/midi_test_freertos/CMakeLists.txt
new file mode 100644
index 000000000..33f3b915f
--- /dev/null
+++ b/examples/device/midi_test_freertos/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT} C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example with FreeRTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_device_example(${PROJECT} freertos)
diff --git a/examples/device/midi_test_freertos/Makefile b/examples/device/midi_test_freertos/Makefile
new file mode 100644
index 000000000..0f504bbe6
--- /dev/null
+++ b/examples/device/midi_test_freertos/Makefile
@@ -0,0 +1,40 @@
+include ../../build_system/make/make.mk
+
+FREERTOS_SRC = lib/FreeRTOS-Kernel
+FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC)
+
+INC += \
+ src \
+ $(TOP)/hw \
+ ${TOP}/${FAMILY_PATH}/FreeRTOSConfig \
+ $(TOP)/$(FREERTOS_SRC)/include \
+ $(TOP)/$(FREERTOS_PORTABLE_SRC) \
+
+# Example source
+EXAMPLE_SOURCE += \
+ src/main.c \
+ src/usb_descriptors.c \
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+# FreeRTOS source, all files in port folder
+SRC_C += \
+ $(FREERTOS_SRC)/list.c \
+ $(FREERTOS_SRC)/queue.c \
+ $(FREERTOS_SRC)/tasks.c \
+ $(FREERTOS_SRC)/timers.c \
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
+
+SRC_S += \
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
+
+# Suppress FreeRTOSConfig.h warnings
+CFLAGS_GCC += -Wno-error=redundant-decls
+
+# Suppress FreeRTOS source warnings
+CFLAGS_GCC += -Wno-error=cast-qual
+
+# FreeRTOS (lto + Os) linker issue
+LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext
+
+include ../../build_system/make/rules.mk
diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt
new file mode 100644
index 000000000..650bf355b
--- /dev/null
+++ b/examples/device/midi_test_freertos/skip.txt
@@ -0,0 +1,16 @@
+mcu:CH32V103
+mcu:CH32V20X
+mcu:CH32V307
+mcu:CXD56
+mcu:F1C100S
+mcu:GD32VF103
+mcu:MCXA15
+mcu:MKL25ZXX
+mcu:MSP430x5xx
+mcu:RP2040
+mcu:SAMD11
+mcu:SAMX7X
+mcu:VALENTYUSB_EPTRI
+mcu:RAXXX
+family:broadcom_32bit
+family:broadcom_64bit
diff --git a/examples/device/midi_test_freertos/src/CMakeLists.txt b/examples/device/midi_test_freertos/src/CMakeLists.txt
new file mode 100644
index 000000000..9bd427c89
--- /dev/null
+++ b/examples/device/midi_test_freertos/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+# This file is for ESP-IDF only
+idf_component_register(SRCS main.c usb_descriptors.c
+ INCLUDE_DIRS "."
+ REQUIRES boards tinyusb_src)
diff --git a/examples/device/midi_test_freertos/src/main.c b/examples/device/midi_test_freertos/src/main.c
new file mode 100644
index 000000000..dbe89080c
--- /dev/null
+++ b/examples/device/midi_test_freertos/src/main.c
@@ -0,0 +1,239 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+/* This MIDI example send sequence of note (on/off) repeatedly. To test on PC, you need to install
+ * synth software and midi connection management software. On
+ * - Linux (Ubuntu): install qsynth, qjackctl. Then connect TinyUSB output port to FLUID Synth input port
+ * - Windows: install MIDI-OX
+ * - MacOS: SimpleSynth
+ */
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+#if TUSB_MCU_VENDOR_ESPRESSIF
+ #define USBD_STACK_SIZE 4096
+#else
+ // Increase stack size when debug log is enabled
+ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
+#endif
+
+#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
+#define MIDI_STACK_SIZE configMINIMAL_STACK_SIZE
+
+// static task
+#if configSUPPORT_STATIC_ALLOCATION
+StackType_t blinky_stack[BLINKY_STACK_SIZE];
+StaticTask_t blinky_taskdef;
+
+StackType_t usb_device_stack[USBD_STACK_SIZE];
+StaticTask_t usb_device_taskdef;
+
+StackType_t midi_stack[MIDI_STACK_SIZE];
+StaticTask_t midi_taskdef;
+#endif
+
+/* Blink pattern
+ * - 250 ms : device not mounted
+ * - 1000 ms : device mounted
+ * - 2500 ms : device is suspended
+ */
+enum {
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+
+void usb_device_task(void *param);
+void led_blinking_task(void* param);
+void midi_task(void* param);
+
+//--------------------------------------------------------------------+
+// Main
+//--------------------------------------------------------------------+
+int main(void) {
+ board_init();
+
+#if configSUPPORT_STATIC_ALLOCATION
+ xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
+ xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
+ xTaskCreateStatic(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, midi_stack, &midi_taskdef);
+#else
+ xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
+ xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
+ xTaskCreate(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
+#endif
+
+#if !TUSB_MCU_VENDOR_ESPRESSIF
+ // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
+ vTaskStartScheduler();
+#endif
+
+ return 0;
+}
+
+#if TUSB_MCU_VENDOR_ESPRESSIF
+void app_main(void) {
+ main();
+}
+#endif
+
+// USB Device Driver task
+// This top level thread process all usb events and invoke callbacks
+void usb_device_task(void *param) {
+ (void) param;
+
+ // init device stack on configured roothub port
+ // This should be called after scheduler/kernel is started.
+ // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API.
+ tusb_rhport_init_t dev_init = {
+ .role = TUSB_ROLE_DEVICE,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_TUD_RHPORT, &dev_init);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ // RTOS forever loop
+ while (1) {
+ // put this thread to waiting state until there is new events
+ tud_task();
+ }
+}
+
+//--------------------------------------------------------------------+
+// Device callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device is mounted
+void tud_mount_cb(void) {
+ blink_interval_ms = BLINK_MOUNTED;
+}
+
+// Invoked when device is unmounted
+void tud_umount_cb(void) {
+ blink_interval_ms = BLINK_NOT_MOUNTED;
+}
+
+// Invoked when usb bus is suspended
+// remote_wakeup_en : if host allow us to perform remote wakeup
+// Within 7ms, device must draw an average of current less than 2.5 mA from bus
+void tud_suspend_cb(bool remote_wakeup_en) {
+ (void) remote_wakeup_en;
+ blink_interval_ms = BLINK_SUSPENDED;
+}
+
+// Invoked when usb bus is resumed
+void tud_resume_cb(void) {
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
+}
+
+//--------------------------------------------------------------------+
+// MIDI Task
+//--------------------------------------------------------------------+
+
+// Store example melody as an array of note values
+const uint8_t note_sequence[] = {
+ 74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
+ 74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
+ 56,61,64,68,74,78,81,86,90,93,98,102
+};
+
+void midi_task(void* param) {
+ (void) param;
+
+ const uint8_t cable_num = 0; // MIDI jack associated with USB endpoint
+ const uint8_t channel = 0; // 0 for channel 1
+
+ // Variable that holds the current position in the sequence.
+ uint32_t note_pos = 0;
+
+ while (1) {
+ // send note periodically
+ vTaskDelay(286 / portTICK_PERIOD_MS);
+
+ // Previous positions in the note sequence.
+ int previous = (int) (note_pos - 1);
+
+ // If we currently are at position 0, set the
+ // previous position to the last note in the sequence.
+ if (previous < 0) {
+ previous = sizeof(note_sequence) - 1;
+ }
+
+ // Send Note On for current position at full velocity (127) on channel 1.
+ uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 };
+ tud_midi_stream_write(cable_num, note_on, 3);
+
+ // Send Note Off for previous note.
+ uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0};
+ tud_midi_stream_write(cable_num, note_off, 3);
+
+ // Increment position
+ note_pos++;
+
+ // If we are at the end of the sequence, start over.
+ if (note_pos >= sizeof(note_sequence)) {
+ note_pos = 0;
+ }
+
+ // The MIDI interface always creates input and output port/jack descriptors
+ // regardless of these being used or not. Therefore incoming traffic should be read
+ // (possibly just discarded) to avoid the sender blocking in IO
+ while (tud_midi_available()) {
+ uint8_t packet[4];
+ tud_midi_packet_read(packet);
+ }
+ }
+}
+
+//--------------------------------------------------------------------+
+// BLINKING TASK
+//--------------------------------------------------------------------+
+void led_blinking_task(void* param) {
+ (void) param;
+ static uint32_t start_ms = 0;
+ static bool led_state = false;
+
+ while (1) {
+ // Blink every interval ms
+ vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS);
+ start_ms += blink_interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state; // toggle
+ }
+}
diff --git a/examples/device/midi_test_freertos/src/tusb_config.h b/examples/device/midi_test_freertos/src/tusb_config.h
new file mode 100644
index 000000000..0ffdc37fb
--- /dev/null
+++ b/examples/device/midi_test_freertos/src/tusb_config.h
@@ -0,0 +1,108 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Board Specific Configuration
+//--------------------------------------------------------------------+
+
+// RHPort number used for device can be defined by board.mk, default to port 0
+#ifndef BOARD_TUD_RHPORT
+#define BOARD_TUD_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUD_MAX_SPEED
+#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_FREERTOS
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+// Enable Device stack
+#define CFG_TUD_ENABLED 1
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
+#endif
+
+#ifndef CFG_TUSB_MEM_ALIGN
+#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#ifndef CFG_TUD_ENDPOINT0_SIZE
+#define CFG_TUD_ENDPOINT0_SIZE 64
+#endif
+
+//------------- CLASS -------------//
+#define CFG_TUD_CDC 0
+#define CFG_TUD_MSC 0
+#define CFG_TUD_HID 0
+#define CFG_TUD_MIDI 1
+#define CFG_TUD_VENDOR 0
+
+// MIDI FIFO size of TX and RX
+#define CFG_TUD_MIDI_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/examples/device/midi_test_freertos/src/usb_descriptors.c b/examples/device/midi_test_freertos/src/usb_descriptors.c
new file mode 100644
index 000000000..384742ae8
--- /dev/null
+++ b/examples/device/midi_test_freertos/src/usb_descriptors.c
@@ -0,0 +1,199 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ * [MSB] HID | MSC | CDC [LSB]
+ */
+#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
+#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
+ _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
+
+//--------------------------------------------------------------------+
+// Device Descriptors
+//--------------------------------------------------------------------+
+tusb_desc_device_t const desc_device = {
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+
+ .idVendor = 0xCafe,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+// Invoked when received GET DEVICE DESCRIPTOR
+// Application return pointer to descriptor
+uint8_t const * tud_descriptor_device_cb(void) {
+ return (uint8_t const *) &desc_device;
+}
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+enum {
+ ITF_NUM_MIDI = 0,
+ ITF_NUM_MIDI_STREAMING,
+ ITF_NUM_TOTAL
+};
+
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MIDI_DESC_LEN)
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+ // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+ // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
+ #define EPNUM_MIDI_OUT 0x02
+ #define EPNUM_MIDI_IN 0x82
+
+#elif CFG_TUSB_MCU == OPT_MCU_CXD56
+ // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
+ // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
+ #define EPNUM_MIDI_OUT 0x02
+ #define EPNUM_MIDI_IN 0x81
+
+#elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY)
+ // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h
+ // e.g EP1 OUT & EP1 IN cannot exist together
+ #define EPNUM_MIDI_OUT 0x01
+ #define EPNUM_MIDI_IN 0x82
+
+#else
+ #define EPNUM_MIDI_OUT 0x01
+ #define EPNUM_MIDI_IN 0x81
+#endif
+
+uint8_t const desc_fs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+ // Interface number, string index, EP Out & EP In address, EP size
+ TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_IN), 64)
+};
+
+#if TUD_OPT_HIGH_SPEED
+uint8_t const desc_hs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+ // Interface number, string index, EP Out & EP In address, EP size
+ TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_IN), 512)
+};
+#endif
+
+// Invoked when received GET CONFIGURATION DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
+ (void) index; // for multiple configurations
+
+#if TUD_OPT_HIGH_SPEED
+ // Although we are highspeed, host may be fullspeed.
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
+#else
+ return desc_fs_configuration;
+#endif
+}
+
+//--------------------------------------------------------------------+
+// String Descriptors
+//--------------------------------------------------------------------+
+
+// String Descriptor Index
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
+};
+
+// array of pointer to string descriptors
+char const *string_desc_arr[] = {
+ (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB Device", // 2: Product
+ NULL, // 3: Serials will use unique ID if possible
+};
+
+static uint16_t _desc_str[32 + 1];
+
+// Invoked when received GET STRING DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+ (void) langid;
+ size_t chr_count;
+
+ switch ( index ) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
+
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
+
+ default:
+ // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
+
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) {
+ return NULL;
+ }
+
+ const char *str = string_desc_arr[index];
+
+ // Cap at max char
+ chr_count = strlen(str);
+ const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
+ if ( chr_count > max_count ) {
+ chr_count = max_count;
+ }
+
+ // Convert ASCII string into UTF-16
+ for ( size_t i = 0; i < chr_count; i++ ) {
+ _desc_str[1 + i] = str[i];
+ }
+ break;
+ }
+
+ // first byte is length (including header), second byte is string type
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
+
+ return _desc_str;
+}
diff --git a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt
index 2e95a18e0..b4004f8d7 100644
--- a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt
+++ b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt
@@ -20,7 +20,6 @@ add_executable(${PROJECT})
# Example source
target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
- ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile
index bf4725f47..67fbb9af3 100644
--- a/examples/host/cdc_msc_hid_freertos/Makefile
+++ b/examples/host/cdc_msc_hid_freertos/Makefile
@@ -13,7 +13,6 @@ INC += \
# Example source
EXAMPLE_SOURCE = \
src/cdc_app.c \
- src/freertos_hook.c \
src/hid_app.c \
src/main.c \
src/msc_app.c \
diff --git a/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c b/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c
deleted file mode 100644
index 07d159fd5..000000000
--- a/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "FreeRTOS.h"
-#include "task.h"
-#include "common/tusb_common.h"
-
-void vApplicationMallocFailedHook(void) {
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false,);
-}
-
-void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) {
- (void) pxTask;
- (void) pcTaskName;
-
- taskDISABLE_INTERRUPTS();
- TU_ASSERT(false,);
-}
-
-/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
- * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
- * used by the Idle task. */
-void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer,
- uint32_t *pulIdleTaskStackSize) {
- /* If the buffers to be provided to the Idle task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xIdleTaskTCB;
- static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
- state will be stored. */
- *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
-
- /* Pass out the array that will be used as the Idle task's stack. */
- *ppxIdleTaskStackBuffer = uxIdleTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configMINIMAL_STACK_SIZE is specified in words, not bytes. */
- *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
-}
-
-/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
- * application must provide an implementation of vApplicationGetTimerTaskMemory()
- * to provide the memory that is used by the Timer service task. */
-void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer,
- uint32_t *pulTimerTaskStackSize) {
- /* If the buffers to be provided to the Timer task are declared inside this
- * function then they must be declared static - otherwise they will be allocated on
- * the stack and so not exists after this function exits. */
- static StaticTask_t xTimerTaskTCB;
- static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
-
- /* Pass out a pointer to the StaticTask_t structure in which the Timer
- task's state will be stored. */
- *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
-
- /* Pass out the array that will be used as the Timer task's stack. */
- *ppxTimerTaskStackBuffer = uxTimerTaskStack;
-
- /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
- Note that, as the array is necessarily of type StackType_t,
- configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
- *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
-}
-
-#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
-#include "iodefine.h"
-void vApplicationSetupTimerInterrupt(void)
-{
- /* Enable CMT0 */
- SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
- MSTP(CMT0) = 0;
- SYSTEM.PRCR.WORD = (0xA5u<<8);
-
- CMT0.CMCNT = 0;
- CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
- CMT0.CMCR.WORD = TU_BIT(6) | 2;
- IR(CMT0, CMI0) = 0;
- IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
- IEN(CMT0, CMI0) = 1;
- CMT.CMSTR0.BIT.STR0 = 1;
-}
-#endif
diff --git a/hw/bsp/board.c b/hw/bsp/board.c
index 6d9488431..e3a4be461 100644
--- a/hw/bsp/board.c
+++ b/hw/bsp/board.c
@@ -139,3 +139,91 @@ int board_getchar(void) {
uint32_t tusb_time_millis_api(void) {
return board_millis();
}
+
+//--------------------------------------------------------------------
+// FreeRTOS hooks
+//--------------------------------------------------------------------
+#if CFG_TUSB_OS == OPT_OS_FREERTOS && !TUSB_MCU_VENDOR_ESPRESSIF
+#include "FreeRTOS.h"
+#include "task.h"
+
+void vApplicationMallocFailedHook(void) {
+ taskDISABLE_INTERRUPTS();
+ TU_ASSERT(false, );
+}
+
+void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) {
+ (void) pxTask;
+ (void) pcTaskName;
+
+ taskDISABLE_INTERRUPTS();
+ TU_ASSERT(false, );
+}
+
+/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
+ * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
+ * used by the Idle task. */
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) {
+ /* If the buffers to be provided to the Idle task are declared inside this
+ * function then they must be declared static - otherwise they will be allocated on
+ * the stack and so not exists after this function exits. */
+ static StaticTask_t xIdleTaskTCB;
+ static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
+ state will be stored. */
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ /* Pass out the array that will be used as the Idle task's stack. */
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+
+/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
+ * application must provide an implementation of vApplicationGetTimerTaskMemory()
+ * to provide the memory that is used by the Timer service task. */
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) {
+ /* If the buffers to be provided to the Timer task are declared inside this
+ * function then they must be declared static - otherwise they will be allocated on
+ * the stack and so not exists after this function exits. */
+ static StaticTask_t xTimerTaskTCB;
+ static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Timer
+ task's state will be stored. */
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+
+ /* Pass out the array that will be used as the Timer task's stack. */
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}
+
+#if CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X
+#include "iodefine.h"
+void vApplicationSetupTimerInterrupt(void) {
+ /* Enable CMT0 */
+ unsigned short oldPRCR = SYSTEM.PRCR.WORD;
+ SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
+ MSTP(CMT0) = 0;
+ SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR;
+
+ CMT0.CMCNT = 0;
+ CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128);
+ CMT0.CMCR.WORD = TU_BIT(6) | 2;
+ IR(CMT0, CMI0) = 0;
+ IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY;
+ IEN(CMT0, CMI0) = 1;
+ CMT.CMSTR0.BIT.STR0 = 1;
+}
+#endif
+
+
+#endif
diff --git a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
index 0022f0d2d..e57f7c51f 100644
--- a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
+++ b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
@@ -33,7 +33,7 @@
// #define NEOPIXEL_PIN 48
-#define BUTTON_PIN 0
+#define BUTTON_PIN 35
#define BUTTON_STATE_ACTIVE 0
// For CI hardware test, to test both device and host on the same HS port with help of
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index 57fa63261..3f2872a30 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -553,6 +553,7 @@ function(family_flash_teensy TARGET)
add_custom_target(${TARGET}-teensy
DEPENDS ${TARGET}
+ COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.hex
COMMAND ${TEENSY_CLI} --mcu=${TEENSY_MCU} -w -s $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.hex
)
endfunction()
diff --git a/hw/bsp/kinetis_k/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/kinetis_k/FreeRTOSConfig/FreeRTOSConfig.h
index ed46508a4..76004241a 100644
--- a/hw/bsp/kinetis_k/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/kinetis_k/FreeRTOSConfig/FreeRTOSConfig.h
@@ -129,8 +129,6 @@
}\
}\
} while(0)
-#else
- #define configASSERT( x )
#endif
/* FreeRTOS hooks to NVIC vectors */
diff --git a/hw/bsp/kinetis_k/boards/teensy_35/board.cmake b/hw/bsp/kinetis_k/boards/teensy_35/board.cmake
index bd253d996..ae4409e12 100644
--- a/hw/bsp/kinetis_k/boards/teensy_35/board.cmake
+++ b/hw/bsp/kinetis_k/boards/teensy_35/board.cmake
@@ -2,7 +2,6 @@ set(MCU_VARIANT MK64F12)
set(JLINK_DEVICE MK64FX512xxx12)
set(TEENSY_MCU TEENSY35)
-set(PYOCD_TARGET k64f)
set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/MK64FX512xxx12_flash.ld)
diff --git a/hw/bsp/kinetis_k/family.cmake b/hw/bsp/kinetis_k/family.cmake
index 771754ebd..c30268629 100644
--- a/hw/bsp/kinetis_k/family.cmake
+++ b/hw/bsp/kinetis_k/family.cmake
@@ -111,7 +111,6 @@ function(family_configure_example TARGET RTOS)
family_flash_jlink(${TARGET})
if (DEFINED TEENSY_MCU)
- family_add_bin_hex(${TARGET})
family_flash_teensy(${TARGET})
endif ()
endfunction()
diff --git a/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h
index e6604d360..0225abe8d 100644
--- a/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h
@@ -85,6 +85,7 @@
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
diff --git a/hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h
index 27b2d76f5..0e0721674 100644
--- a/hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h
@@ -94,6 +94,7 @@
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
diff --git a/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h
index e6604d360..3bc226667 100644
--- a/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/lpc51/FreeRTOSConfig/FreeRTOSConfig.h
@@ -85,6 +85,7 @@
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
@@ -122,7 +123,8 @@
/* Define to trap errors during development. */
// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7
-#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
+#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \
+ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
#define configASSERT(_exp) \
do {\
if ( !(_exp) ) { \
@@ -133,8 +135,6 @@
}\
}\
} while(0)
-#else
- #define configASSERT( x )
#endif
/* FreeRTOS hooks to NVIC vectors */
diff --git a/hw/bsp/rx/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/rx/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..edf0a8433
--- /dev/null
+++ b/hw/bsp/rx/FreeRTOSConfig/FreeRTOSConfig.h
@@ -0,0 +1,177 @@
+/*
+ * FreeRTOS Kernel V10.0.0
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. If you wish to use our Amazon
+ * FreeRTOS name, please do so in a fair use way that does not cause confusion.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+// skip if included from IAR assembler
+#ifndef __IASMARM__
+// FIXME cause redundant-decls warnings
+extern uint32_t SystemCoreClock;
+#endif
+
+/* Cortex M23/M33 port configuration. */
+#define configENABLE_MPU 0
+#define configENABLE_FPU 0
+#define configENABLE_TRUSTZONE 0
+#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
+#define configRUN_FREERTOS_SECURE_ONLY 1
+
+#define configUSE_PREEMPTION 1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#define configCPU_CLOCK_HZ SystemCoreClock
+#define configTICK_RATE_HZ ( 1000 )
+#define configMAX_PRIORITIES ( 5 )
+#define configMINIMAL_STACK_SIZE ( 128 )
+#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
+#define configMAX_TASK_NAME_LEN 16
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configQUEUE_REGISTRY_SIZE 4
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 0
+#define configUSE_NEWLIB_REENTRANT 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
+#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
+
+#define configSUPPORT_STATIC_ALLOCATION 1
+#define configSUPPORT_DYNAMIC_ALLOCATION 0
+
+/* Hook function related definitions. */
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TRACE_FACILITY 1 // legacy trace
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES 2
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
+#define configTIMER_QUEUE_LENGTH 32
+#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet 0
+#define INCLUDE_uxTaskPriorityGet 0
+#define INCLUDE_vTaskDelete 0
+#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
+#define INCLUDE_xResumeFromISR 0
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 0
+#define INCLUDE_xTaskGetCurrentTaskHandle 0
+#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#define INCLUDE_pcTaskGetTaskName 0
+#define INCLUDE_eTaskGetState 0
+#define INCLUDE_xEventGroupSetBitFromISR 0
+#define INCLUDE_xTimerPendFunctionCall 0
+
+#ifdef __RX__
+/* Renesas RX series */
+#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
+#define vTickISR INT_Excep_CMT0_CMI0
+#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
+#define configKERNEL_INTERRUPT_PRIORITY 1
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
+
+#else
+
+/* FreeRTOS hooks to NVIC vectors */
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+#define vPortSVCHandler SVC_Handler
+
+//--------------------------------------------------------------------+
+// Interrupt nesting behavior configuration.
+//--------------------------------------------------------------------+
+#if defined(__NVIC_PRIO_BITS)
+ // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+
+#elif defined(__ECLIC_INTCTLBITS)
+ // RISC-V Bumblebee core from nuclei
+ #define configPRIO_BITS __ECLIC_INTCTLBITS
+
+#elif defined(__IASMARM__)
+ // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
+ // Therefore we will hard coded it to minimum value of 2 to get pass ci build.
+ // IAR user must update this to correct value of the target MCU
+ #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
+ #define configPRIO_BITS 2
+
+#else
+ #error "FreeRTOS configPRIO_BITS to be defined"
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1)
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+#endif
+
+#endif /* __FREERTOS_CONFIG__H */
diff --git a/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h
index 6a9c90a4a..c621b48bb 100644
--- a/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h
@@ -119,8 +119,9 @@
/* Define to trap errors during development. */
// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7
-#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
-#define configASSERT(_exp) \
+#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \
+ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
+ #define configASSERT(_exp) \
do {\
if ( !(_exp) ) { \
volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \
@@ -130,8 +131,6 @@
}\
}\
} while(0)
-#else
-#define configASSERT( x )
#endif
/* FreeRTOS hooks to NVIC vectors */
diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c
index 60afb8615..451d5405b 100644
--- a/lib/networking/rndis_reports.c
+++ b/lib/networking/rndis_reports.c
@@ -43,8 +43,6 @@ static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 };
static uint32_t oid_packet_filter = 0x0000000;
static rndis_state_t rndis_state;
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
-
static const uint32_t OIDSupportedList[] =
{
OID_GEN_SUPPORTED_LIST,
@@ -76,8 +74,8 @@ static const uint32_t OIDSupportedList[] =
static void *encapsulated_buffer;
-static void rndis_report(void)
-{
+static void rndis_report(void) {
+ uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
netd_report(ndis_report, sizeof(ndis_report));
}
diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c
index a79908627..5e533cf35 100755
--- a/src/class/bth/bth_device.c
+++ b/src/class/bth/bth_device.c
@@ -37,8 +37,7 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
uint8_t itf_num;
uint8_t ep_ev;
uint8_t ep_acl_in;
@@ -49,17 +48,18 @@ typedef struct
// Previous amount of bytes sent when issuing ZLP
uint32_t prev_xferred_bytes;
-
- // Endpoint Transfer buffer
- CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd;
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE];
-
} btd_interface_t;
+typedef struct {
+ TUD_EPBUF_DEF(epout_buf, CFG_TUD_BTH_DATA_EPSIZE);
+ TUD_EPBUF_TYPE_DEF(hci_cmd, bt_hci_cmd_t);
+} btd_epbuf_t;
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUD_MEM_SECTION btd_interface_t _btd_itf;
+static btd_interface_t _btd_itf;
+CFG_TUD_MEM_SECTION static btd_epbuf_t _btd_epbuf;
static bool bt_tx_data(uint8_t ep, void *data, uint16_t len)
{
@@ -152,7 +152,7 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(desc_ep));
// Prepare for incoming data from host
- TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
+ TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
drv_len = hci_itf_size;
@@ -243,14 +243,16 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
}
else return false;
- return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd));
+ return tud_control_xfer(rhport, request, &_btd_epbuf.hci_cmd, sizeof(bt_hci_cmd_t));
}
else if ( stage == CONTROL_STAGE_DATA )
{
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd)));
+ if (tud_bt_hci_cmd_cb) {
+ tud_bt_hci_cmd_cb(&_btd_epbuf.hci_cmd, tu_min16(request->wLength, sizeof(bt_hci_cmd_t)));
+ }
}
return true;
@@ -261,10 +263,10 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
// received new data from host
if (ep_addr == _btd_itf.ep_acl_out)
{
- if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes);
+ if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_epbuf.epout_buf, xferred_bytes);
// prepare for next data
- TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE));
+ TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE));
}
else if (ep_addr == _btd_itf.ep_ev)
{
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index ebc408f5a..efb672201 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -67,22 +67,27 @@ typedef struct {
OSAL_MUTEX_DEF(rx_ff_mutex);
OSAL_MUTEX_DEF(tx_ff_mutex);
-
- // Endpoint Transfer buffer
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE];
} cdcd_interface_t;
#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
+typedef struct {
+ TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
+ TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
+} cdcd_epbuf_t;
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
+
static tud_cdc_configure_fifo_t _cdcd_fifo_cfg;
-static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
- uint8_t const rhport = 0;
+static bool _prep_out_transaction(uint8_t itf) {
+ const uint8_t rhport = 0;
+ cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
+ cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Skip if usb is not ready yet
TU_VERIFY(tud_ready() && p_cdc->ep_out);
@@ -93,7 +98,7 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// TODO Actually we can still carry out the transfer, keeping count of received bytes
// and slowly move it to the FIFO when read().
// This pre-check reduces endpoint claiming
- TU_VERIFY(available >= sizeof(p_cdc->epout_buf));
+ TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE);
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out));
@@ -101,9 +106,9 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_cdc->rx_ff);
- if ( available >= sizeof(p_cdc->epout_buf) ) {
- return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
- }else {
+ if (available >= CFG_TUD_CDC_EP_BUFSIZE) {
+ return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE);
+ } else {
// Release endpoint since we don't make any transfer
usbd_edpt_release(rhport, p_cdc->ep_out);
return false;
@@ -114,7 +119,7 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) {
+bool tud_cdc_configure_fifo(const tud_cdc_configure_fifo_t* cfg) {
TU_VERIFY(cfg);
_cdcd_fifo_cfg = (*cfg);
return true;
@@ -151,7 +156,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) {
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
- _prep_out_transaction(p_cdc);
+ _prep_out_transaction(itf);
return num_read;
}
@@ -162,13 +167,13 @@ bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) {
void tud_cdc_n_read_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
tu_fifo_clear(&p_cdc->rx_ff);
- _prep_out_transaction(p_cdc);
+ _prep_out_transaction(itf);
}
//--------------------------------------------------------------------+
// WRITE API
//--------------------------------------------------------------------+
-uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
+uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
@@ -186,23 +191,26 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
uint32_t tud_cdc_n_write_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
+ cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Skip if usb is not ready yet
TU_VERIFY(tud_ready(), 0);
// No data to send
- if (!tu_fifo_count(&p_cdc->tx_ff)) return 0;
+ if (!tu_fifo_count(&p_cdc->tx_ff)) {
+ return 0;
+ }
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
// Claim the endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0);
// Pull data from FIFO
- uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
+ const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE);
if (count) {
- TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0);
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_epbuf->epin, count), 0);
return count;
} else {
// Release endpoint since we don't make any transfer
@@ -286,32 +294,37 @@ void cdcd_reset(uint8_t rhport) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
- if (!_cdcd_fifo_cfg.rx_persistent) tu_fifo_clear(&p_cdc->rx_ff);
- if (!_cdcd_fifo_cfg.tx_persistent) tu_fifo_clear(&p_cdc->tx_ff);
+ if (!_cdcd_fifo_cfg.rx_persistent) {
+ tu_fifo_clear(&p_cdc->rx_ff);
+ }
+ if (!_cdcd_fifo_cfg.tx_persistent) {
+ tu_fifo_clear(&p_cdc->tx_ff);
+ }
tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
}
}
-uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
+uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) {
// Only support ACM subclass
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
// Find available interface
- cdcd_interface_t* p_cdc = NULL;
- for (uint8_t cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
- if (_cdcd_itf[cdc_id].ep_in == 0) {
- p_cdc = &_cdcd_itf[cdc_id];
+ cdcd_interface_t* p_cdc;
+ uint8_t cdc_id;
+ for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
+ p_cdc = &_cdcd_itf[cdc_id];
+ if (p_cdc->ep_in == 0) {
break;
}
}
- TU_ASSERT(p_cdc, 0);
+ TU_ASSERT(cdc_id < CFG_TUD_CDC, 0);
//------------- Control Interface -------------//
p_cdc->itf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
- uint8_t const* p_desc = tu_desc_next(itf_desc);
+ const uint8_t* p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
@@ -321,7 +334,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
// notification endpoint
- tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
+ const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc;
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
p_cdc->ep_notif = desc_ep->bEndpointAddress;
@@ -332,7 +345,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
//------------- Data Interface (if any) -------------//
if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
- (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) {
+ (TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) {
// next to endpoint descriptor
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
@@ -344,7 +357,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
}
// Prepare for incoming data
- _prep_out_transaction(p_cdc);
+ _prep_out_transaction(cdc_id);
return drv_len;
}
@@ -352,19 +365,21 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
+bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- uint8_t itf = 0;
- cdcd_interface_t* p_cdc = _cdcd_itf;
+ uint8_t itf;
+ cdcd_interface_t* p_cdc;
// Identify which interface to use
- for (;; itf++, p_cdc++) {
- if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
-
- if (p_cdc->itf_num == request->wIndex) break;
+ for (itf = 0; itf < CFG_TUD_CDC; itf++) {
+ p_cdc = &_cdcd_itf[itf];
+ if (p_cdc->itf_num == request->wIndex) {
+ break;
+ }
}
+ TU_VERIFY(itf < CFG_TUD_CDC);
switch (request->bRequest) {
case CDC_REQUEST_SET_LINE_CODING:
@@ -372,7 +387,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
} else if (stage == CONTROL_STAGE_ACK) {
- if (tud_cdc_line_coding_cb) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
+ if (tud_cdc_line_coding_cb) {
+ tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
+ }
}
break;
@@ -403,7 +420,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
// Invoke callback
- if (tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts);
+ if (tud_cdc_line_state_cb) {
+ tud_cdc_line_state_cb(itf, dtr, rts);
+ }
}
break;
@@ -412,7 +431,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
TU_LOG_DRV(" Send Break\r\n");
- if (tud_cdc_send_break_cb) tud_cdc_send_break_cb(itf, request->wValue);
+ if (tud_cdc_send_break_cb) {
+ tud_cdc_send_break_cb(itf, request->wValue);
+ }
}
break;
@@ -432,28 +453,33 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Identify which interface to use
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
p_cdc = &_cdcd_itf[itf];
- if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) break;
+ if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) {
+ break;
+ }
}
TU_ASSERT(itf < CFG_TUD_CDC);
+ cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Received new data
if (ep_addr == p_cdc->ep_out) {
- tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes);
+ tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes);
// Check for wanted char and invoke callback if needed
if (tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1)) {
for (uint32_t i = 0; i < xferred_bytes; i++) {
- if ((p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
+ if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
}
}
}
// invoke receive callback (if there is still data)
- if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf);
+ if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) {
+ tud_cdc_rx_cb(itf);
+ }
// prepare for OUT transaction
- _prep_out_transaction(p_cdc);
+ _prep_out_transaction(itf);
}
// Data sent to host, we continue to fetch from tx fifo to send.
@@ -461,7 +487,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Though maybe the baudrate is not really important !!!
if (ep_addr == p_cdc->ep_in) {
// invoke transmit callback to possibly refill tx fifo
- if (tud_cdc_tx_complete_cb) tud_cdc_tx_complete_cb(itf);
+ if (tud_cdc_tx_complete_cb) {
+ tud_cdc_tx_complete_cb(itf);
+ }
if (0 == tud_cdc_n_write_flush(itf)) {
// If there is no data left, a ZLP should be sent if
diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c
index 71e7ac2b3..d9e2d3f2f 100644
--- a/src/class/dfu/dfu_device.c
+++ b/src/class/dfu/dfu_device.c
@@ -47,8 +47,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
uint8_t attrs;
uint8_t alt;
@@ -58,69 +57,65 @@ typedef struct
bool flashing_in_progress;
uint16_t block;
uint16_t length;
-
- CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE];
} dfu_state_ctx_t;
// Only a single dfu state is allowed
-CFG_TUD_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx;
+static dfu_state_ctx_t _dfu_ctx;
+
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(transfer_buf, CFG_TUD_DFU_XFER_BUFSIZE);
+} _dfu_epbuf;
-static void reset_state(void)
-{
+static void reset_state(void) {
_dfu_ctx.state = DFU_IDLE;
_dfu_ctx.status = DFU_STATUS_OK;
_dfu_ctx.flashing_in_progress = false;
}
-static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout);
-static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
-static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
+static bool reply_getstatus(uint8_t rhport, const tusb_control_request_t* request, dfu_state_t state, dfu_status_t status, uint32_t timeout);
+static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request);
+static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request);
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= 2
-tu_static tu_lookup_entry_t const _dfu_request_lookup[] =
-{
- { .key = DFU_REQUEST_DETACH , .data = "DETACH" },
- { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
- { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
- { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" },
- { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" },
- { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
- { .key = DFU_REQUEST_ABORT , .data = "ABORT" },
+tu_static tu_lookup_entry_t const _dfu_request_lookup[] = {
+ { .key = DFU_REQUEST_DETACH , .data = "DETACH" },
+ { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
+ { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
+ { .key = DFU_REQUEST_GETSTATUS, .data = "GETSTATUS" },
+ { .key = DFU_REQUEST_CLRSTATUS, .data = "CLRSTATUS" },
+ { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
+ { .key = DFU_REQUEST_ABORT , .data = "ABORT" },
};
-tu_static tu_lookup_table_t const _dfu_request_table =
-{
+tu_static tu_lookup_table_t const _dfu_request_table = {
.count = TU_ARRAY_SIZE(_dfu_request_lookup),
.items = _dfu_request_lookup
};
-tu_static tu_lookup_entry_t const _dfu_state_lookup[] =
-{
- { .key = APP_IDLE , .data = "APP_IDLE" },
- { .key = APP_DETACH , .data = "APP_DETACH" },
- { .key = DFU_IDLE , .data = "IDLE" },
- { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" },
- { .key = DFU_DNBUSY , .data = "DNBUSY" },
- { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" },
- { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" },
- { .key = DFU_MANIFEST , .data = "MANIFEST" },
- { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" },
- { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" },
- { .key = DFU_ERROR , .data = "ERROR" },
+tu_static tu_lookup_entry_t const _dfu_state_lookup[] = {
+ { .key = APP_IDLE , .data = "APP_IDLE" },
+ { .key = APP_DETACH , .data = "APP_DETACH" },
+ { .key = DFU_IDLE , .data = "IDLE" },
+ { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" },
+ { .key = DFU_DNBUSY , .data = "DNBUSY" },
+ { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" },
+ { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" },
+ { .key = DFU_MANIFEST , .data = "MANIFEST" },
+ { .key = DFU_MANIFEST_WAIT_RESET, .data = "MANIFEST_WAIT_RESET" },
+ { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" },
+ { .key = DFU_ERROR , .data = "ERROR" },
};
-tu_static tu_lookup_table_t const _dfu_state_table =
-{
+tu_static tu_lookup_table_t const _dfu_state_table = {
.count = TU_ARRAY_SIZE(_dfu_state_lookup),
.items = _dfu_state_lookup
};
-tu_static tu_lookup_entry_t const _dfu_status_lookup[] =
-{
+tu_static tu_lookup_entry_t const _dfu_status_lookup[] = {
{ .key = DFU_STATUS_OK , .data = "OK" },
{ .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" },
{ .key = DFU_STATUS_ERR_FILE , .data = "errFILE" },
@@ -139,8 +134,7 @@ tu_static tu_lookup_entry_t const _dfu_status_lookup[] =
{ .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" },
};
-tu_static tu_lookup_table_t const _dfu_status_table =
-{
+tu_static tu_lookup_table_t const _dfu_status_table = {
.count = TU_ARRAY_SIZE(_dfu_status_lookup),
.items = _dfu_status_lookup
};
@@ -150,13 +144,10 @@ tu_static tu_lookup_table_t const _dfu_status_table =
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void dfu_moded_reset(uint8_t rhport)
-{
+void dfu_moded_reset(uint8_t rhport) {
(void) rhport;
-
_dfu_ctx.attrs = 0;
_dfu_ctx.alt = 0;
-
reset_state();
}
@@ -168,19 +159,17 @@ bool dfu_moded_deinit(void) {
return true;
}
-uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
-{
+uint16_t dfu_moded_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) {
(void) rhport;
//------------- Interface (with Alt) descriptor -------------//
- uint8_t const itf_num = itf_desc->bInterfaceNumber;
+ const uint8_t itf_num = itf_desc->bInterfaceNumber;
uint8_t alt_count = 0;
uint16_t drv_len = 0;
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0);
- while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
- {
+ while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) {
TU_ASSERT(max_len > drv_len, 0);
// Alternate must have the same interface number
@@ -191,18 +180,18 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
alt_count++;
drv_len += tu_desc_len(itf_desc);
- itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc);
+ itf_desc = (const tusb_desc_interface_t*) tu_desc_next(itf_desc);
}
//------------- DFU Functional descriptor -------------//
- tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc;
+ const tusb_desc_dfu_functional_t*func_desc = (const tusb_desc_dfu_functional_t*) itf_desc;
TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0);
drv_len += sizeof(tusb_desc_dfu_functional_t);
_dfu_ctx.attrs = func_desc->bAttributes;
// CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR
- uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) );
+ const uint16_t transfer_size = tu_le16toh( tu_unaligned_read16((const uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) );
TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len);
return drv_len;
@@ -211,99 +200,85 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
+bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
-
TU_LOG_DRV(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status));
- if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
- {
+ if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
// Standard request include GET/SET_INTERFACE
- switch ( request->bRequest )
- {
+ switch (request->bRequest) {
case TUSB_REQ_SET_INTERFACE:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
// Switch Alt interface and reset state machine
- _dfu_ctx.alt = (uint8_t) request->wValue;
+ _dfu_ctx.alt = (uint8_t)request->wValue;
reset_state();
return tud_control_status(rhport, request);
}
- break;
+ break;
case TUSB_REQ_GET_INTERFACE:
- if(stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1);
}
- break;
+ break;
// unsupported request
default: return false;
}
- }
- else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS )
- {
+ } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
TU_LOG_DRV(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
// Class request
- switch ( request->bRequest )
- {
+ switch (request->bRequest) {
case DFU_REQUEST_DETACH:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
tud_control_status(rhport, request);
+ } else if (stage == CONTROL_STAGE_ACK) {
+ if (tud_dfu_detach_cb) {
+ tud_dfu_detach_cb();
+ }
}
- else if ( stage == CONTROL_STAGE_ACK )
- {
- if ( tud_dfu_detach_cb ) tud_dfu_detach_cb();
- }
- break;
+ break;
case DFU_REQUEST_CLRSTATUS:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
reset_state();
tud_control_status(rhport, request);
}
- break;
+ break;
case DFU_REQUEST_GETSTATE:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
tud_control_xfer(rhport, request, &_dfu_ctx.state, 1);
}
- break;
+ break;
case DFU_REQUEST_ABORT:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
reset_state();
tud_control_status(rhport, request);
+ } else if (stage == CONTROL_STAGE_ACK) {
+ if (tud_dfu_abort_cb) {
+ tud_dfu_abort_cb(_dfu_ctx.alt);
+ }
}
- else if ( stage == CONTROL_STAGE_ACK )
- {
- if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt);
- }
- break;
+ break;
case DFU_REQUEST_UPLOAD:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD);
TU_VERIFY(tud_dfu_upload_cb);
TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
- uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength);
+ const uint16_t xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_epbuf.transfer_buf,
+ request->wLength);
- return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len);
+ return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, xfer_len);
}
- break;
+ break;
case DFU_REQUEST_DNLOAD:
- if ( stage == CONTROL_STAGE_SETUP )
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD);
TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE);
TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
@@ -312,104 +287,86 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque
_dfu_ctx.flashing_in_progress = true;
// save block and length for flashing
- _dfu_ctx.block = request->wValue;
+ _dfu_ctx.block = request->wValue;
_dfu_ctx.length = request->wLength;
- if ( request->wLength )
- {
+ if (request->wLength) {
// Download with payload -> transition to DOWNLOAD SYNC
_dfu_ctx.state = DFU_DNLOAD_SYNC;
- return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength);
- }
- else
- {
+ return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, request->wLength);
+ } else {
// Download is complete -> transition to MANIFEST SYNC
_dfu_ctx.state = DFU_MANIFEST_SYNC;
return tud_control_status(rhport, request);
}
}
- break;
+ break;
case DFU_REQUEST_GETSTATUS:
- switch ( _dfu_ctx.state )
- {
+ switch (_dfu_ctx.state) {
case DFU_DNLOAD_SYNC:
return process_download_get_status(rhport, stage, request);
- break;
+ break;
case DFU_MANIFEST_SYNC:
return process_manifest_get_status(rhport, stage, request);
- break;
+ break;
default:
- if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0);
- break;
+ if (stage == CONTROL_STAGE_SETUP) {
+ return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0);
+ }
+ break;
}
- break;
+ break;
default: return false; // stall unsupported request
}
- }else
- {
+ } else {
return false; // unsupported request
}
return true;
}
-void tud_dfu_finish_flashing(uint8_t status)
-{
+void tud_dfu_finish_flashing(uint8_t status) {
_dfu_ctx.flashing_in_progress = false;
- if ( status == DFU_STATUS_OK )
- {
- if (_dfu_ctx.state == DFU_DNBUSY)
- {
+ if (status == DFU_STATUS_OK) {
+ if (_dfu_ctx.state == DFU_DNBUSY) {
_dfu_ctx.state = DFU_DNLOAD_SYNC;
- }
- else if (_dfu_ctx.state == DFU_MANIFEST)
- {
+ } else if (_dfu_ctx.state == DFU_MANIFEST) {
_dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT)
- ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET;
+ ? DFU_MANIFEST_SYNC
+ : DFU_MANIFEST_WAIT_RESET;
}
- }
- else
- {
+ } else {
// failed while flashing, move to dfuError
_dfu_ctx.state = DFU_ERROR;
_dfu_ctx.status = (dfu_status_t)status;
}
}
-static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- if ( stage == CONTROL_STAGE_SETUP )
- {
+static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
+ if (stage == CONTROL_STAGE_SETUP) {
// only transition to next state on CONTROL_STAGE_ACK
dfu_state_t next_state;
uint32_t timeout;
- if ( _dfu_ctx.flashing_in_progress )
- {
+ if (_dfu_ctx.flashing_in_progress) {
next_state = DFU_DNBUSY;
- timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state);
- }
- else
- {
+ timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t)next_state);
+ } else {
next_state = DFU_DNLOAD_IDLE;
timeout = 0;
}
return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
- }
- else if ( stage == CONTROL_STAGE_ACK )
- {
- if ( _dfu_ctx.flashing_in_progress )
- {
+ } else if (stage == CONTROL_STAGE_ACK) {
+ if (_dfu_ctx.flashing_in_progress) {
_dfu_ctx.state = DFU_DNBUSY;
- tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length);
- }else
- {
+ tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_epbuf.transfer_buf, _dfu_ctx.length);
+ } else {
_dfu_ctx.state = DFU_DNLOAD_IDLE;
}
}
@@ -417,36 +374,26 @@ static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_cont
return true;
}
-static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- if ( stage == CONTROL_STAGE_SETUP )
- {
+static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
+ if (stage == CONTROL_STAGE_SETUP) {
// only transition to next state on CONTROL_STAGE_ACK
dfu_state_t next_state;
uint32_t timeout;
- if ( _dfu_ctx.flashing_in_progress )
- {
+ if (_dfu_ctx.flashing_in_progress) {
next_state = DFU_MANIFEST;
timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state);
- }
- else
- {
+ } else {
next_state = DFU_IDLE;
timeout = 0;
}
return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
- }
- else if ( stage == CONTROL_STAGE_ACK )
- {
- if ( _dfu_ctx.flashing_in_progress )
- {
+ } else if (stage == CONTROL_STAGE_ACK) {
+ if (_dfu_ctx.flashing_in_progress) {
_dfu_ctx.state = DFU_MANIFEST;
tud_dfu_manifest_cb(_dfu_ctx.alt);
- }
- else
- {
+ } else {
_dfu_ctx.state = DFU_IDLE;
}
}
@@ -454,15 +401,15 @@ static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_cont
return true;
}
-static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout)
-{
+static bool reply_getstatus(uint8_t rhport, const tusb_control_request_t* request, dfu_state_t state,
+ dfu_status_t status, uint32_t timeout) {
dfu_status_response_t resp;
- resp.bStatus = (uint8_t) status;
+ resp.bStatus = (uint8_t)status;
resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout);
resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout);
resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout);
- resp.bState = (uint8_t) state;
- resp.iString = 0;
+ resp.bState = (uint8_t)state;
+ resp.iString = 0;
return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t));
}
diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c
index 3b801b787..a63c23d9a 100644
--- a/src/class/dfu/dfu_rt_device.c
+++ b/src/class/dfu/dfu_rt_device.c
@@ -58,9 +58,8 @@ bool dfu_rtd_deinit(void) {
return true;
}
-void dfu_rtd_reset(uint8_t rhport)
-{
- (void) rhport;
+void dfu_rtd_reset(uint8_t rhport) {
+ (void) rhport;
}
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index ef6c7f3af..eedcba984 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -51,14 +51,17 @@ typedef struct {
// TODO save hid descriptor since host can specifically request this after enumeration
// Note: HID descriptor may be not available from application after enumeration
- tusb_hid_descriptor_hid_t const *hid_descriptor;
-
- uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE];
+ const tusb_hid_descriptor_hid_t*hid_descriptor;
} hidd_interface_t;
-CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
+typedef struct {
+ TUD_EPBUF_DEF(ctrl , CFG_TUD_HID_EP_BUFSIZE);
+ TUD_EPBUF_DEF(epin , CFG_TUD_HID_EP_BUFSIZE);
+ TUD_EPBUF_DEF(epout, CFG_TUD_HID_EP_BUFSIZE);
+} hidd_epbuf_t;
+
+static hidd_interface_t _hidd_itf[CFG_TUD_HID];
+CFG_TUD_MEM_SECTION static hidd_epbuf_t _hidd_epbuf[CFG_TUD_HID];
/*------------- Helpers -------------*/
TU_ATTR_ALWAYS_INLINE static inline uint8_t get_index_by_itfnum(uint8_t itf_num) {
@@ -108,22 +111,24 @@ bool tud_hid_n_ready(uint8_t instance) {
}
bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len) {
- uint8_t const rhport = 0;
+ TU_VERIFY(instance < CFG_TUD_HID);
+ const uint8_t rhport = 0;
hidd_interface_t *p_hid = &_hidd_itf[instance];
+ hidd_epbuf_t *p_epbuf = &_hidd_epbuf[instance];
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_hid->ep_in));
// prepare data
if (report_id) {
- p_hid->epin_buf[0] = report_id;
- TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf + 1, CFG_TUD_HID_EP_BUFSIZE - 1, report, len));
+ p_epbuf->epin[0] = report_id;
+ TU_VERIFY(0 == tu_memcpy_s(p_epbuf->epin + 1, CFG_TUD_HID_EP_BUFSIZE - 1, report, len));
len++;
} else {
- TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf, CFG_TUD_HID_EP_BUFSIZE, report, len));
+ TU_VERIFY(0 == tu_memcpy_s(p_epbuf->epin, CFG_TUD_HID_EP_BUFSIZE, report, len));
}
- return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len);
+ return usbd_edpt_xfer(rhport, p_hid->ep_in, p_epbuf->epin, len);
}
uint8_t tud_hid_n_interface_protocol(uint8_t instance) {
@@ -214,15 +219,16 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16
TU_ASSERT(max_len >= drv_len, 0);
// Find available interface
- hidd_interface_t *p_hid = NULL;
+ hidd_interface_t *p_hid;
uint8_t hid_id;
for (hid_id = 0; hid_id < CFG_TUD_HID; hid_id++) {
- if (_hidd_itf[hid_id].ep_in == 0) {
- p_hid = &_hidd_itf[hid_id];
+ p_hid = &_hidd_itf[hid_id];
+ if (p_hid->ep_in == 0) {
break;
}
}
- TU_ASSERT(p_hid, 0);
+ TU_ASSERT(hid_id < CFG_TUD_HID, 0);
+ hidd_epbuf_t *p_epbuf = &_hidd_epbuf[hid_id];
uint8_t const *p_desc = (uint8_t const *)desc_itf;
@@ -247,10 +253,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16
// Prepare for output endpoint
if (p_hid->ep_out) {
- if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))) {
- TU_LOG_FAILED();
- TU_BREAKPOINT();
- }
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE), drv_len);
}
return drv_len;
@@ -264,8 +267,8 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const hid_itf = get_index_by_itfnum((uint8_t)request->wIndex);
TU_VERIFY(hid_itf < CFG_TUD_HID);
-
hidd_interface_t *p_hid = &_hidd_itf[hid_itf];
+ hidd_epbuf_t *p_epbuf = &_hidd_epbuf[hid_itf];
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
//------------- STD Request -------------//
@@ -291,7 +294,7 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
- uint8_t* report_buf = p_hid->ctrl_buf;
+ uint8_t* report_buf = p_epbuf->ctrl;
uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
uint16_t xferlen = 0;
@@ -305,19 +308,19 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
TU_ASSERT(xferlen > 0);
- tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
+ tud_control_xfer(rhport, request, p_epbuf->ctrl, xferlen);
}
break;
case HID_REQ_CONTROL_SET_REPORT:
if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
- tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength);
+ TU_VERIFY(request->wLength <= CFG_TUD_HID_EP_BUFSIZE);
+ tud_control_xfer(rhport, request, p_epbuf->ctrl, request->wLength);
} else if (stage == CONTROL_STAGE_ACK) {
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
- uint8_t const* report_buf = p_hid->ctrl_buf;
+ uint8_t const* report_buf = p_epbuf->ctrl;
uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
// If host request a specific Report ID, extract report ID in buffer before invoking callback
@@ -371,8 +374,8 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
}
bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
- uint8_t instance = 0;
- hidd_interface_t *p_hid = _hidd_itf;
+ uint8_t instance;
+ hidd_interface_t *p_hid;
// Identify which interface to use
for (instance = 0; instance < CFG_TUD_HID; instance++) {
@@ -382,24 +385,25 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
}
}
TU_ASSERT(instance < CFG_TUD_HID);
+ hidd_epbuf_t *p_epbuf = &_hidd_epbuf[instance];
if (ep_addr == p_hid->ep_in) {
// Input report
if (XFER_RESULT_SUCCESS == result) {
- tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes);
+ tud_hid_report_complete_cb(instance, p_epbuf->epin, (uint16_t) xferred_bytes);
} else {
- tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_INPUT, p_hid->epin_buf, (uint16_t) xferred_bytes);
+ tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_INPUT, p_epbuf->epin, (uint16_t) xferred_bytes);
}
} else {
// Output report
if (XFER_RESULT_SUCCESS == result) {
- tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes);
+ tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_epbuf->epout, (uint16_t)xferred_bytes);
} else {
- tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t) xferred_bytes);
+ tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_OUTPUT, p_epbuf->epout, (uint16_t) xferred_bytes);
}
// prepare for new transfer
- TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE));
}
return true;
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index 42905ab0d..c545f8287 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -40,15 +40,13 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
uint8_t buffer[4];
uint8_t index;
uint8_t total;
-}midid_stream_t;
+} midid_stream_t;
-typedef struct
-{
+typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
@@ -70,36 +68,36 @@ typedef struct
osal_mutex_def_t rx_ff_mutex;
osal_mutex_def_t tx_ff_mutex;
#endif
-
- // Endpoint Transfer buffer
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE];
-
} midid_interface_t;
#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff)
+// Endpoint Transfer buffer
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(epin, CFG_TUD_MIDI_EP_BUFSIZE);
+ TUD_EPBUF_DEF(epout, CFG_TUD_MIDI_EP_BUFSIZE);
+} _midid_epbuf[CFG_TUD_MIDI];
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUD_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI];
+static midid_interface_t _midid_itf[CFG_TUD_MIDI];
-bool tud_midi_n_mounted (uint8_t itf)
-{
+bool tud_midi_n_mounted (uint8_t itf) {
midid_interface_t* midi = &_midid_itf[itf];
return midi->ep_in && midi->ep_out;
}
-static void _prep_out_transaction (midid_interface_t* p_midi)
-{
- uint8_t const rhport = 0;
+static void _prep_out_transaction(uint8_t idx) {
+ const uint8_t rhport = 0;
+ midid_interface_t* p_midi = &_midid_itf[idx];
uint16_t available = tu_fifo_remaining(&p_midi->rx_ff);
// Prepare for incoming data but only allow what we can store in the ring buffer.
// TODO Actually we can still carry out the transfer, keeping count of received bytes
// and slowly move it to the FIFO when read().
// This pre-check reduces endpoint claiming
- TU_VERIFY(available >= sizeof(p_midi->epout_buf), );
+ TU_VERIFY(available >= CFG_TUD_MIDI_EP_BUFSIZE, );
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), );
@@ -107,8 +105,8 @@ static void _prep_out_transaction (midid_interface_t* p_midi)
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_midi->rx_ff);
- if ( available >= sizeof(p_midi->epout_buf) ) {
- usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf));
+ if ( available >= CFG_TUD_MIDI_EP_BUFSIZE ) {
+ usbd_edpt_xfer(rhport, p_midi->ep_out, _midid_epbuf[idx].epout, CFG_TUD_MIDI_EP_BUFSIZE);
}else
{
// Release endpoint since we don't make any transfer
@@ -124,7 +122,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num)
(void) cable_num;
midid_interface_t* midi = &_midid_itf[itf];
- midid_stream_t const* stream = &midi->stream_read;
+ const midid_stream_t* stream = &midi->stream_read;
// when using with packet API stream total & index are both zero
return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index);
@@ -205,8 +203,8 @@ bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
midid_interface_t* midi = &_midid_itf[itf];
TU_VERIFY(midi->ep_out);
- uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4);
- _prep_out_transaction(midi);
+ const uint32_t num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4);
+ _prep_out_transaction(itf);
return (num_read == 4);
}
@@ -214,31 +212,31 @@ bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
// WRITE API
//--------------------------------------------------------------------+
-static uint32_t write_flush(midid_interface_t* midi)
-{
- // No data to send
- if ( !tu_fifo_count(&midi->tx_ff) ) return 0;
+static uint32_t write_flush(uint8_t idx) {
+ midid_interface_t* midi = &_midid_itf[idx];
- uint8_t const rhport = 0;
+ if (!tu_fifo_count(&midi->tx_ff)) {
+ return 0; // No data to send
+ }
+
+ const uint8_t rhport = 0;
// skip if previous transfer not complete
TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 );
- uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE);
+ uint16_t count = tu_fifo_read_n(&midi->tx_ff, _midid_epbuf[idx].epin, CFG_TUD_MIDI_EP_BUFSIZE);
- if (count)
- {
- TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 );
+ if (count) {
+ TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, _midid_epbuf[idx].epin, count), 0 );
return count;
- }else
- {
+ }else {
// Release endpoint since we don't make any transfer
usbd_edpt_release(rhport, midi->ep_in);
return 0;
}
}
-uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
+uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* buffer, uint32_t bufsize)
{
midid_interface_t* midi = &_midid_itf[itf];
TU_VERIFY(midi->ep_in, 0);
@@ -248,14 +246,13 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
uint32_t i = 0;
while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) )
{
- uint8_t const data = buffer[i];
+ const uint8_t data = buffer[i];
i++;
if ( stream->index == 0 )
{
//------------- New event packet -------------//
-
- uint8_t const msg = data >> 4;
+ const uint8_t msg = data >> 4;
stream->index = 2;
stream->buffer[1] = data;
@@ -340,9 +337,11 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
if ( stream->index == stream->total )
{
// zeroes unused bytes
- for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0;
+ for (uint8_t idx = stream->total; idx < 4; idx++) {
+ stream->buffer[idx] = 0;
+ }
- uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4);
+ const uint16_t count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4);
// complete current event packet, reset stream
stream->index = stream->total = 0;
@@ -352,20 +351,21 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
}
}
- write_flush(midi);
+ write_flush(itf);
return i;
}
-bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
-{
+bool tud_midi_n_packet_write (uint8_t itf, const uint8_t packet[4]) {
midid_interface_t* midi = &_midid_itf[itf];
TU_VERIFY(midi->ep_in);
- if (tu_fifo_remaining(&midi->tx_ff) < 4) return false;
+ if (tu_fifo_remaining(&midi->tx_ff) < 4) {
+ return false;
+ }
tu_fifo_write_n(&midi->tx_ff, packet, 4);
- write_flush(midi);
+ write_flush(itf);
return true;
}
@@ -429,7 +429,7 @@ void midid_reset(uint8_t rhport)
}
}
-uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len)
+uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len)
{
// 1st Interface is Audio Control v1
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
@@ -437,7 +437,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0);
uint16_t drv_len = tu_desc_len(desc_itf);
- uint8_t const * p_desc = tu_desc_next(desc_itf);
+ const uint8_t* p_desc = tu_desc_next(desc_itf);
// Skip Class Specific descriptors
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
@@ -448,7 +448,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
// 2nd Interface is MIDI Streaming
TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0);
- tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc;
+ const tusb_desc_interface_t* desc_midi = (const tusb_desc_interface_t*) p_desc;
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
@@ -456,11 +456,10 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
// Find available interface
midid_interface_t * p_midi = NULL;
- for(uint8_t i=0; i<CFG_TUD_MIDI; i++)
- {
- if ( _midid_itf[i].ep_in == 0 && _midid_itf[i].ep_out == 0 )
- {
- p_midi = &_midid_itf[i];
+ uint8_t idx;
+ for(idx=0; idx<CFG_TUD_MIDI; idx++) {
+ if ( _midid_itf[idx].ep_in == 0 && _midid_itf[idx].ep_out == 0 ) {
+ p_midi = &_midid_itf[idx];
break;
}
}
@@ -479,8 +478,8 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
{
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
- TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0);
- uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
+ TU_ASSERT(usbd_edpt_open(rhport, (const tusb_desc_endpoint_t*) p_desc), 0);
+ uint8_t ep_addr = ((const tusb_desc_endpoint_t*) p_desc)->bEndpointAddress;
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN)
{
@@ -501,7 +500,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
}
// Prepare for incoming data
- _prep_out_transaction(p_midi);
+ _prep_out_transaction(idx);
return drv_len;
}
@@ -509,14 +508,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- (void) rhport;
- (void) stage;
- (void) request;
-
- // driver doesn't support any request yet
- return false;
+bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
+ (void) rhport; (void) stage; (void) request;
+ return false; // driver doesn't support any request yet
}
bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
@@ -524,40 +518,37 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32
(void) result;
(void) rhport;
- uint8_t itf;
+ uint8_t idx;
midid_interface_t* p_midi;
// Identify which interface to use
- for (itf = 0; itf < CFG_TUD_MIDI; itf++)
- {
- p_midi = &_midid_itf[itf];
- if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break;
+ for (idx = 0; idx < CFG_TUD_MIDI; idx++) {
+ p_midi = &_midid_itf[idx];
+ if ((ep_addr == p_midi->ep_out) || (ep_addr == p_midi->ep_in)) {
+ break;
+ }
}
- TU_ASSERT(itf < CFG_TUD_MIDI);
+ TU_ASSERT(idx < CFG_TUD_MIDI);
// receive new data
- if ( ep_addr == p_midi->ep_out )
- {
- tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, (uint16_t) xferred_bytes);
+ if (ep_addr == p_midi->ep_out) {
+ tu_fifo_write_n(&p_midi->rx_ff, _midid_epbuf[idx].epout, (uint16_t)xferred_bytes);
// invoke receive callback if available
- if (tud_midi_rx_cb) tud_midi_rx_cb(itf);
+ if (tud_midi_rx_cb) {
+ tud_midi_rx_cb(idx);
+ }
// prepare for next
// TODO for now ep_out is not used by public API therefore there is no race condition,
// and does not need to claim like ep_in
- _prep_out_transaction(p_midi);
- }
- else if ( ep_addr == p_midi->ep_in )
- {
- if (0 == write_flush(p_midi))
- {
+ _prep_out_transaction(idx);
+ } else if (ep_addr == p_midi->ep_in) {
+ if (0 == write_flush(idx)) {
// If there is no data left, a ZLP should be sent if
// xferred_bytes is multiple of EP size and not zero
- if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) )
- {
- if ( usbd_edpt_claim(rhport, p_midi->ep_in) )
- {
+ if (!tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE))) {
+ if (usbd_edpt_claim(rhport, p_midi->ep_in)) {
usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0);
}
}
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 447560b4d..cfae646a1 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -44,8 +44,7 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-enum
-{
+enum {
MSC_STAGE_CMD = 0,
MSC_STAGE_DATA,
MSC_STAGE_STATUS,
@@ -53,11 +52,9 @@ enum
MSC_STAGE_NEED_RESET,
};
-typedef struct
-{
- // TODO optimize alignment
- CFG_TUSB_MEM_ALIGN msc_cbw_t cbw;
- CFG_TUSB_MEM_ALIGN msc_csw_t csw;
+typedef struct {
+ TU_ATTR_ALIGNED(4) msc_cbw_t cbw;
+ TU_ATTR_ALIGNED(4) msc_csw_t csw;
uint8_t itf_num;
uint8_t ep_in;
@@ -65,6 +62,7 @@ typedef struct
// Bulk Only Transfer (BOT) Protocol
uint8_t stage;
+
uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw
uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
@@ -74,8 +72,11 @@ typedef struct
uint8_t add_sense_qualifier;
}mscd_interface_t;
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf;
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE];
+static mscd_interface_t _mscd_itf;
+
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(buf, CFG_TUD_MSC_EP_BUFSIZE);
+} _mscd_epbuf;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
@@ -86,28 +87,24 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes);
-TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) {
return tu_bit_test(dir, 7);
}
-static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc)
-{
+static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) {
// Data residue is always = host expect - actual transferred
p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len;
-
p_msc->stage = MSC_STAGE_STATUS_SENT;
- return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t));
+ memcpy(_mscd_epbuf.buf, &p_msc->csw, sizeof(msc_csw_t));
+ return usbd_edpt_xfer(rhport, p_msc->ep_in , _mscd_epbuf.buf, sizeof(msc_csw_t));
}
-static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc)
-{
+static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) {
p_msc->stage = MSC_STAGE_CMD;
- return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t));
+ return usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, sizeof(msc_cbw_t));
}
-static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status)
-{
+static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) {
msc_cbw_t const * p_cbw = &p_msc->cbw;
msc_csw_t * p_csw = &p_msc->csw;
@@ -116,82 +113,62 @@ static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status
p_msc->stage = MSC_STAGE_STATUS;
// failed but sense key is not set: default to Illegal Request
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+ if (p_msc->sense_key == 0) {
+ tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+ }
// If there is data stage and not yet complete, stall it
- if ( p_cbw->total_bytes && p_csw->data_residue )
- {
- if ( is_data_in(p_cbw->dir) )
- {
+ if (p_cbw->total_bytes && p_csw->data_residue) {
+ if (is_data_in(p_cbw->dir)) {
usbd_edpt_stall(rhport, p_msc->ep_in);
- }
- else
- {
+ } else {
usbd_edpt_stall(rhport, p_msc->ep_out);
}
}
}
-static inline uint32_t rdwr10_get_lba(uint8_t const command[])
-{
+static inline uint32_t rdwr10_get_lba(uint8_t const command[]) {
// use offsetof to avoid pointer to the odd/unaligned address
- uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba));
-
- // lba is in Big Endian
- return tu_ntohl(lba);
+ const uint32_t lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba));
+ return tu_ntohl(lba); // lba is in Big Endian
}
-static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw)
-{
+static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) {
uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count));
return tu_ntohs(block_count);
}
-static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw)
-{
+static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) {
// first extract block count in the command
uint16_t const block_count = rdwr10_get_blockcount(cbw);
-
- // invalid block count
- if (block_count == 0) return 0;
-
+ if (block_count == 0) {
+ return 0; // invalid block count
+ }
return (uint16_t) (cbw->total_bytes / block_count);
}
-uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
-{
+uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) {
uint8_t status = MSC_CSW_STATUS_PASSED;
uint16_t const block_count = rdwr10_get_blockcount(cbw);
- if ( cbw->total_bytes == 0 )
- {
- if ( block_count )
- {
+ if (cbw->total_bytes == 0) {
+ if (block_count) {
TU_LOG_DRV(" SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
- }else
- {
+ } else {
// no data transfer, only exist in complaint test suite
}
- }else
- {
- if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) )
- {
+ } else {
+ if (SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir)) {
TU_LOG_DRV(" SCSI case 10 (Ho <> Di)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
- }
- else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) )
- {
+ } else if (SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir)) {
TU_LOG_DRV(" SCSI case 8 (Hi <> Do)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
- }
- else if ( 0 == block_count )
- {
+ } else if (0 == block_count) {
TU_LOG_DRV(" SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n");
- status = MSC_CSW_STATUS_FAILED;
- }
- else if ( cbw->total_bytes / block_count == 0 )
- {
+ status = MSC_CSW_STATUS_FAILED;
+ } else if (cbw->total_bytes / block_count == 0) {
TU_LOG_DRV(" Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
}
@@ -205,8 +182,7 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= CFG_TUD_MSC_LOG_LEVEL
-TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
-{
+TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = {
{ .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" },
{ .key = SCSI_CMD_INQUIRY , .data = "Inquiry" },
{ .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" },
@@ -220,8 +196,7 @@ TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
{ .key = SCSI_CMD_WRITE_10 , .data = "Write10" }
};
-TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table =
-{
+TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table = {
.count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup),
.items = _msc_scsi_cmd_lookup
};
@@ -231,19 +206,15 @@ TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table =
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier)
-{
+bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) {
(void) lun;
-
_mscd_itf.sense_key = sense_key;
_mscd_itf.add_sense_code = add_sense_code;
_mscd_itf.add_sense_qualifier = add_sense_qualifier;
-
return true;
}
-static inline void set_sense_medium_not_present(uint8_t lun)
-{
+static inline void set_sense_medium_not_present(uint8_t lun) {
// default sense is NOT READY, MEDIUM NOT PRESENT
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
}
@@ -256,47 +227,38 @@ void mscd_init(void) {
}
bool mscd_deinit(void) {
- // nothing to do
- return true;
+ return true; // nothing to do
}
-void mscd_reset(uint8_t rhport)
-{
+void mscd_reset(uint8_t rhport) {
(void) rhport;
tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
}
-uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
-{
+uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
// only support SCSI's BOT protocol
TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass &&
MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0);
-
- // msc driver length is fixed
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
-
- // Max length must be at least 1 interface + 2 endpoints
- TU_ASSERT(max_len >= drv_len, 0);
+ TU_ASSERT(max_len >= drv_len, 0); // Max length must be at least 1 interface + 2 endpoints
mscd_interface_t * p_msc = &_mscd_itf;
p_msc->itf_num = itf_desc->bInterfaceNumber;
// Open endpoint pair
- TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 );
+ TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0);
// Prepare for Command Block Wrapper
- TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len);
+ TU_ASSERT(prepare_cbw(rhport, p_msc), drv_len);
return drv_len;
}
-static void proc_bot_reset(mscd_interface_t* p_msc)
-{
+static void proc_bot_reset(mscd_interface_t* p_msc) {
p_msc->stage = MSC_STAGE_CMD;
p_msc->total_len = 0;
p_msc->xferred_len = 0;
-
p_msc->sense_key = 0;
p_msc->add_sense_code = 0;
p_msc->add_sense_qualifier = 0;
@@ -305,10 +267,10 @@ static void proc_bot_reset(mscd_interface_t* p_msc)
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- // nothing to do with DATA & ACK stage
- if (stage != CONTROL_STAGE_SETUP) return true;
+bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) {
+ if (stage != CONTROL_STAGE_SETUP) {
+ return true; // nothing to do with DATA & ACK stage
+ }
mscd_interface_t* p_msc = &_mscd_itf;
@@ -316,35 +278,25 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient &&
TUSB_REQ_CLEAR_FEATURE == request->bRequest &&
- TUSB_REQ_FEATURE_EDPT_HALT == request->wValue )
- {
+ TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) {
uint8_t const ep_addr = tu_u16_low(request->wIndex);
- if ( p_msc->stage == MSC_STAGE_NEED_RESET )
- {
+ if (p_msc->stage == MSC_STAGE_NEED_RESET) {
// reset recovery is required to recover from this stage
// Clear Stall request cannot resolve this -> continue to stall endpoint
usbd_edpt_stall(rhport, ep_addr);
- }
- else
- {
- if ( ep_addr == p_msc->ep_in )
- {
- if ( p_msc->stage == MSC_STAGE_STATUS )
- {
+ } else {
+ if (ep_addr == p_msc->ep_in) {
+ if (p_msc->stage == MSC_STAGE_STATUS) {
// resume sending SCSI status if we are in this stage previously before stalled
- TU_ASSERT( send_csw(rhport, p_msc) );
+ TU_ASSERT(send_csw(rhport, p_msc));
}
- }
- else if ( ep_addr == p_msc->ep_out )
- {
- if ( p_msc->stage == MSC_STAGE_CMD )
- {
+ } else if (ep_addr == p_msc->ep_out) {
+ if (p_msc->stage == MSC_STAGE_CMD) {
// part of reset recovery (probably due to invalid CBW) -> prepare for new command
// Note: skip if already queued previously
- if ( usbd_edpt_ready(rhport, p_msc->ep_out) )
- {
- TU_ASSERT( prepare_cbw(rhport, p_msc) );
+ if (usbd_edpt_ready(rhport, p_msc->ep_out)) {
+ TU_ASSERT(prepare_cbw(rhport, p_msc));
}
}
}
@@ -356,33 +308,27 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
// From this point only handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- switch ( request->bRequest )
- {
+ switch ( request->bRequest ) {
case MSC_REQ_RESET:
TU_LOG_DRV(" MSC BOT Reset\r\n");
TU_VERIFY(request->wValue == 0 && request->wLength == 0);
-
- // driver state reset
- proc_bot_reset(p_msc);
-
+ proc_bot_reset(p_msc); // driver state reset
tud_control_status(rhport, request);
break;
- case MSC_REQ_GET_MAX_LUN:
- {
+ case MSC_REQ_GET_MAX_LUN: {
TU_LOG_DRV(" MSC Get Max Lun\r\n");
TU_VERIFY(request->wValue == 0 && request->wLength == 1);
uint8_t maxlun = 1;
- if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb();
+ if (tud_msc_get_maxlun_cb) {
+ maxlun = tud_msc_get_maxlun_cb();
+ }
TU_VERIFY(maxlun);
-
- // MAX LUN is minus 1 by specs
- maxlun--;
-
+ maxlun--; // MAX LUN is minus 1 by specs
tud_control_xfer(rhport, request, &maxlun, 1);
+ break;
}
- break;
default: return false; // stall unsupported request
}
@@ -390,35 +336,34 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
return true;
}
-bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
-{
+bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
(void) event;
mscd_interface_t* p_msc = &_mscd_itf;
- msc_cbw_t const * p_cbw = &p_msc->cbw;
- msc_csw_t * p_csw = &p_msc->csw;
+ msc_cbw_t * p_cbw = &p_msc->cbw;
+ msc_csw_t * p_csw = &p_msc->csw;
- switch (p_msc->stage)
- {
+ switch (p_msc->stage) {
case MSC_STAGE_CMD:
//------------- new CBW received -------------//
// Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it
- if(ep_addr != p_msc->ep_out) return true;
+ if (ep_addr != p_msc->ep_out) {
+ return true;
+ }
- if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) )
- {
- TU_LOG_DRV(" SCSI CBW is not valid\r\n");
+ const uint32_t signature = tu_le32toh(tu_unaligned_read32(_mscd_epbuf.buf));
+ if (!(xferred_bytes == sizeof(msc_cbw_t) && signature == MSC_CBW_SIGNATURE)) {
// BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery
+ TU_LOG_DRV(" SCSI CBW is not valid\r\n");
p_msc->stage = MSC_STAGE_NEED_RESET;
-
- // invalid CBW stall both endpoints
usbd_edpt_stall(rhport, p_msc->ep_in);
usbd_edpt_stall(rhport, p_msc->ep_out);
-
return false;
}
+ memcpy(p_cbw, _mscd_epbuf.buf, sizeof(msc_cbw_t));
+
TU_LOG_DRV(" SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
//TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
@@ -433,87 +378,65 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
p_msc->xferred_len = 0;
// Read10 or Write10
- if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) )
- {
+ if ((SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0])) {
uint8_t const status = rdwr10_validate_cmd(p_cbw);
- if ( status != MSC_CSW_STATUS_PASSED)
- {
+ if (status != MSC_CSW_STATUS_PASSED) {
fail_scsi_op(rhport, p_msc, status);
- }else if ( p_cbw->total_bytes )
- {
- if (SCSI_CMD_READ_10 == p_cbw->command[0])
- {
+ } else if (p_cbw->total_bytes) {
+ if (SCSI_CMD_READ_10 == p_cbw->command[0]) {
proc_read10_cmd(rhport, p_msc);
- }else
- {
+ } else {
proc_write10_cmd(rhport, p_msc);
}
- }else
- {
+ } else {
// no data transfer, only exist in complaint test suite
p_msc->stage = MSC_STAGE_STATUS;
}
- }
- else
- {
+ } else {
// For other SCSI commands
// 1. OUT : queue transfer (invoke app callback after done)
// 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length
- if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) )
- {
- if (p_cbw->total_bytes > sizeof(_mscd_buf))
- {
+ if ((p_cbw->total_bytes > 0) && !is_data_in(p_cbw->dir)) {
+ if (p_cbw->total_bytes > CFG_TUD_MSC_EP_BUFSIZE) {
TU_LOG_DRV(" SCSI reject non READ10/WRITE10 with large data\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }else
- {
+ } else {
// Didn't check for case 9 (Ho > Dn), which requires examining scsi command first
// but it is OK to just receive data then responded with failed status
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, (uint16_t) p_msc->total_len) );
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, (uint16_t) p_msc->total_len));
}
- }else
- {
+ } else {
// First process if it is a built-in commands
- int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf));
+ int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_epbuf.buf, CFG_TUD_MSC_EP_BUFSIZE);
// Invoke user callback if not built-in
- if ( (resplen < 0) && (p_msc->sense_key == 0) )
- {
- resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len);
+ if ((resplen < 0) && (p_msc->sense_key == 0)) {
+ resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_epbuf.buf, (uint16_t)p_msc->total_len);
}
- if ( resplen < 0 )
- {
+ if (resplen < 0) {
// unsupported command
TU_LOG_DRV(" SCSI unsupported or failed command\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }
- else if (resplen == 0)
- {
- if (p_cbw->total_bytes)
- {
+ } else if (resplen == 0) {
+ if (p_cbw->total_bytes) {
// 6.7 The 13 Cases: case 4 (Hi > Dn)
// TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }else
- {
+ } else {
// case 1 Hn = Dn: all good
p_msc->stage = MSC_STAGE_STATUS;
}
- }
- else
- {
- if ( p_cbw->total_bytes == 0 )
- {
+ } else {
+ if (p_cbw->total_bytes == 0) {
// 6.7 The 13 Cases: case 2 (Hn < Di)
// TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }else
- {
+ } else {
// cannot return more than host expect
- p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes);
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) p_msc->total_len) );
+ p_msc->total_len = tu_min32((uint32_t)resplen, p_cbw->total_bytes);
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) p_msc->total_len));
}
}
}
@@ -522,52 +445,39 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
case MSC_STAGE_DATA:
TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun);
- //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2);
+ //TU_LOG_MEM(MSC_DEBUG, _mscd_epbuf.buf, xferred_bytes, 2);
- if (SCSI_CMD_READ_10 == p_cbw->command[0])
- {
+ if (SCSI_CMD_READ_10 == p_cbw->command[0]) {
p_msc->xferred_len += xferred_bytes;
- if ( p_msc->xferred_len >= p_msc->total_len )
- {
+ if ( p_msc->xferred_len >= p_msc->total_len ) {
// Data Stage is complete
p_msc->stage = MSC_STAGE_STATUS;
- }else
- {
+ }else {
proc_read10_cmd(rhport, p_msc);
}
- }
- else if (SCSI_CMD_WRITE_10 == p_cbw->command[0])
- {
+ } else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) {
proc_write10_new_data(rhport, p_msc, xferred_bytes);
- }
- else
- {
+ } else {
p_msc->xferred_len += xferred_bytes;
// OUT transfer, invoke callback if needed
- if ( !is_data_in(p_cbw->dir) )
- {
- int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len);
+ if ( !is_data_in(p_cbw->dir) ) {
+ int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_epbuf.buf, (uint16_t) p_msc->total_len);
- if ( cb_result < 0 )
- {
+ if ( cb_result < 0 ) {
// unsupported command
TU_LOG_DRV(" SCSI unsupported command\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }else
- {
+ }else {
// TODO haven't implement this scenario any further yet
}
}
- if ( p_msc->xferred_len >= p_msc->total_len )
- {
+ if ( p_msc->xferred_len >= p_msc->total_len ) {
// Data Stage is complete
p_msc->stage = MSC_STAGE_STATUS;
- }
- else
- {
+ } else {
// This scenario with command that take more than one transfer is already rejected at Command stage
TU_BREAKPOINT();
}
@@ -580,53 +490,52 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
case MSC_STAGE_STATUS_SENT:
// Wait for the Status phase to complete
- if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
- {
+ if ((ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t))) {
TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
// TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
// Invoke complete callback if defined
// Note: There is racing issue with samd51 + qspi flash testing with arduino
// if complete_cb() is invoked after queuing the status.
- switch(p_cbw->command[0])
- {
+ switch (p_cbw->command[0]) {
case SCSI_CMD_READ_10:
- if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun);
- break;
+ if (tud_msc_read10_complete_cb) {
+ tud_msc_read10_complete_cb(p_cbw->lun);
+ }
+ break;
case SCSI_CMD_WRITE_10:
- if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun);
- break;
+ if (tud_msc_write10_complete_cb) {
+ tud_msc_write10_complete_cb(p_cbw->lun);
+ }
+ break;
default:
- if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command);
- break;
+ if (tud_msc_scsi_complete_cb) {
+ tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command);
+ }
+ break;
}
- TU_ASSERT( prepare_cbw(rhport, p_msc) );
- }else
- {
+ TU_ASSERT(prepare_cbw(rhport, p_msc));
+ } else {
// Any xfer ended here is consider unknown error, ignore it
TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n");
}
- break;
+ break;
- default : break;
+ default: break;
}
- if ( p_msc->stage == MSC_STAGE_STATUS )
- {
+ if (p_msc->stage == MSC_STAGE_STATUS) {
// skip status if epin is currently stalled, will do it when received Clear Stall request
- if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) )
- {
- if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) )
- {
+ if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) {
+ if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) {
// 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
// TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
usbd_edpt_stall(rhport, p_msc->ep_in);
- }else
- {
- TU_ASSERT( send_csw(rhport, p_msc) );
+ } else {
+ TU_ASSERT(send_csw(rhport, p_msc));
}
}
@@ -634,8 +543,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD.
// There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and
// hope everything will work
- if ( usbd_edpt_stalled(rhport, p_msc->ep_in) )
- {
+ if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) {
usbd_edpt_clear_stall(rhport, p_msc->ep_in);
send_csw(rhport, p_msc);
}
@@ -651,84 +559,82 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW)
// In case of a failed status, sense key must be set for reason of failure
-static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize)
-{
- (void) bufsize; // TODO refractor later
+static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) {
+ (void)bufsize; // TODO refractor later
int32_t resplen;
mscd_interface_t* p_msc = &_mscd_itf;
- switch ( scsi_cmd[0] )
- {
+ switch (scsi_cmd[0]) {
case SCSI_CMD_TEST_UNIT_READY:
resplen = 0;
- if ( !tud_msc_test_unit_ready_cb(lun) )
- {
+ if (!tud_msc_test_unit_ready_cb(lun)) {
// Failed status response
- resplen = - 1;
+ resplen = -1;
// set default sense if not set by callback
- if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
+ if (p_msc->sense_key == 0) {
+ set_sense_medium_not_present(lun);
+ }
}
- break;
+ break;
case SCSI_CMD_START_STOP_UNIT:
resplen = 0;
- if (tud_msc_start_stop_cb)
- {
- scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd;
- if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) )
- {
+ if (tud_msc_start_stop_cb) {
+ scsi_start_stop_unit_t const* start_stop = (scsi_start_stop_unit_t const*)scsi_cmd;
+ if (!tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject)) {
// Failed status response
- resplen = - 1;
+ resplen = -1;
// set default sense if not set by callback
- if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
+ if (p_msc->sense_key == 0) {
+ set_sense_medium_not_present(lun);
+ }
}
}
- break;
+ break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
resplen = 0;
- if (tud_msc_prevent_allow_medium_removal_cb)
- {
- scsi_prevent_allow_medium_removal_t const * prevent_allow = (scsi_prevent_allow_medium_removal_t const *) scsi_cmd;
- if ( !tud_msc_prevent_allow_medium_removal_cb(lun, prevent_allow->prohibit_removal, prevent_allow->control) )
- {
+ if (tud_msc_prevent_allow_medium_removal_cb) {
+ scsi_prevent_allow_medium_removal_t const* prevent_allow = (scsi_prevent_allow_medium_removal_t const*)scsi_cmd;
+ if (!tud_msc_prevent_allow_medium_removal_cb(lun, prevent_allow->prohibit_removal, prevent_allow->control)) {
// Failed status response
- resplen = - 1;
+ resplen = -1;
// set default sense if not set by callback
- if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
+ if (p_msc->sense_key == 0) {
+ set_sense_medium_not_present(lun);
+ }
}
}
- break;
+ break;
- case SCSI_CMD_READ_CAPACITY_10:
- {
+ case SCSI_CMD_READ_CAPACITY_10: {
uint32_t block_count;
uint32_t block_size;
uint16_t block_size_u16;
tud_msc_capacity_cb(lun, &block_count, &block_size_u16);
- block_size = (uint32_t) block_size_u16;
+ block_size = (uint32_t)block_size_u16;
// Invalid block size/count from callback, possibly unit is not ready
// stall this request, set sense key to NOT READY
- if (block_count == 0 || block_size == 0)
- {
+ if (block_count == 0 || block_size == 0) {
resplen = -1;
// set default sense if not set by callback
- if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
- }else
- {
+ if (p_msc->sense_key == 0) {
+ set_sense_medium_not_present(lun);
+ }
+ } else {
scsi_read_capacity10_resp_t read_capa10;
- read_capa10.last_lba = tu_htonl(block_count-1);
+ read_capa10.last_lba = tu_htonl(block_count-1);
read_capa10.block_size = tu_htonl(block_size);
resplen = sizeof(read_capa10);
@@ -737,14 +643,13 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
}
break;
- case SCSI_CMD_READ_FORMAT_CAPACITY:
- {
+ case SCSI_CMD_READ_FORMAT_CAPACITY: {
scsi_read_format_capacity_data_t read_fmt_capa =
{
- .list_length = 8,
- .block_num = 0,
- .descriptor_type = 2, // formatted media
- .block_size_u16 = 0
+ .list_length = 8,
+ .block_num = 0,
+ .descriptor_type = 2, // formatted media
+ .block_size_u16 = 0
};
uint32_t block_count;
@@ -754,14 +659,14 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
// Invalid block size/count from callback, possibly unit is not ready
// stall this request, set sense key to NOT READY
- if (block_count == 0 || block_size == 0)
- {
+ if (block_count == 0 || block_size == 0) {
resplen = -1;
// set default sense if not set by callback
- if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
- }else
- {
+ if (p_msc->sense_key == 0) {
+ set_sense_medium_not_present(lun);
+ }
+ } else {
read_fmt_capa.block_num = tu_htonl(block_count);
read_fmt_capa.block_size_u16 = tu_htons(block_size);
@@ -771,14 +676,13 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
}
break;
- case SCSI_CMD_INQUIRY:
- {
+ case SCSI_CMD_INQUIRY: {
scsi_inquiry_resp_t inquiry_rsp =
{
- .is_removable = 1,
- .version = 2,
- .response_data_format = 2,
- .additional_length = sizeof(scsi_inquiry_resp_t) - 5,
+ .is_removable = 1,
+ .version = 2,
+ .response_data_format = 2,
+ .additional_length = sizeof(scsi_inquiry_resp_t) - 5,
};
// vendor_id, product_id, product_rev is space padded string
@@ -793,20 +697,18 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
}
break;
- case SCSI_CMD_MODE_SENSE_6:
- {
+ case SCSI_CMD_MODE_SENSE_6: {
scsi_mode_sense6_resp_t mode_resp =
{
- .data_len = 3,
- .medium_type = 0,
- .write_protected = false,
- .reserved = 0,
- .block_descriptor_len = 0 // no block descriptor are included
+ .data_len = 3,
+ .medium_type = 0,
+ .write_protected = false,
+ .reserved = 0,
+ .block_descriptor_len = 0 // no block descriptor are included
};
bool writable = true;
- if ( tud_msc_is_writable_cb )
- {
+ if (tud_msc_is_writable_cb) {
writable = tud_msc_is_writable_cb(lun);
}
@@ -817,26 +719,24 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
}
break;
- case SCSI_CMD_REQUEST_SENSE:
- {
+ case SCSI_CMD_REQUEST_SENSE: {
scsi_sense_fixed_resp_t sense_rsp =
{
- .response_code = 0x70, // current, fixed format
- .valid = 1
+ .response_code = 0x70, // current, fixed format
+ .valid = 1
};
- sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
- sense_rsp.sense_key = (uint8_t) (p_msc->sense_key & 0x0F);
- sense_rsp.add_sense_code = p_msc->add_sense_code;
+ sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
+ sense_rsp.sense_key = (uint8_t)(p_msc->sense_key & 0x0F);
+ sense_rsp.add_sense_code = p_msc->add_sense_code;
sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier;
resplen = sizeof(sense_rsp);
TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &sense_rsp, (size_t) resplen));
// request sense callback could overwrite the sense data
- if (tud_msc_request_sense_cb)
- {
- resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t) bufsize);
+ if (tud_msc_request_sense_cb) {
+ resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t)bufsize);
}
// Clear sense data after copy
@@ -844,15 +744,15 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
}
break;
- default: resplen = -1; break;
+ default: resplen = -1;
+ break;
}
return resplen;
}
-static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
-{
- msc_cbw_t const * p_cbw = &p_msc->cbw;
+static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) {
+ msc_cbw_t const* p_cbw = &p_msc->cbw;
// block size already verified not zero
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
@@ -861,14 +761,13 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
// remaining bytes capped at class buffer
- int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
+ int32_t nbytes = (int32_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len);
// Application can consume smaller bytes
uint32_t const offset = p_msc->xferred_len % block_sz;
- nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes);
+ nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes);
- if ( nbytes < 0 )
- {
+ if (nbytes < 0) {
// negative means error -> endpoint is stalled & status in CSW set to failed
TU_LOG_DRV(" tud_msc_read10_cb() return -1\r\n");
@@ -876,30 +775,23 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
set_sense_medium_not_present(p_cbw->lun);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }
- else if ( nbytes == 0 )
- {
+ } else if (nbytes == 0) {
// zero means not ready -> simulate an transfer complete so that this driver callback will fired again
dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
- }
- else
- {
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) nbytes), );
+ } else {
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),);
}
}
-static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
-{
- msc_cbw_t const * p_cbw = &p_msc->cbw;
+static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) {
+ msc_cbw_t const* p_cbw = &p_msc->cbw;
bool writable = true;
- if ( tud_msc_is_writable_cb )
- {
+ if (tud_msc_is_writable_cb) {
writable = tud_msc_is_writable_cb(p_cbw->lun);
}
- if ( !writable )
- {
+ if (!writable) {
// Not writable, complete this SCSI op with error
// Sense = Write protected
tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00);
@@ -908,16 +800,15 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
}
// remaining bytes capped at class buffer
- uint16_t nbytes = (uint16_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
+ uint16_t nbytes = (uint16_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len);
// Write10 callback will be called later when usb transfer complete
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), );
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),);
}
// process new data arrived from WRITE10
-static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes)
-{
- msc_cbw_t const * p_cbw = &p_msc->cbw;
+static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) {
+ msc_cbw_t const* p_cbw = &p_msc->cbw;
// block size already verified not zero
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
@@ -927,10 +818,9 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
// Invoke callback to consume new data
uint32_t const offset = p_msc->xferred_len % block_sz;
- int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes);
+ int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes);
- if ( nbytes < 0 )
- {
+ if (nbytes < 0) {
// negative means error -> failed this scsi op
TU_LOG_DRV(" tud_msc_write10_cb() return -1\r\n");
@@ -941,32 +831,25 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
set_sense_medium_not_present(p_cbw->lun);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
- }else
- {
+ } else {
// Application consume less than what we got (including zero)
- if ( (uint32_t) nbytes < xferred_bytes )
- {
- uint32_t const left_over = xferred_bytes - (uint32_t) nbytes;
- if ( nbytes > 0 )
- {
- p_msc->xferred_len += (uint16_t) nbytes;
- memmove(_mscd_buf, _mscd_buf+nbytes, left_over);
+ if ((uint32_t)nbytes < xferred_bytes) {
+ uint32_t const left_over = xferred_bytes - (uint32_t)nbytes;
+ if (nbytes > 0) {
+ p_msc->xferred_len += (uint16_t)nbytes;
+ memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over);
}
// simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false);
- }
- else
- {
+ } else {
// Application consume all bytes in our buffer
p_msc->xferred_len += xferred_bytes;
- if ( p_msc->xferred_len >= p_msc->total_len )
- {
+ if (p_msc->xferred_len >= p_msc->total_len) {
// Data Stage is complete
p_msc->stage = MSC_STAGE_STATUS;
- }else
- {
+ } else {
// prepare to receive more data from host
proc_write10_cmd(rhport, p_msc);
}
diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c
index f7a5fd225..a54e6d662 100644
--- a/src/class/net/ecm_rndis_device.c
+++ b/src/class/net/ecm_rndis_device.c
@@ -35,13 +35,18 @@
#include "net_device.h"
#include "rndis_protocol.h"
-void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */
+extern void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */
+
+#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
+#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
+
+#define NETD_PACKET_SIZE (CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN)
+#define NETD_CONTROL_SIZE 120
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface
uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active
@@ -55,78 +60,44 @@ typedef struct
// TODO since configuration descriptor may not be long-lived memory, we should
// keep a copy of endpoint attribute instead
uint8_t const * ecm_desc_epdata;
-
} netd_interface_t;
-#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
-#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
-
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
-uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
-
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
-uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
-
-struct ecm_notify_struct
-{
+typedef struct ecm_notify_struct {
tusb_control_request_t header;
uint32_t downlink, uplink;
-};
-
-tu_static const struct ecm_notify_struct ecm_notify_nc =
-{
- .header = {
- .bmRequestType = 0xA1,
- .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */,
- .wValue = 1 /* Connected */,
- .wLength = 0,
- },
-};
+} ecm_notify_t;
-tu_static const struct ecm_notify_struct ecm_notify_csc =
-{
- .header = {
- .bmRequestType = 0xA1,
- .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */,
- .wLength = 8,
- },
- .downlink = 9728000,
- .uplink = 9728000,
-};
+typedef struct {
+ TUD_EPBUF_DEF(rx, NETD_PACKET_SIZE);
+ TUD_EPBUF_DEF(tx, NETD_PACKET_SIZE);
-// TODO remove CFG_TUD_MEM_SECTION, control internal buffer is already in this special section
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union
-{
- uint8_t rndis_buf[120];
- struct ecm_notify_struct ecm_buf;
-} notify;
+ TUD_EPBUF_DEF(notify, sizeof(ecm_notify_t));
+ TUD_EPBUF_DEF(ctrl, NETD_CONTROL_SIZE);
+} netd_epbuf_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-// TODO remove CFG_TUD_MEM_SECTION
-CFG_TUD_MEM_SECTION tu_static netd_interface_t _netd_itf;
+static netd_interface_t _netd_itf;
+CFG_TUD_MEM_SECTION static netd_epbuf_t _netd_epbuf;
+static bool can_xmit;
-tu_static bool can_xmit;
-
-void tud_network_recv_renew(void)
-{
- usbd_edpt_xfer(0, _netd_itf.ep_out, received, sizeof(received));
+void tud_network_recv_renew(void) {
+ usbd_edpt_xfer(0, _netd_itf.ep_out, _netd_epbuf.rx, NETD_PACKET_SIZE);
}
-static void do_in_xfer(uint8_t *buf, uint16_t len)
-{
+static void do_in_xfer(uint8_t *buf, uint16_t len) {
can_xmit = false;
usbd_edpt_xfer(0, _netd_itf.ep_in, buf, len);
}
-void netd_report(uint8_t *buf, uint16_t len)
-{
- uint8_t const rhport = 0;
+void netd_report(uint8_t *buf, uint16_t len) {
+ const uint8_t rhport = 0;
+ len = tu_min16(len, sizeof(ecm_notify_t));
- // skip if previous report not yet acknowledged by host
- if ( usbd_edpt_busy(rhport, _netd_itf.ep_notif) ) return;
- usbd_edpt_xfer(rhport, _netd_itf.ep_notif, buf, len);
+ TU_VERIFY(usbd_edpt_claim(rhport, _netd_itf.ep_notif), );
+ memcpy(_netd_epbuf.notify, buf, len);
+ usbd_edpt_xfer(rhport, _netd_itf.ep_notif, _netd_epbuf.notify, len);
}
//--------------------------------------------------------------------+
@@ -140,15 +111,12 @@ bool netd_deinit(void) {
return true;
}
-void netd_reset(uint8_t rhport)
-{
+void netd_reset(uint8_t rhport) {
(void) rhport;
-
netd_init();
}
-uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
-{
+uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass &&
TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass &&
TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol);
@@ -172,21 +140,19 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
uint8_t const * p_desc = tu_desc_next( itf_desc );
// Communication Functional Descriptors
- while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
- {
+ while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
// notification endpoint (if any)
- if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
- {
- TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 );
+ if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
+ TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0);
- _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
+ _netd_itf.ep_notif = ((tusb_desc_endpoint_t const*)p_desc)->bEndpointAddress;
drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface -------------//
@@ -196,27 +162,24 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
// - 1 : IN & OUT endpoints for active networking
TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0);
- do
- {
+ do {
tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc;
TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0);
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
- }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) );
+ } while (_netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len));
// Pair of endpoints
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0);
- if ( _netd_itf.ecm_mode )
- {
+ if (_netd_itf.ecm_mode) {
// ECM by default is in-active, save the endpoint attribute
// to open later when received setInterface
_netd_itf.ecm_desc_epdata = p_desc;
- }else
- {
+ } else {
// Open endpoint pair for RNDIS
- TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 );
+ TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0);
tud_network_init_cb();
@@ -232,38 +195,50 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
return drv_len;
}
-static void ecm_report(bool nc)
-{
- notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc;
- notify.ecm_buf.header.wIndex = _netd_itf.itf_num;
- netd_report((uint8_t *)&notify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf));
+static void ecm_report(bool nc) {
+ const ecm_notify_t ecm_notify_nc = {
+ .header = {
+ .bmRequestType = 0xA1,
+ .bRequest = 0, /* NETWORK_CONNECTION aka NetworkConnection */
+ .wValue = 1, /* Connected */
+ .wLength = 0,
+ },
+ };
+
+ const ecm_notify_t ecm_notify_csc = {
+ .header = {
+ .bmRequestType = 0xA1,
+ .bRequest = 0x2A, /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */
+ .wLength = 8,
+ },
+ .downlink = 9728000,
+ .uplink = 9728000,
+ };
+
+ ecm_notify_t notify = (nc) ? ecm_notify_nc : ecm_notify_csc;
+ notify.header.wIndex = _netd_itf.itf_num;
+ netd_report((uint8_t *)&notify, (nc) ? sizeof(notify.header) : sizeof(notify));
}
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- if ( stage == CONTROL_STAGE_SETUP )
- {
- switch ( request->bmRequestType_bit.type )
- {
+bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) {
+ if (stage == CONTROL_STAGE_SETUP) {
+ switch (request->bmRequestType_bit.type) {
case TUSB_REQ_TYPE_STANDARD:
- switch ( request->bRequest )
- {
- case TUSB_REQ_GET_INTERFACE:
- {
- uint8_t const req_itfnum = (uint8_t) request->wIndex;
+ switch (request->bRequest) {
+ case TUSB_REQ_GET_INTERFACE: {
+ uint8_t const req_itfnum = (uint8_t)request->wIndex;
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum);
tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1);
}
break;
- case TUSB_REQ_SET_INTERFACE:
- {
- uint8_t const req_itfnum = (uint8_t) request->wIndex;
- uint8_t const req_alt = (uint8_t) request->wValue;
+ case TUSB_REQ_SET_INTERFACE: {
+ uint8_t const req_itfnum = (uint8_t)request->wIndex;
+ uint8_t const req_alt = (uint8_t)request->wValue;
// Only valid for Data Interface with Alternate is either 0 or 1
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2);
@@ -273,14 +248,14 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
_netd_itf.itf_data_alt = req_alt;
- if ( _netd_itf.itf_data_alt )
- {
+ if (_netd_itf.itf_data_alt) {
// TODO since we don't actually close endpoint
// hack here to not re-open it
- if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 )
- {
+ if (_netd_itf.ep_in == 0 && _netd_itf.ep_out == 0) {
TU_ASSERT(_netd_itf.ecm_desc_epdata);
- TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
+ TU_ASSERT(
+ usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &
+ _netd_itf.ep_in));
// TODO should be merge with RNDIS's after endpoint opened
// Also should have opposite callback for application to disable network !!
@@ -288,8 +263,7 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
can_xmit = true; // we are ready to transmit a packet
tud_network_recv_renew(); // prepare for incoming packets
}
- }else
- {
+ } else {
// TODO close the endpoint pair
// For now pretend that we did, this should have no harm since host won't try to
// communicate with the endpoints again
@@ -303,50 +277,39 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
// unsupported request
default: return false;
}
- break;
+ break;
case TUSB_REQ_TYPE_CLASS:
- TU_VERIFY (_netd_itf.itf_num == request->wIndex);
+ TU_VERIFY(_netd_itf.itf_num == request->wIndex);
- if (_netd_itf.ecm_mode)
- {
+ if (_netd_itf.ecm_mode) {
/* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */
- if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest)
- {
+ if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) {
tud_control_xfer(rhport, request, NULL, 0);
ecm_report(true);
}
- }
- else
- {
- if (request->bmRequestType_bit.direction == TUSB_DIR_IN)
- {
- rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf);
+ } else {
+ if (request->bmRequestType_bit.direction == TUSB_DIR_IN) {
+ rndis_generic_msg_t* rndis_msg = (rndis_generic_msg_t*)((void*)_netd_epbuf.ctrl);
uint32_t msglen = tu_le32toh(rndis_msg->MessageLength);
- TU_ASSERT(msglen <= sizeof(notify.rndis_buf));
- tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) msglen);
- }
- else
- {
- tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) sizeof(notify.rndis_buf));
+ TU_ASSERT(msglen <= NETD_CONTROL_SIZE);
+ tud_control_xfer(rhport, request, _netd_epbuf.ctrl, (uint16_t)msglen);
+ } else {
+ tud_control_xfer(rhport, request, _netd_epbuf.ctrl, NETD_CONTROL_SIZE);
}
}
- break;
+ break;
// unsupported request
default: return false;
}
- }
- else if ( stage == CONTROL_STAGE_DATA )
- {
+ } else if (stage == CONTROL_STAGE_DATA) {
// Handle RNDIS class control OUT only
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
- request->bmRequestType_bit.direction == TUSB_DIR_OUT &&
- _netd_itf.itf_num == request->wIndex)
- {
- if ( !_netd_itf.ecm_mode )
- {
- rndis_class_set_handler(notify.rndis_buf, request->wLength);
+ request->bmRequestType_bit.direction == TUSB_DIR_OUT &&
+ _netd_itf.itf_num == request->wIndex) {
+ if (!_netd_itf.ecm_mode) {
+ rndis_class_set_handler(_netd_epbuf.ctrl, request->wLength);
}
}
}
@@ -354,92 +317,77 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
return true;
}
-static void handle_incoming_packet(uint32_t len)
-{
- uint8_t *pnt = received;
+static void handle_incoming_packet(uint32_t len) {
+ uint8_t* pnt = _netd_epbuf.rx;
uint32_t size = 0;
- if (_netd_itf.ecm_mode)
- {
+ if (_netd_itf.ecm_mode) {
size = len;
- }
- else
- {
- rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt);
- if (len >= sizeof(rndis_data_packet_t))
- if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len))
- if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len)
- {
- pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)];
+ } else {
+ rndis_data_packet_t* r = (rndis_data_packet_t*)((void*)pnt);
+ if (len >= sizeof(rndis_data_packet_t)) {
+ if ((r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) {
+ if ((r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) {
+ pnt = &_netd_epbuf.rx[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)];
size = r->DataLength;
}
+ }
+ }
}
- if (!tud_network_recv_cb(pnt, (uint16_t) size))
- {
+ if (!tud_network_recv_cb(pnt, (uint16_t)size)) {
/* if a buffer was never handled by user code, we must renew on the user's behalf */
tud_network_recv_renew();
}
}
-bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
- (void) rhport;
- (void) result;
+bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
+ (void)rhport;
+ (void)result;
/* new packet received */
- if ( ep_addr == _netd_itf.ep_out )
- {
+ if (ep_addr == _netd_itf.ep_out) {
handle_incoming_packet(xferred_bytes);
}
/* data transmission finished */
- if ( ep_addr == _netd_itf.ep_in )
- {
+ if (ep_addr == _netd_itf.ep_in) {
/* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */
- if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) )
- {
+ if (xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE))) {
do_in_xfer(NULL, 0); /* a ZLP is needed */
- }
- else
- {
+ } else {
/* we're finally finished */
can_xmit = true;
}
}
- if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) )
- {
- if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false);
+ if (_netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif)) {
+ if (sizeof(tusb_control_request_t) == xferred_bytes) {
+ ecm_report(false);
+ }
}
return true;
}
-bool tud_network_can_xmit(uint16_t size)
-{
+bool tud_network_can_xmit(uint16_t size) {
(void)size;
-
return can_xmit;
}
-void tud_network_xmit(void *ref, uint16_t arg)
-{
- uint8_t *data;
- uint16_t len;
-
- if (!can_xmit)
+void tud_network_xmit(void *ref, uint16_t arg) {
+ if (!can_xmit) {
return;
+ }
- len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN;
- data = transmitted + len;
+ uint16_t len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN;
+ uint8_t* data = _netd_epbuf.tx + len;
len += tud_network_xmit_cb(data, ref, arg);
- if (!_netd_itf.ecm_mode)
- {
- rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted);
+ if (!_netd_itf.ecm_mode) {
+ rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) _netd_epbuf.tx);
memset(hdr, 0, sizeof(rndis_data_packet_t));
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
hdr->MessageLength = len;
@@ -447,7 +395,7 @@ void tud_network_xmit(void *ref, uint16_t arg)
hdr->DataLength = len - sizeof(rndis_data_packet_t);
}
- do_in_xfer(transmitted, len);
+ do_in_xfer(_netd_epbuf.tx, len);
}
#endif
diff --git a/src/class/net/ncm.h b/src/class/net/ncm.h
index 1b987fca0..0245a87f2 100644
--- a/src/class/net/ncm.h
+++ b/src/class/net/ncm.h
@@ -155,9 +155,10 @@ typedef union TU_ATTR_PACKED {
uint8_t data[CFG_TUD_NCM_OUT_NTB_MAX_SIZE];
} recv_ntb_t;
-struct ncm_notify_t {
+typedef struct {
tusb_control_request_t header;
- uint32_t downlink, uplink;
-};
+ uint32_t downlink;
+ uint32_t uplink;
+} ncm_notify_t;
#endif
diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c
index 1516c329a..c97c66a4e 100644
--- a/src/class/net/ncm_device.c
+++ b/src/class/net/ncm_device.c
@@ -89,7 +89,6 @@ typedef struct {
uint8_t rhport; // storage of \a rhport because some callbacks are done without it
// recv handling
- CFG_TUSB_MEM_ALIGN recv_ntb_t recv_ntb[RECV_NTB_N]; // actual recv NTBs
recv_ntb_t *recv_free_ntb[RECV_NTB_N]; // free list of recv NTBs
recv_ntb_t *recv_ready_ntb[RECV_NTB_N]; // NTBs waiting for transmission to glue logic
recv_ntb_t *recv_tinyusb_ntb; // buffer for the running transfer TinyUSB -> driver
@@ -97,7 +96,6 @@ typedef struct {
uint16_t recv_glue_ntb_datagram_ndx; // index into \a recv_glue_ntb_datagram
// xmit handling
- CFG_TUSB_MEM_ALIGN xmit_ntb_t xmit_ntb[XMIT_NTB_N]; // actual xmit NTBs
xmit_ntb_t *xmit_free_ntb[XMIT_NTB_N]; // free list of xmit NTBs
xmit_ntb_t *xmit_ready_ntb[XMIT_NTB_N]; // NTBs waiting for transmission to TinyUSB
xmit_ntb_t *xmit_tinyusb_ntb; // buffer for the running transfer driver -> TinyUSB
@@ -118,7 +116,20 @@ typedef struct {
bool tud_network_recv_renew_process_again; // tud_network_recv_renew() should process again
} ncm_interface_t;
-CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static ncm_interface_t ncm_interface;
+typedef struct {
+ struct {
+ TUD_EPBUF_TYPE_DEF(ntb, recv_ntb_t);
+ } recv[RECV_NTB_N];
+
+ struct {
+ TUD_EPBUF_TYPE_DEF(ntb, xmit_ntb_t);
+ } xmit[XMIT_NTB_N];
+
+ TUD_EPBUF_TYPE_DEF(epnotif, ncm_notify_t);
+} ncm_epbuf_t;
+
+static ncm_interface_t ncm_interface;
+CFG_TUD_MEM_SECTION static ncm_epbuf_t ncm_epbuf;
/**
* This is the NTB parameter structure
@@ -126,7 +137,7 @@ CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static ncm_interface_t ncm_interface;
* \attention
* We are lucky, that byte order is correct
*/
-CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = {
+TU_ATTR_ALIGNED(4) static const ntb_parameters_t ntb_parameters = {
.wLength = sizeof(ntb_parameters_t),
.bmNtbFormatsSupported = 0x01,// 16-bit NTB supported
.dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE,
@@ -156,30 +167,6 @@ CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static const ntb_parameters_t ntb_param
//
// everything about notifications
//
-tu_static struct ncm_notify_t ncm_notify_connected = {
- .header = {
- .bmRequestType_bit = {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN},
- .bRequest = CDC_NOTIF_NETWORK_CONNECTION,
- .wValue = 1 /* Connected */,
- .wLength = 0,
- },
-};
-
-tu_static struct ncm_notify_t ncm_notify_speed_change = {
- .header = {
- .bmRequestType_bit = {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN},
- .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE,
- .wLength = 8,
- },
- .downlink = TUD_OPT_HIGH_SPEED ? 480000000 : 12000000,
- .uplink = TUD_OPT_HIGH_SPEED ? 480000000 : 12000000,
-};
/**
* Transmit next notification to the host (if appropriate).
@@ -194,14 +181,53 @@ static void notification_xmit(uint8_t rhport, bool force_next) {
if (ncm_interface.notification_xmit_state == NOTIFICATION_SPEED) {
TU_LOG_DRV(" NOTIFICATION_SPEED\n");
- ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num;
- usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change));
+ ncm_notify_t notify_speed_change = {
+ .header = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE,
+ .wValue = 0,
+ .wIndex = ncm_interface.itf_num,
+ .wLength = 8
+ }
+ };
+ if (tud_speed_get() == TUSB_SPEED_HIGH) {
+ notify_speed_change.downlink = 480000000;
+ notify_speed_change.uplink = 480000000;
+ } else {
+ notify_speed_change.downlink = 12000000;
+ notify_speed_change.uplink = 12000000;
+ }
+
+ uint16_t notif_len = sizeof(notify_speed_change.header) + notify_speed_change.header.wLength;
+ ncm_epbuf.epnotif = notify_speed_change;
+ usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t*) &ncm_epbuf.epnotif, notif_len);
+
ncm_interface.notification_xmit_state = NOTIFICATION_CONNECTED;
ncm_interface.notification_xmit_is_running = true;
} else if (ncm_interface.notification_xmit_state == NOTIFICATION_CONNECTED) {
TU_LOG_DRV(" NOTIFICATION_CONNECTED\n");
- ncm_notify_connected.header.wIndex = ncm_interface.itf_num;
- usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected));
+ ncm_notify_t notify_connected = {
+ .header = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = CDC_NOTIF_NETWORK_CONNECTION,
+ .wValue = 1 /* Connected */,
+ .wIndex = ncm_interface.itf_num,
+ .wLength = 0,
+ },
+ };
+
+ uint16_t notif_len = sizeof(notify_connected.header) + notify_connected.header.wLength;
+ ncm_epbuf.epnotif = notify_connected;
+ usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_epbuf.epnotif, notif_len);
+
ncm_interface.notification_xmit_state = NOTIFICATION_DONE;
ncm_interface.notification_xmit_is_running = true;
} else {
@@ -743,10 +769,10 @@ void netd_init(void) {
memset(&ncm_interface, 0, sizeof(ncm_interface));
for (int i = 0; i < XMIT_NTB_N; ++i) {
- ncm_interface.xmit_free_ntb[i] = ncm_interface.xmit_ntb + i;
+ ncm_interface.xmit_free_ntb[i] = &ncm_epbuf.xmit[i].ntb;
}
for (int i = 0; i < RECV_NTB_N; ++i) {
- ncm_interface.recv_free_ntb[i] = ncm_interface.recv_ntb + i;
+ ncm_interface.recv_free_ntb[i] = &ncm_epbuf.recv[i].ntb;
}
} // netd_init
diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c
index 129ff465d..37634c38e 100644
--- a/src/class/usbtmc/usbtmc_device.c
+++ b/src/class/usbtmc/usbtmc_device.c
@@ -131,14 +131,6 @@ typedef struct
uint8_t ep_int_in;
uint32_t ep_bulk_in_wMaxPacketSize;
uint32_t ep_bulk_out_wMaxPacketSize;
- // IN buffer is only used for first packet, not the remainder
- // in order to deal with prepending header
- CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE];
- // OUT buffer receives one packet at a time
- CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE];
- // Buffer int msg to ensure alignment and placement correctness
- CFG_TUSB_MEM_ALIGN uint8_t ep_int_in_buf[CFG_TUD_USBTMC_INT_EP_SIZE];
-
uint32_t transfer_size_remaining; // also used for requested length for bulk IN.
uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes)
@@ -150,11 +142,23 @@ typedef struct
usbtmc_capabilities_specific_t const * capabilities;
} usbtmc_interface_state_t;
-CFG_TUD_MEM_SECTION tu_static usbtmc_interface_state_t usbtmc_state =
-{
- .itf_id = 0xFF,
+typedef struct {
+ // IN buffer is only used for first packet, not the remainder in order to deal with prepending header
+ TUD_EPBUF_DEF(epin, USBTMCD_BUFFER_SIZE);
+
+ // OUT buffer receives one packet at a time
+ TUD_EPBUF_DEF(epout, USBTMCD_BUFFER_SIZE);
+
+ // Buffer int msg
+ TUD_EPBUF_DEF(epnotif, CFG_TUD_USBTMC_INT_EP_SIZE);
+} usbtmc_epbuf_t;
+
+static usbtmc_interface_state_t usbtmc_state = {
+ .itf_id = 0xFF,
};
+CFG_TUD_MEM_SECTION static usbtmc_epbuf_t usbtmc_epbuf;
+
// We need all headers to fit in a single packet in this implementation, 32 bytes will fit all standard USBTMC headers
TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u,"USBTMC dev buffer size too small");
@@ -205,7 +209,7 @@ bool tud_usbtmc_transmit_dev_msg_data(
bool endOfMessage,
bool usingTermChar)
{
- const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf);
+ const unsigned int txBufLen = USBTMCD_BUFFER_SIZE;
#ifndef NDEBUG
TU_ASSERT(len > 0u);
@@ -220,7 +224,7 @@ bool tud_usbtmc_transmit_dev_msg_data(
#endif
TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED);
- usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf;
+ usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_epbuf.epin;
tu_varclr(hdr);
hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN;
hdr->header.bTag = usbtmc_state.lastBulkInTag;
@@ -235,7 +239,7 @@ bool tud_usbtmc_transmit_dev_msg_data(
len : (txBufLen - headerLen);
const size_t packetLen = headerLen + dataLen;
- memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen);
+ memcpy((uint8_t*)(usbtmc_epbuf.epin) + headerLen, data, dataLen);
usbtmc_state.transfer_size_remaining = len - dataLen;
usbtmc_state.transfer_size_sent = dataLen;
usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen);
@@ -243,7 +247,7 @@ bool tud_usbtmc_transmit_dev_msg_data(
bool stateChanged =
atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED);
TU_VERIFY(stateChanged);
- TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen));
+ TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t)packetLen));
return true;
}
@@ -255,8 +259,8 @@ bool tud_usbtmc_transmit_notification_data(const void * data, size_t len)
#endif
TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in));
- TU_VERIFY(tu_memcpy_s(usbtmc_state.ep_int_in_buf, sizeof(usbtmc_state.ep_int_in_buf), data, len) == 0);
- TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_state.ep_int_in_buf, (uint16_t)len));
+ TU_VERIFY(tu_memcpy_s(usbtmc_epbuf.epnotif, CFG_TUD_USBTMC_INT_EP_SIZE, data, len) == 0);
+ TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_epbuf.epnotif, (uint16_t)len));
return true;
}
@@ -396,7 +400,7 @@ bool tud_usbtmc_start_bus_read(void)
default:
return false;
}
- TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize));
+ TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_epbuf.epout, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize));
return true;
}
@@ -501,7 +505,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
case STATE_IDLE:
{
TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t));
- msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf);
+ msg = (usbtmc_msg_generic_t*)(usbtmc_epbuf.epout);
uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse);
TU_VERIFY(msg->header.bTag == invInvTag);
TU_VERIFY(msg->header.bTag != 0x00);
@@ -536,7 +540,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
return true;
}
case STATE_RCV:
- if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes))
+ if(!handle_devMsgOut(rhport, usbtmc_epbuf.epout, xferred_bytes, xferred_bytes))
{
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
return false;
@@ -565,24 +569,23 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
break;
case STATE_TX_INITIATED:
- if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf))
+ if(usbtmc_state.transfer_size_remaining >= USBTMCD_BUFFER_SIZE)
{
// Copy buffer to ensure alignment correctness
- memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf));
- TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
- usbtmc_state.ep_bulk_in_buf, sizeof(usbtmc_state.ep_bulk_in_buf)));
- usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf);
- usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf);
- usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf);
+ memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, USBTMCD_BUFFER_SIZE);
+ TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, USBTMCD_BUFFER_SIZE));
+ usbtmc_state.devInBuffer += USBTMCD_BUFFER_SIZE;
+ usbtmc_state.transfer_size_remaining -= USBTMCD_BUFFER_SIZE;
+ usbtmc_state.transfer_size_sent += USBTMCD_BUFFER_SIZE;
}
else // last packet
{
size_t packetLen = usbtmc_state.transfer_size_remaining;
- memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining);
+ memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining);
usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining);
usbtmc_state.transfer_size_remaining = 0;
usbtmc_state.devInBuffer = NULL;
- TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) );
+ TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t)packetLen) );
if(((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0 ))
{
usbtmc_state.state = STATE_TX_SHORTED;
@@ -592,7 +595,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
case STATE_ABORTING_BULK_IN:
// need to send short packet (ZLP?)
- TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u));
+ TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin,(uint16_t)0u));
usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED;
return true;
@@ -744,7 +747,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
if(usbtmc_state.transfer_size_sent == 0)
{
// Send short packet, nothing is in the buffer yet
- TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u));
+ TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin,(uint16_t)0u));
usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED;
}
TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status)));
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index ca04d9a01..6f9b4853f 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -40,16 +40,12 @@ typedef struct {
uint8_t itf_num;
/*------------- From this point, data is not cleared by bus reset -------------*/
- // Endpoint Transfer buffer
- CFG_TUD_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE];
- CFG_TUD_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE];
-
struct {
tu_edpt_stream_t stream;
#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
uint8_t ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
#endif
- }tx;
+ } tx;
struct {
tu_edpt_stream_t stream;
@@ -60,10 +56,17 @@ typedef struct {
} vendord_interface_t;
-CFG_TUD_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
-
#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num))
+static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
+
+typedef struct {
+ TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_EPSIZE);
+ TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_EPSIZE);
+} vendord_epbuf_t;
+
+CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR];
+
//--------------------------------------------------------------------
// Application API
//--------------------------------------------------------------------
@@ -94,7 +97,7 @@ bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) {
uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) {
TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
vendord_interface_t* p_itf = &_vendord_itf[itf];
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
return tu_edpt_stream_read(rhport, &p_itf->rx.stream, buffer, bufsize);
}
@@ -102,7 +105,7 @@ uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) {
void tud_vendor_n_read_flush (uint8_t itf) {
TU_VERIFY(itf < CFG_TUD_VENDOR, );
vendord_interface_t* p_itf = &_vendord_itf[itf];
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
tu_edpt_stream_clear(&p_itf->rx.stream);
tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream);
@@ -111,10 +114,10 @@ void tud_vendor_n_read_flush (uint8_t itf) {
//--------------------------------------------------------------------+
// Write API
//--------------------------------------------------------------------+
-uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) {
+uint32_t tud_vendor_n_write (uint8_t itf, const void* buffer, uint32_t bufsize) {
TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
vendord_interface_t* p_itf = &_vendord_itf[itf];
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
return tu_edpt_stream_write(rhport, &p_itf->tx.stream, buffer, (uint16_t) bufsize);
}
@@ -122,7 +125,7 @@ uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize)
uint32_t tud_vendor_n_write_flush (uint8_t itf) {
TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
vendord_interface_t* p_itf = &_vendord_itf[itf];
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
return tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream);
}
@@ -130,7 +133,7 @@ uint32_t tud_vendor_n_write_flush (uint8_t itf) {
uint32_t tud_vendor_n_write_available (uint8_t itf) {
TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
vendord_interface_t* p_itf = &_vendord_itf[itf];
- uint8_t const rhport = 0;
+ const uint8_t rhport = 0;
return tu_edpt_stream_write_available(rhport, &p_itf->tx.stream);
}
@@ -143,6 +146,7 @@ void vendord_init(void) {
for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
vendord_interface_t* p_itf = &_vendord_itf[i];
+ vendord_epbuf_t* p_epbuf = &_vendord_epbuf[i];
uint8_t* rx_ff_buf =
#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
@@ -153,7 +157,7 @@ void vendord_init(void) {
tu_edpt_stream_init(&p_itf->rx.stream, false, false, false,
rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE,
- p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE);
+ p_epbuf->epout, CFG_TUD_VENDOR_EPSIZE);
uint8_t* tx_ff_buf =
#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
@@ -164,7 +168,7 @@ void vendord_init(void) {
tu_edpt_stream_init(&p_itf->tx.stream, false, true, false,
tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE,
- p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE);
+ p_epbuf->epin, CFG_TUD_VENDOR_EPSIZE);
}
}
@@ -190,7 +194,7 @@ void vendord_reset(uint8_t rhport) {
}
}
-uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) {
+uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) {
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0);
const uint8_t* p_desc = tu_desc_next(desc_itf);
const uint8_t* desc_end = p_desc + max_len;
@@ -237,25 +241,29 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, ui
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
- uint8_t itf = 0;
- vendord_interface_t* p_itf = _vendord_itf;
+ uint8_t itf;
+ vendord_interface_t* p_vendor;
- for ( ; ; itf++, p_itf++) {
- if (itf >= CFG_TUD_VENDOR) return false;
- if ((ep_addr == p_itf->rx.stream.ep_addr) || (ep_addr == p_itf->tx.stream.ep_addr)) break;
+ for (itf = 0; itf < CFG_TUD_VENDOR; itf++) {
+ p_vendor = &_vendord_itf[itf];
+ if ((ep_addr == p_vendor->rx.stream.ep_addr) || (ep_addr == p_vendor->tx.stream.ep_addr)) {
+ break;
+ }
}
+ TU_VERIFY(itf < CFG_TUD_VENDOR);
+ vendord_epbuf_t* p_epbuf = &_vendord_epbuf[itf];
- if ( ep_addr == p_itf->rx.stream.ep_addr ) {
+ if ( ep_addr == p_vendor->rx.stream.ep_addr ) {
// Received new data: put into stream's fifo
- tu_edpt_stream_read_xfer_complete(&p_itf->rx.stream, xferred_bytes);
+ tu_edpt_stream_read_xfer_complete(&p_vendor->rx.stream, xferred_bytes);
// Invoked callback if any
if (tud_vendor_rx_cb) {
- tud_vendor_rx_cb(itf, p_itf->epout_buf, (uint16_t) xferred_bytes);
+ tud_vendor_rx_cb(itf, p_epbuf->epout, (uint16_t) xferred_bytes);
}
- tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream);
- } else if ( ep_addr == p_itf->tx.stream.ep_addr ) {
+ tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream);
+ } else if ( ep_addr == p_vendor->tx.stream.ep_addr ) {
// Send complete
if (tud_vendor_tx_cb) {
tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes);
@@ -263,9 +271,9 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
// try to send more if possible
- if ( 0 == tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream) ) {
+ if ( 0 == tu_edpt_stream_write_xfer(rhport, &p_vendor->tx.stream) ) {
// If there is no data left, a ZLP should be sent if xferred_bytes is multiple of EP Packet size and not zero
- tu_edpt_stream_write_zlp_if_needed(rhport, &p_itf->tx.stream, xferred_bytes);
+ tu_edpt_stream_write_zlp_if_needed(rhport, &p_vendor->tx.stream, xferred_bytes);
}
#endif
}
diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c
index 70dbb5b9e..a7451c577 100644
--- a/src/class/video/video_device.c
+++ b/src/class/video/video_device.c
@@ -116,34 +116,32 @@ typedef struct TU_ATTR_PACKED {
uint8_t state; /* 0:probing 1:committed 2:streaming */
video_probe_and_commit_control_t probe_commit_payload; /* Probe and Commit control */
- /*------------- From this point, data is not cleared by bus reset -------------*/
- CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */
} videod_streaming_interface_t;
+typedef struct {
+ TUD_EPBUF_DEF(buf, CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE);
+} videod_streaming_epbuf_t;
+
/* video control interface */
typedef struct TU_ATTR_PACKED {
- uint8_t const *beg; /* The head of the first video control interface descriptor */
- uint16_t len; /* Byte length of the descriptors */
- uint16_t cur; /* offset for current video control interface */
- uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */
- uint8_t error_code; /* error code */
- uint8_t power_mode;
-
- /*------------- From this point, data is not cleared by bus reset -------------*/
- // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */
-
+ const uint8_t*beg; /* The head of the first video control interface descriptor */
+ uint16_t len; /* Byte length of the descriptors */
+ uint16_t cur; /* offset for current video control interface */
+ uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */
+ uint8_t error_code; /* error code */
+ uint8_t power_mode;
} videod_interface_t;
-#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf)
-
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUD_MEM_SECTION tu_static videod_interface_t _videod_itf[CFG_TUD_VIDEO];
-CFG_TUD_MEM_SECTION tu_static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING];
+static videod_interface_t _videod_itf[CFG_TUD_VIDEO];
+
+static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING];
+CFG_TUD_MEM_SECTION static videod_streaming_epbuf_t _videod_streaming_epbuf[CFG_TUD_VIDEO_STREAMING];
-tu_static uint8_t const _cap_get = 0x1u; /* support for GET */
-tu_static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */
+static uint8_t const _cap_get = 0x1u; /* support for GET */
+static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */
//--------------------------------------------------------------------+
// Debug
@@ -816,21 +814,20 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint
}
/** Prepare the next packet payload. */
-static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm)
-{
+static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm, uint8_t* ep_buf) {
uint_fast16_t remaining = stm->bufsize - stm->offset;
- uint_fast16_t hdr_len = stm->ep_buf[0];
+ uint_fast16_t hdr_len = ep_buf[0];
uint_fast16_t pkt_len = stm->max_payload_transfer_size;
if (hdr_len + remaining < pkt_len) {
pkt_len = hdr_len + remaining;
}
TU_ASSERT(pkt_len >= hdr_len);
uint_fast16_t data_len = pkt_len - hdr_len;
- memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len);
+ memcpy(&ep_buf[hdr_len], stm->buffer + stm->offset, data_len);
stm->offset += data_len;
remaining -= data_len;
if (!remaining) {
- tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
+ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*) ep_buf;
hdr->EndOfFrame = 1;
}
return hdr_len + data_len;
@@ -1001,7 +998,8 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
tusb_control_request_t const *request,
uint_fast8_t stm_idx) {
(void)rhport;
- videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx];
+ videod_streaming_interface_t *stm = &_videod_streaming_itf[stm_idx];
+ videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[stm_idx];
uint8_t const ctrl_sel = TU_U16_HIGH(request->wValue);
TU_LOG_DRV("%s_Control(%s)\r\n", tu_str_video_vs_control_selector[ctrl_sel], tu_lookup_find(&tu_table_video_request, request->bRequest));
@@ -1013,7 +1011,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
case VIDEO_REQUEST_GET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
/* TODO */
- TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &stm->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -1028,17 +1026,17 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
break;
case VIDEO_VS_CTL_PROBE:
- if (self->state != VS_STATE_PROBING) {
- self->state = VS_STATE_PROBING;
+ if (stm->state != VS_STATE_PROBING) {
+ stm->state = VS_STATE_PROBING;
}
switch (request->bRequest) {
case VIDEO_REQUEST_SET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)),
+ TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)),
VIDEO_ERROR_UNKNOWN);
} else if (stage == CONTROL_STAGE_DATA) {
- TU_VERIFY(_update_streaming_parameters(self, &self->probe_commit_payload),
+ TU_VERIFY(_update_streaming_parameters(stm, &stm->probe_commit_payload),
VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
}
return VIDEO_ERROR_NONE;
@@ -1046,7 +1044,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
case VIDEO_REQUEST_GET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -1056,8 +1054,8 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
case VIDEO_REQUEST_GET_DEF:
if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- video_probe_and_commit_control_t tmp = self->probe_commit_payload;
- TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
+ video_probe_and_commit_control_t tmp = stm->probe_commit_payload;
+ TU_VERIFY(_negotiate_streaming_parameters(stm, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -1085,23 +1083,23 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
switch (request->bRequest) {
case VIDEO_REQUEST_SET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
} else if (stage == CONTROL_STAGE_DATA) {
- video_probe_and_commit_control_t *param = &self->probe_commit_payload;
- TU_VERIFY(_update_streaming_parameters(self, param), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
+ video_probe_and_commit_control_t *param = &stm->probe_commit_payload;
+ TU_VERIFY(_update_streaming_parameters(stm, param), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
/* Set the negotiated value */
- self->max_payload_transfer_size = param->dwMaxPayloadTransferSize;
+ stm->max_payload_transfer_size = param->dwMaxPayloadTransferSize;
int ret = VIDEO_ERROR_NONE;
if (tud_video_commit_cb) {
- ret = tud_video_commit_cb(self->index_vc, self->index_vs, param);
+ ret = tud_video_commit_cb(stm->index_vc, stm->index_vs, param);
}
if (VIDEO_ERROR_NONE == ret) {
- self->state = VS_STATE_COMMITTED;
- self->buffer = NULL;
- self->bufsize = 0;
- self->offset = 0;
+ stm->state = VS_STATE_COMMITTED;
+ stm->buffer = NULL;
+ stm->bufsize = 0;
+ stm->offset = 0;
/* initialize payload header */
- tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)self->ep_buf;
+ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm_epbuf->buf;
hdr->bHeaderLength = sizeof(*hdr);
hdr->bmHeaderInfo = 0;
}
@@ -1111,7 +1109,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
case VIDEO_REQUEST_GET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -1199,12 +1197,14 @@ bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
return true;
}
-bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize)
-{
+bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) {
TU_ASSERT(ctl_idx < CFG_TUD_VIDEO);
TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING);
+
if (!buffer || !bufsize) return false;
videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx);
+ videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[ctl_idx];
+
if (!stm || !stm->desc.ep[0] || stm->buffer) return false;
if (stm->state == VS_STATE_PROBING) return false;
@@ -1221,14 +1221,14 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu
TU_VERIFY( usbd_edpt_claim(0, ep_addr) );
/* update the packet header */
- tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
+ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm_epbuf->buf;
hdr->FrameID ^= 1;
hdr->EndOfFrame = 0;
/* update the packet data */
stm->buffer = (uint8_t*)buffer;
stm->bufsize = bufsize;
- uint_fast16_t pkt_len = _prepare_in_payload(stm);
- TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0);
+ uint_fast16_t pkt_len = _prepare_in_payload(stm, stm_epbuf->buf);
+ TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0);
return true;
}
@@ -1242,7 +1242,7 @@ void videod_init(void) {
}
for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
videod_streaming_interface_t *stm = &_videod_streaming_itf[i];
- tu_memclr(stm, ITF_STM_MEM_RESET_SIZE);
+ tu_memclr(stm, sizeof(videod_streaming_interface_t));
}
}
@@ -1258,7 +1258,7 @@ void videod_reset(uint8_t rhport) {
}
for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) {
videod_streaming_interface_t *stm = &_videod_streaming_itf[i];
- tu_memclr(stm, ITF_STM_MEM_RESET_SIZE);
+ tu_memclr(stm, sizeof(videod_streaming_interface_t));
}
}
@@ -1392,13 +1392,14 @@ bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
uint8_t const *desc = ctl->beg;
if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break;
}
-
TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING);
+ videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[itf];
+
if (stm->offset < stm->bufsize) {
/* Claim the endpoint */
TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0);
- uint_fast16_t pkt_len = _prepare_in_payload(stm);
- TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0);
+ uint_fast16_t pkt_len = _prepare_in_payload(stm, stm_epbuf->buf);
+ TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0);
} else {
stm->buffer = NULL;
stm->bufsize = 0;
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index 59cc0fb48..d05032d00 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -176,7 +176,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned32(uint32_t value) { retur
TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { return (value & 0x3FUL) == 0; }
//------------- Mathematics -------------//
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; }
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return TU_DIV_CEIL(v, d); }
// log2 of a value is its MSB's position
// TODO use clz TODO remove
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h
index 646c22b29..9b33a6f61 100644
--- a/src/common/tusb_compiler.h
+++ b/src/common/tusb_compiler.h
@@ -136,7 +136,7 @@
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_WEAK __attribute__ ((weak))
- // #define TU_ATTR_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f))
+ // #define TU_ATTR_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f)))
#ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#endif
@@ -189,6 +189,7 @@
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_WEAK __attribute__ ((weak))
+ // #define TU_ATTR_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f)))
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
@@ -216,6 +217,7 @@
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_WEAK __attribute__ ((weak))
+ // #define TU_ATTR_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f)))
#ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#endif
@@ -244,6 +246,7 @@
#define TU_ATTR_SECTION(sec_name)
#define TU_ATTR_PACKED
#define TU_ATTR_WEAK
+ // #define TU_ATTR_WEAK_ALIAS(f)
#define TU_ATTR_ALWAYS_INLINE
#define TU_ATTR_DEPRECATED(mess)
#define TU_ATTR_UNUSED
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index dfa6c7151..622c8fc21 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -355,6 +355,7 @@
#define TUP_USBIP_DWC2_ESP32
#define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN
#define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 // TODO currently have issue with buffer DMA with espressif
+ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/
#elif TU_CHECK_MCU(OPT_MCU_ESP32P4)
#define TUP_USBIP_DWC2
@@ -362,6 +363,8 @@
#define TUP_RHPORT_HIGHSPEED 1 // port0 FS, port1 HS
#define TUP_DCD_ENDPOINT_MAX 16 // FS 7 ep, HS 16 ep
+ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/
+
#if defined(CFG_TUD_DWC2_DMA_ENABLE) && CFG_TUD_DWC2_DMA_ENABLE == 1
#define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1
#endif
@@ -370,8 +373,8 @@
#define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1
#endif
- #define CFG_TUD_MEM_DCACHE_LINE_SIZE 64
- #define CFG_TUH_MEM_DCACHE_LINE_SIZE 64
+ #define CFG_TUD_MEM_DCACHE_LINE_SIZE_DEFAULT 64
+ #define CFG_TUH_MEM_DCACHE_LINE_SIZE_DEFAULT 64
#define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 // TODO currently have issue with buffer DMA with espressif
@@ -379,7 +382,9 @@
#if (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421))
#error "MCUs are only supported with CFG_TUH_MAX3421 enabled"
#endif
+
#define TUP_DCD_ENDPOINT_MAX 0
+ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/
//--------------------------------------------------------------------+
// Dialog
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index d045a3c8f..e5660861d 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -35,6 +35,23 @@
extern "C" {
#endif
+#define TUD_EPBUF_DCACHE_SIZE(_size) \
+ (CFG_TUD_MEM_DCACHE_ENABLE ? (TU_DIV_CEIL(_size, CFG_TUD_MEM_DCACHE_LINE_SIZE) * CFG_TUD_MEM_DCACHE_LINE_SIZE) : (_size))
+
+// Declare an endpoint buffer with uint8_t[size]
+#define TUD_EPBUF_DEF(_name, _size) \
+ union { \
+ CFG_TUD_MEM_ALIGN uint8_t _name[_size]; \
+ uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(_size)]; \
+ };
+
+// Declare an endpoint buffer with a type
+#define TUD_EPBUF_TYPE_DEF(_name, _type) \
+ union { \
+ CFG_TUD_MEM_ALIGN _type _name; \
+ uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(sizeof(_type))]; \
+ };
+
/*------------------------------------------------------------------*/
/* CONSTANTS
*------------------------------------------------------------------*/
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index b1fd357aa..80a2a2cc1 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -35,7 +35,7 @@
//--------------------------------------------------------------------+
// Callback weak stubs (called if application does not provide)
//--------------------------------------------------------------------+
-TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) {
+TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t* request) {
(void) rhport;
(void) request;
}
@@ -61,54 +61,53 @@ typedef struct {
usbd_control_xfer_cb_t complete_cb;
} usbd_control_xfer_t;
-tu_static usbd_control_xfer_t _ctrl_xfer;
+static usbd_control_xfer_t _ctrl_xfer;
-CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN
-tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE];
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(buf, CFG_TUD_ENDPOINT0_SIZE);
+} _ctrl_epbuf;
//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
// Queue ZLP status transaction
-static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const* request) {
+static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) {
// Opposite to endpoint in Data Phase
- uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
+ const uint8_t ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
}
// Status phase
-bool tud_control_status(uint8_t rhport, tusb_control_request_t const* request) {
+bool tud_control_status(uint8_t rhport, const tusb_control_request_t* request) {
_ctrl_xfer.request = (*request);
_ctrl_xfer.buffer = NULL;
_ctrl_xfer.total_xferred = 0;
_ctrl_xfer.data_len = 0;
- return _status_stage_xact(rhport, request);
+ return status_stage_xact(rhport, request);
}
// Queue a transaction in Data Stage
// Each transaction has up to Endpoint0's max packet size.
// This function can also transfer an zero-length packet
-static bool _data_stage_xact(uint8_t rhport) {
- uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred,
- CFG_TUD_ENDPOINT0_SIZE);
-
+static bool data_stage_xact(uint8_t rhport) {
+ const uint16_t xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE);
uint8_t ep_addr = EDPT_CTRL_OUT;
if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) {
ep_addr = EDPT_CTRL_IN;
if (xact_len) {
- TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len));
+ TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len));
}
}
- return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len);
+ return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _ctrl_epbuf.buf : NULL, xact_len);
}
// Transmit data to/from the control endpoint.
// If the request's wLength is zero, a status packet is sent instead.
-bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, void* buffer, uint16_t len) {
+bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
_ctrl_xfer.request = (*request);
_ctrl_xfer.buffer = (uint8_t*) buffer;
_ctrl_xfer.total_xferred = 0U;
@@ -118,14 +117,9 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, voi
if (_ctrl_xfer.data_len > 0U) {
TU_ASSERT(buffer);
}
-
-// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len);
-
- // Data stage
- TU_ASSERT(_data_stage_xact(rhport));
+ TU_ASSERT(data_stage_xact(rhport));
} else {
- // Status stage
- TU_ASSERT(_status_stage_xact(rhport, request));
+ TU_ASSERT(status_stage_xact(rhport, request));
}
return true;
@@ -135,7 +129,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, voi
// USBD API
//--------------------------------------------------------------------+
void usbd_control_reset(void);
-void usbd_control_set_request(tusb_control_request_t const* request);
+void usbd_control_set_request(const tusb_control_request_t* request);
void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp);
bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
@@ -149,7 +143,7 @@ void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) {
}
// for dcd_set_address where DCD is responsible for status response
-void usbd_control_set_request(tusb_control_request_t const* request) {
+void usbd_control_set_request(const tusb_control_request_t* request) {
_ctrl_xfer.request = (*request);
_ctrl_xfer.buffer = NULL;
_ctrl_xfer.total_xferred = 0;
@@ -179,7 +173,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) {
TU_VERIFY(_ctrl_xfer.buffer);
- memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes);
+ memcpy(_ctrl_xfer.buffer, _ctrl_epbuf.buf, xferred_bytes);
TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2);
}
@@ -204,8 +198,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
}
if (is_ok) {
- // Send status
- TU_ASSERT(_status_stage_xact(rhport, &_ctrl_xfer.request));
+ TU_ASSERT(status_stage_xact(rhport, &_ctrl_xfer.request));
} else {
// Stall both IN and OUT control endpoint
dcd_edpt_stall(rhport, EDPT_CTRL_OUT);
@@ -213,7 +206,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
}
} else {
// More data to transfer
- TU_ASSERT(_data_stage_xact(rhport));
+ TU_ASSERT(data_stage_xact(rhport));
}
return true;
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 363c77761..6c7b94778 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/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
@@ -58,13 +62,6 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir])
typedef struct {
- CFG_TUD_MEM_ALIGN union {
- uint32_t setup_packet[2];
-#if CFG_TUD_MEM_DCACHE_ENABLE
- uint8_t setup_packet_cache_padding[CFG_TUD_MEM_DCACHE_LINE_SIZE];
-#endif
- };
-
// 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
@@ -76,7 +73,11 @@ typedef struct {
bool sof_en;
} dcd_data_t;
-CFG_TUD_MEM_SECTION static dcd_data_t _dcd_data;
+static dcd_data_t _dcd_data;
+
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(setup_packet, 8);
+} _dcd_usbbuf;
//--------------------------------------------------------------------
// DMA
@@ -118,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) _dcd_data.setup_packet;
+ dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_packet;
dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP;
}
@@ -753,12 +754,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.
- _dcd_data.setup_packet[0] = (*rx_fifo);
- _dcd_data.setup_packet[1] = (*rx_fifo);
+ setup[0] = (*rx_fifo);
+ setup[1] = (*rx_fifo);
break;
+ }
case GRXSTS_PKTSTS_SETUP_DONE:
// Setup packet done:
@@ -804,7 +807,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*) _dcd_data.setup_packet, true);
+ dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true);
return;
}
@@ -880,8 +883,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_dcache_invalidate(_dcd_data.setup_packet, 8);
- dcd_event_setup_received(rhport, (uint8_t*) _dcd_data.setup_packet, true);
+ dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8);
+ dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true);
return;
}
diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h
index 84a8360c5..6220716d3 100644
--- a/src/portable/synopsys/dwc2/dwc2_esp32.h
+++ b/src/portable/synopsys/dwc2/dwc2_esp32.h
@@ -116,7 +116,6 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint
//--------------------------------------------------------------------+
#if CFG_TUD_DWC2_DMA_ENABLE || CFG_TUH_DWC2_DMA_ENABLE
#if defined(SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE) && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
-#include "hal/cache_hal.h"
#include "esp_cache.h"
#if CFG_TUD_MEM_DCACHE_LINE_SIZE != CONFIG_CACHE_L1_CACHE_LINE_SIZE || \
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 500d74903..2f07b8da6 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -252,11 +252,7 @@
#define CFG_TUD_DWC2_SLAVE_ENABLE 1
#endif
-// DWC2 controller: use DMA for data transfer
-// For processors with data cache enabled, USB endpoint buffer region
-// (defined by CFG_TUSB_MEM_SECTION) must be declared as non-cacheable.
-// For example, on Cortex-M7 the MPU region can be configured as normal
-// non-cacheable, with RASR register value: TEX=1 C=0 B=0 S=0.
+// Enable DWC2 DMA for device
#ifndef CFG_TUD_DWC2_DMA_ENABLE
#define CFG_TUD_DWC2_DMA_ENABLE 0
#endif
@@ -407,7 +403,11 @@
#endif
#ifndef CFG_TUSB_OS_INC_PATH
- #define CFG_TUSB_OS_INC_PATH
+ #ifndef CFG_TUSB_OS_INC_PATH_DEFAULT
+ #define CFG_TUSB_OS_INC_PATH_DEFAULT
+ #endif
+
+ #define CFG_TUSB_OS_INC_PATH CFG_TUSB_OS_INC_PATH_DEFAULT
#endif
//--------------------------------------------------------------------
@@ -433,7 +433,11 @@
#endif
#ifndef CFG_TUD_MEM_DCACHE_LINE_SIZE
- #define CFG_TUD_MEM_DCACHE_LINE_SIZE 32
+ #ifndef CFG_TUD_MEM_DCACHE_LINE_SIZE_DEFAULT
+ #define CFG_TUD_MEM_DCACHE_LINE_SIZE_DEFAULT 32
+ #endif
+
+ #define CFG_TUD_MEM_DCACHE_LINE_SIZE CFG_TUD_MEM_DCACHE_LINE_SIZE_DEFAULT
#endif
#ifndef CFG_TUD_ENDPOINT0_SIZE
@@ -543,6 +547,22 @@
#define CFG_TUH_MEM_ALIGN CFG_TUSB_MEM_ALIGN
#endif
+#ifndef CFG_TUH_MEM_DCACHE_ENABLE
+ #ifndef CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT
+ #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 0
+ #endif
+
+ #define CFG_TUH_MEM_DCACHE_ENABLE CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT
+#endif
+
+#ifndef CFG_TUH_MEM_DCACHE_LINE_SIZE
+ #ifndef CFG_TUH_MEM_DCACHE_LINE_SIZE_DEFAULT
+ #define CFG_TUH_MEM_DCACHE_LINE_SIZE_DEFAULT 32
+ #endif
+
+ #define CFG_TUH_MEM_DCACHE_LINE_SIZE CFG_TUH_MEM_DCACHE_LINE_SIZE_DEFAULT
+#endif
+
//------------- CLASS -------------//
#ifndef CFG_TUH_HUB
diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json
index b6c9b540a..8b4ef6d3a 100644
--- a/test/hil/tinyusb.json
+++ b/test/hil/tinyusb.json
@@ -3,6 +3,9 @@
{
"name": "espressif_p4_function_ev",
"uid": "6055F9F98715",
+ "build" : {
+ "flags_on": ["", "CFG_TUD_DWC2_DMA_ENABLE"]
+ },
"tests": {
"only": ["device/cdc_msc_freertos", "device/hid_composite_freertos", "host/device_info"],
"dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002427"}]