From 14d7e457a784c618996fdeae1ea94c04396be2bf Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 29 Jun 2026 14:06:05 +0200 Subject: [PATCH 1/4] Improve Espressif example build selection Default Espressif builds to FreeRTOS, discover ESP-IDF examples from component metadata, and make skip filtering RTOS-aware. --- examples/device/board_test/CMakeLists.txt | 2 +- examples/device/video_capture_2ch/skip.txt | 1 - .../host_info_to_device_cdc/CMakeLists.txt | 2 +- hw/bsp/family_support.cmake | 43 +++++++++++--- tools/build.py | 59 ++++++++++++++++--- tools/build_utils.py | 23 ++++++-- 6 files changed, 104 insertions(+), 26 deletions(-) diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt index f14d72c080..ff79f14192 100644 --- a/examples/device/board_test/CMakeLists.txt +++ b/examples/device/board_test/CMakeLists.txt @@ -34,6 +34,6 @@ target_include_directories(${EXE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${EXE_NAME} ${RTOS}) diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index c37205b8cb..107d19457b 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -7,7 +7,6 @@ mcu:CH32V20X mcu:CH32V307 mcu:CH583 mcu:STM32L0 -family:espressif board:curiosity_nano board:kuiic board:frdm_k32l2b diff --git a/examples/dual/host_info_to_device_cdc/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/CMakeLists.txt index 87b5336f1c..fecffac2b3 100644 --- a/examples/dual/host_info_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_info_to_device_cdc/CMakeLists.txt @@ -25,7 +25,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_dual_usb_example(${PROJECT_NAME} ${RTOS}) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 1f39522051..780d696f3a 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -149,7 +149,11 @@ endif() # RTOS #---------------------------------- if (NOT DEFINED RTOS) - set(RTOS noos CACHE STRING "RTOS") + if (FAMILY STREQUAL "espressif") + set(RTOS freertos CACHE STRING "RTOS") + else() + set(RTOS noos CACHE STRING "RTOS") + endif() endif () if (RTOS STREQUAL zephyr) @@ -173,15 +177,38 @@ function(family_filter RESULT DIR) if (EXISTS "${DIR}/skip.txt") file(STRINGS "${DIR}/skip.txt" SKIPS_LINES) - foreach(MCU IN LISTS FAMILY_MCUS) - # For each line in only.txt - foreach(_line ${SKIPS_LINES}) - # If mcu:xxx exists for this mcu then skip - if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}" OR ${_line} STREQUAL "family:${FAMILY}") - set(${RESULT} 0 PARENT_SCOPE) - return() + foreach(_line IN LISTS SKIPS_LINES) + string(STRIP "${_line}" _line) + if (_line STREQUAL "" OR _line MATCHES "^#") + continue() + endif() + + separate_arguments(_tokens UNIX_COMMAND "${_line}") + set(_rtos_match 1) + set(_skip_match 0) + + foreach(_token IN LISTS _tokens) + if (_token MATCHES "^rtos:") + string(REGEX REPLACE "^rtos:" "" _skip_rtos "${_token}") + if (NOT "${_skip_rtos}" STREQUAL "${RTOS}") + set(_rtos_match 0) + endif() endif() endforeach() + + foreach(MCU IN LISTS FAMILY_MCUS) + foreach(_token IN LISTS _tokens) + # If mcu:xxx exists for this mcu then skip + if (_token STREQUAL "mcu:${MCU}" OR _token STREQUAL "board:${BOARD}" OR _token STREQUAL "family:${FAMILY}") + set(_skip_match 1) + endif() + endforeach() + endforeach() + + if (_rtos_match AND _skip_match) + set(${RESULT} 0 PARENT_SCOPE) + return() + endif() endforeach() endif () diff --git a/tools/build.py b/tools/build.py index 86bc30d283..57a68fbfd7 100755 --- a/tools/build.py +++ b/tools/build.py @@ -80,19 +80,55 @@ def find_family(board): return None +def default_rtos(family): + return 'freertos' if family == 'espressif' else 'noos' + + +def cmake_define_value(args, name): + for arg in reversed(args): + if not arg.startswith('-D'): + continue + + key, sep, value = arg[2:].partition('=') + if not sep: + continue + + if key.split(':', 1)[0] == name: + return value + + return None + + +def cmake_args_with_default(args, name, value): + if cmake_define_value(args, name) is not None: + return list(args) + + return [*args, f'-D{name}={value}'] + + +def make_option_value(options, name): + for option in reversed(shlex.split(options or '')): + if option.startswith(name + '='): + return option.split('=', 1)[1] + + return None + + def get_examples(family): all_examples = [] for d in os.scandir("examples"): if d.is_dir() and 'cmake' not in d.name and 'build_system' not in d.name: for entry in os.scandir(d.path): - if entry.is_dir() and 'cmake' not in entry.name: - if family != 'espressif' or 'freertos' in entry.name: + if not entry.is_dir() or 'cmake' in entry.name: + continue + + path = Path(entry.path) + if family == 'espressif': + if (path / 'src' / 'CMakeLists.txt').is_file(): all_examples.append(d.name + '/' + entry.name) + elif (path / 'CMakeLists.txt').is_file() or (path / 'Makefile').is_file(): + all_examples.append(d.name + '/' + entry.name) - if family == 'espressif': - all_examples.append('device/board_test') - all_examples.append('device/video_capture') - all_examples.append('host/device_info') all_examples.sort() return all_examples @@ -115,16 +151,18 @@ def cmake_board(board, build_args, build_name, build_cflags, build_targets): build_flags.append('-DCFLAGS_CLI=' + ' '.join(build_cflags)) family = find_family(board) + rtos = cmake_define_value(build_args, 'RTOS') or default_rtos(family) if family == 'espressif': # for espressif, we have to build example individually + build_args = cmake_args_with_default(build_args, 'RTOS', rtos) all_examples = get_examples(family) for example in all_examples: - if build_utils.skip_example(example, board): + if build_utils.skip_example(example, board, rtos=rtos): ret[2] += 1 else: rcmd = run_cmd([ 'idf.py', '-C', f'examples/{example}', '-B', f'{build_dir}/{example}', '-GNinja', - f'-DBOARD={board}', *build_flags, 'build' + f'-DBOARD={board}', *build_args, *build_flags, 'build' ]) ret[0 if rcmd.returncode == 0 else 1] += 1 else: @@ -147,8 +185,11 @@ def cmake_board(board, build_args, build_name, build_cflags, build_targets): # Make # ----------------------------- def make_one_example(example, board, make_option, build_targets): + family = find_family(board) + rtos = make_option_value(make_option, 'RTOS') or default_rtos(family) + # Check if board is skipped - if build_utils.skip_example(example, board): + if build_utils.skip_example(example, board, rtos=rtos): print_build_result(board, example, 2, '-') r = 2 else: diff --git a/tools/build_utils.py b/tools/build_utils.py index d80ceea7c5..e3d3ac6520 100755 --- a/tools/build_utils.py +++ b/tools/build_utils.py @@ -10,7 +10,7 @@ SKIPPED = "\033[33mskipped\033[0m" -def skip_example(example, board): +def skip_example(example, board, rtos='noos'): ex_dir = pathlib.Path('examples/') / example bsp = pathlib.Path("hw/bsp") @@ -68,11 +68,22 @@ def skip_example(example, board): only_file = ex_dir / "only.txt" if skip_file.exists(): - skips = skip_file.read_text().split() - if ("mcu:" + mcu in skips or - "board:" + board in skips or - "family:" + family in skips): - return True + for line in skip_file.read_text().splitlines(): + tokens = line.split() + if not tokens or tokens[0].startswith("#"): + continue + + rtos_matches = True + for token in tokens: + if token.startswith("rtos:") and token != "rtos:" + rtos: + rtos_matches = False + break + + if (rtos_matches and + ("mcu:" + mcu in tokens or + "board:" + board in tokens or + "family:" + family in tokens)): + return True if only_file.exists(): onlys = only_file.read_text().split() From 7ddee569914da22df0735891912a1aad405ffd1d Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 29 Jun 2026 14:07:07 +0200 Subject: [PATCH 2/4] Consolidate FreeRTOS device examples Merge paired FreeRTOS/no-OS device examples into their base directories. --- examples/device/CMakeLists.txt | 5 - .../device/audio_4_channel_mic/CMakeLists.txt | 9 +- .../sdkconfig.defaults | 0 examples/device/audio_4_channel_mic/skip.txt | 35 +- .../src/CMakeLists.txt | 0 .../device/audio_4_channel_mic/src/main.c | 147 +++++- .../audio_4_channel_mic/src/tusb_config.h | 5 + .../CMakeLists.txt | 40 -- .../CMakePresets.json | 6 - .../audio_4_channel_mic_freertos/Makefile | 15 - .../audio_4_channel_mic_freertos/skip.txt | 22 - .../audio_4_channel_mic_freertos/src/main.c | 486 ------------------ .../src/plot_audio_samples.py | 80 --- .../src/tusb_config.h | 128 ----- .../src/usb_descriptors.c | 187 ------- examples/device/audio_test/CMakeLists.txt | 9 +- .../sdkconfig.defaults | 0 examples/device/audio_test/skip.txt | 31 +- .../src/CMakeLists.txt | 0 examples/device/audio_test/src/main.c | 153 ++++-- examples/device/audio_test/src/tusb_config.h | 5 + .../device/audio_test_freertos/CMakeLists.txt | 35 -- .../audio_test_freertos/CMakePresets.json | 6 - examples/device/audio_test_freertos/Makefile | 15 - examples/device/audio_test_freertos/skip.txt | 20 - .../device/audio_test_freertos/src/main.c | 480 ----------------- .../src/plot_audio_samples.py | 80 --- .../audio_test_freertos/src/tusb_config.h | 128 ----- .../audio_test_freertos/src/usb_descriptors.c | 189 ------- examples/device/cdc_msc/CMakeLists.txt | 7 +- .../sdkconfig.defaults | 0 examples/device/cdc_msc/skip.txt | 27 +- .../src/CMakeLists.txt | 0 examples/device/cdc_msc/src/main.c | 183 +++++-- examples/device/cdc_msc/src/msc_disk.c | 103 +++- examples/device/cdc_msc/src/tusb_config.h | 5 + .../device/cdc_msc_freertos/CMakeLists.txt | 36 -- .../device/cdc_msc_freertos/CMakePresets.json | 6 - examples/device/cdc_msc_freertos/Makefile | 16 - examples/device/cdc_msc_freertos/skip.txt | 20 - examples/device/cdc_msc_freertos/src/main.c | 239 --------- .../device/cdc_msc_freertos/src/msc_disk.c | 340 ------------ .../device/cdc_msc_freertos/src/tusb_config.h | 125 ----- .../cdc_msc_freertos/src/usb_descriptors.c | 288 ----------- examples/device/freertos_noos_merge_todo.md | 14 + examples/device/hid_composite/CMakeLists.txt | 9 +- .../sdkconfig.defaults | 0 examples/device/hid_composite/skip.txt | 21 +- .../src/CMakeLists.txt | 0 examples/device/hid_composite/src/main.c | 178 +++++-- .../device/hid_composite/src/tusb_config.h | 5 + .../hid_composite_freertos/CMakeLists.txt | 35 -- .../hid_composite_freertos/CMakePresets.json | 6 - .../device/hid_composite_freertos/Makefile | 15 - .../device/hid_composite_freertos/skip.txt | 18 - .../device/hid_composite_freertos/src/main.c | 387 -------------- .../hid_composite_freertos/src/tusb_config.h | 114 ---- .../src/usb_descriptors.c | 238 --------- .../src/usb_descriptors.h | 37 -- examples/device/midi_test/CMakeLists.txt | 4 +- examples/device/midi_test/skip.txt | 21 +- .../src/CMakeLists.txt | 0 examples/device/midi_test/src/main.c | 203 ++++++-- examples/device/midi_test/src/tusb_config.h | 5 + .../device/midi_test_freertos/CMakeLists.txt | 30 -- .../midi_test_freertos/CMakePresets.json | 6 - examples/device/midi_test_freertos/Makefile | 15 - examples/device/midi_test_freertos/skip.txt | 18 - examples/device/midi_test_freertos/src/main.c | 235 --------- .../midi_test_freertos/src/tusb_config.h | 108 ---- .../midi_test_freertos/src/usb_descriptors.c | 199 ------- .../device/uac2_speaker_fb/CMakeLists.txt | 9 +- .../uac2_speaker_fb/freertos_merge_todo.md | 11 + .../device/uac2_speaker_fb/sdkconfig.defaults | 4 + .../device/uac2_speaker_fb/src/CMakeLists.txt | 4 + examples/device/uac2_speaker_fb/src/main.c | 154 +++++- .../device/uac2_speaker_fb/src/tusb_config.h | 5 + 77 files changed, 1137 insertions(+), 4682 deletions(-) rename examples/device/{audio_4_channel_mic_freertos => audio_4_channel_mic}/sdkconfig.defaults (100%) rename examples/device/{audio_4_channel_mic_freertos => audio_4_channel_mic}/src/CMakeLists.txt (100%) delete mode 100644 examples/device/audio_4_channel_mic_freertos/CMakeLists.txt delete mode 100644 examples/device/audio_4_channel_mic_freertos/CMakePresets.json delete mode 100644 examples/device/audio_4_channel_mic_freertos/Makefile delete mode 100644 examples/device/audio_4_channel_mic_freertos/skip.txt delete mode 100644 examples/device/audio_4_channel_mic_freertos/src/main.c delete mode 100755 examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py delete mode 100644 examples/device/audio_4_channel_mic_freertos/src/tusb_config.h delete mode 100644 examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c rename examples/device/{audio_test_freertos => audio_test}/sdkconfig.defaults (100%) rename examples/device/{audio_test_freertos => audio_test}/src/CMakeLists.txt (100%) delete mode 100644 examples/device/audio_test_freertos/CMakeLists.txt delete mode 100644 examples/device/audio_test_freertos/CMakePresets.json delete mode 100644 examples/device/audio_test_freertos/Makefile delete mode 100644 examples/device/audio_test_freertos/skip.txt delete mode 100644 examples/device/audio_test_freertos/src/main.c delete mode 100755 examples/device/audio_test_freertos/src/plot_audio_samples.py delete mode 100644 examples/device/audio_test_freertos/src/tusb_config.h delete mode 100644 examples/device/audio_test_freertos/src/usb_descriptors.c rename examples/device/{cdc_msc_freertos => cdc_msc}/sdkconfig.defaults (100%) rename examples/device/{cdc_msc_freertos => cdc_msc}/src/CMakeLists.txt (100%) delete mode 100644 examples/device/cdc_msc_freertos/CMakeLists.txt delete mode 100644 examples/device/cdc_msc_freertos/CMakePresets.json delete mode 100644 examples/device/cdc_msc_freertos/Makefile delete mode 100644 examples/device/cdc_msc_freertos/skip.txt delete mode 100644 examples/device/cdc_msc_freertos/src/main.c delete mode 100644 examples/device/cdc_msc_freertos/src/msc_disk.c delete mode 100644 examples/device/cdc_msc_freertos/src/tusb_config.h delete mode 100644 examples/device/cdc_msc_freertos/src/usb_descriptors.c create mode 100644 examples/device/freertos_noos_merge_todo.md rename examples/device/{hid_composite_freertos => hid_composite}/sdkconfig.defaults (100%) rename examples/device/{hid_composite_freertos => hid_composite}/src/CMakeLists.txt (100%) delete mode 100644 examples/device/hid_composite_freertos/CMakeLists.txt delete mode 100644 examples/device/hid_composite_freertos/CMakePresets.json delete mode 100644 examples/device/hid_composite_freertos/Makefile delete mode 100644 examples/device/hid_composite_freertos/skip.txt delete mode 100644 examples/device/hid_composite_freertos/src/main.c delete mode 100644 examples/device/hid_composite_freertos/src/tusb_config.h delete mode 100644 examples/device/hid_composite_freertos/src/usb_descriptors.c delete mode 100644 examples/device/hid_composite_freertos/src/usb_descriptors.h rename examples/device/{midi_test_freertos => midi_test}/src/CMakeLists.txt (100%) delete mode 100644 examples/device/midi_test_freertos/CMakeLists.txt delete mode 100644 examples/device/midi_test_freertos/CMakePresets.json delete mode 100644 examples/device/midi_test_freertos/Makefile delete mode 100644 examples/device/midi_test_freertos/skip.txt delete mode 100644 examples/device/midi_test_freertos/src/main.c delete mode 100644 examples/device/midi_test_freertos/src/tusb_config.h delete mode 100644 examples/device/midi_test_freertos/src/usb_descriptors.c create mode 100644 examples/device/uac2_speaker_fb/freertos_merge_todo.md create mode 100644 examples/device/uac2_speaker_fb/sdkconfig.defaults create mode 100644 examples/device/uac2_speaker_fb/src/CMakeLists.txt diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 1432b36bb3..ad438cbf1e 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -8,14 +8,11 @@ family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY set(EXAMPLE_LIST audio_4_channel_mic - audio_4_channel_mic_freertos audio_test - audio_test_freertos audio_test_multi_rate board_test cdc_dual_ports cdc_msc - cdc_msc_freertos cdc_msc_throughput cdc_uac2 dfu @@ -23,11 +20,9 @@ set(EXAMPLE_LIST dynamic_configuration hid_boot_interface hid_composite - hid_composite_freertos hid_generic_inout hid_multiple_interface midi_test - midi_test_freertos midi2_device msc_dual_lun mtp diff --git a/examples/device/audio_4_channel_mic/CMakeLists.txt b/examples/device/audio_4_channel_mic/CMakeLists.txt index 5d7ffa4fc9..8c27e900d8 100644 --- a/examples/device/audio_4_channel_mic/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) +# Need to set Espressif defaults before project() is called +if(FAMILY STREQUAL "espressif") + list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") +endif() + project(audio_4_channel_mic C CXX ASM) # Checks this example is valid for the family and initializes the project @@ -30,6 +35,6 @@ if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_libraries(${PROJECT_NAME} PUBLIC m) endif() -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT_NAME} noos) +family_configure_device_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults b/examples/device/audio_4_channel_mic/sdkconfig.defaults similarity index 100% rename from examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults rename to examples/device/audio_4_channel_mic/sdkconfig.defaults diff --git a/examples/device/audio_4_channel_mic/skip.txt b/examples/device/audio_4_channel_mic/skip.txt index 3ca433c08b..70a1a872be 100644 --- a/examples/device/audio_4_channel_mic/skip.txt +++ b/examples/device/audio_4_channel_mic/skip.txt @@ -1,6 +1,29 @@ -mcu:SAMD11 -mcu:SAME5X -mcu:SAMG -family:broadcom_64bit -family:espressif -mcu:CH583 +rtos:noos mcu:SAMD11 +rtos:noos mcu:SAME5X +rtos:noos mcu:SAMG +rtos:noos family:broadcom_64bit +rtos:noos family:espressif +rtos:noos mcu:CH583 + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V103 +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:CH32V307 +rtos:freertos mcu:CH583 +rtos:freertos mcu:CXD56 +rtos:freertos mcu:F1C100S +rtos:freertos mcu:GD32VF103 +rtos:freertos mcu:MCXA15 +rtos:freertos mcu:MKL25ZXX +rtos:freertos mcu:MSP430x5xx +rtos:freertos mcu:FT90X +rtos:freertos mcu:SAMD11 +rtos:freertos mcu:VALENTYUSB_EPTRI +rtos:freertos mcu:RAXXX +rtos:freertos mcu:STM32L0 +rtos:freertos board:lpcxpresso11u37 +rtos:freertos board:lpcxpresso1347 +rtos:freertos family:broadcom_32bit +rtos:freertos family:broadcom_64bit +rtos:freertos family:nuc121_125 +rtos:freertos family:hpmicro diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt b/examples/device/audio_4_channel_mic/src/CMakeLists.txt similarity index 100% rename from examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt rename to examples/device/audio_4_channel_mic/src/CMakeLists.txt diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index c9c6dd46ce..38f42d11f8 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -72,21 +72,18 @@ audio20_control_range_4_n_t(1) sampleFreqRng; // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; -void led_blinking_task(void); -void audio_task(void); +void led_blinking_task(void *param); +void audio_task(void *param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif /*------------- MAIN -------------*/ int main(void) { board_init(); - // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO}; - tusb_init(BOARD_TUD_RHPORT, &dev_init); - - board_init_after_tusb(); - // Init values sampFreq = AUDIO_SAMPLE_RATE; clkValid = 1; @@ -112,11 +109,25 @@ int main(void) { *p_buff++ = (uint16_t) ((int16_t) (sinf(t) * 750) + 6000); } +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else + // init device stack on configured roothub port + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + while (1) { tud_task();// tinyusb device task - led_blinking_task(); - audio_task(); + led_blinking_task(NULL); + audio_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -153,14 +164,23 @@ void tud_resume_cb(void) { // This task simulates an audio receive callback, one frame is received every 1ms. // We assume that the audio data is read from an I2S buffer. // In a real application, this would be replaced with actual I2S receive callback. -void audio_task(void) { +void audio_task(void *param) { + (void) param; static uint32_t start_ms = 0; - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms == curr_ms) { - return; // not enough time + + while (1) { + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); + } + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); +#else + return; +#endif } - start_ms = curr_ms; - tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); } //--------------------------------------------------------------------+ @@ -403,16 +423,91 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) { - static uint32_t start_ms = 0; +void led_blinking_task(void *param) { + (void) param; static bool led_state = false; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; +#endif + + board_led_write(led_state); + led_state = 1 - led_state;// toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 + +void app_main(void) { + main(); +} +#else + #define USBD_STACK_SIZE ((4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1)) +#endif + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE + +#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 audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; +#endif + +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + + while (1) { + tud_task();// tinyusb device task } - start_ms += blink_interval_ms; +} - board_led_write(led_state); - led_state = 1 - led_state;// toggle +static void freertos_init(void) { +#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 - 2, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_taskdef); +#else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); + xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif } + +#endif diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 085f9d1688..0da1b9c00b 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -57,6 +57,11 @@ extern "C" { #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt deleted file mode 100644 index 66ef19fbc4..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -# Need to set Espressif defaults before project() is called -if(FAMILY STREQUAL "espressif") - list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") -endif() - -project(audio_4_channel_mic_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - -# Add libm for GCC -if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_libraries(${PROJECT_NAME} PUBLIC m) -endif() - -# 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_NAME} freertos) diff --git a/examples/device/audio_4_channel_mic_freertos/CMakePresets.json b/examples/device/audio_4_channel_mic_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile deleted file mode 100644 index 3c421af747..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE = \ - src/main.c \ - src/usb_descriptors.c - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt deleted file mode 100644 index 1fd6b4b8a6..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ /dev/null @@ -1,22 +0,0 @@ -mcu:CH32F20X -mcu:CH32V103 -mcu:CH32V20X -mcu:CH32V307 -mcu:CH583 -mcu:CXD56 -mcu:F1C100S -mcu:GD32VF103 -mcu:MCXA15 -mcu:MKL25ZXX -mcu:MSP430x5xx -mcu:FT90X -mcu:SAMD11 -mcu:VALENTYUSB_EPTRI -mcu:RAXXX -mcu:STM32L0 -board:lpcxpresso11u37 -board:lpcxpresso1347 -family:broadcom_32bit -family:broadcom_64bit -family:nuc121_125 -family:hpmicro diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c deleted file mode 100644 index eac66a4ef0..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber - * - * 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. - * - */ - -/* plot_audio_samples.py requires following modules: - * $ sudo apt install libportaudio - * $ pip3 install sounddevice matplotlib - * - * Then run - * $ python3 plot_audio_samples.py - */ - -#include -#include -#include -#include - -#include "bsp/board_api.h" -#include "tusb.h" - -#ifdef ESP_PLATFORM - // ESP-IDF need "freertos/" prefix in include path. - // CFG_TUSB_OS_INC_PATH should be defined accordingly. - #include "freertos/FreeRTOS.h" - #include "freertos/queue.h" - #include "freertos/semphr.h" - #include "freertos/task.h" - #include "freertos/timers.h" - - #define USBD_STACK_SIZE 4096 -#else - - #include "FreeRTOS.h" - #include "queue.h" - #include "semphr.h" - #include "task.h" - #include "timers.h" - - // Increase stack size when debug log is enabled - #define USBD_STACK_SIZE (4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1) -#endif - -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE -#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ -#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE - -/* 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 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 audio_stack[AUDIO_STACK_SIZE]; -StaticTask_t audio_taskdef; -#endif - -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; - -// Audio controls -// Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 -uint32_t sampFreq; -uint8_t clkValid; - -// Range states -audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state - -// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; - -void led_blinking_task(void *param); -void usb_device_task(void *param); -void audio_isr_task(void *param); - -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - // Init values - sampFreq = AUDIO_SAMPLE_RATE; - clkValid = 1; - - sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; - sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; - sampleFreqRng.subrange[0].bRes = 0; - - // Generate dummy data - uint16_t *p_buff = i2s_dummy_buffer; - uint16_t dataVal = 0; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE / 1000; cnt++) { - // CH0 saw wave - *p_buff++ = dataVal; - // CH1 inverted saw wave - *p_buff++ = 3200 + AUDIO_SAMPLE_RATE / 1000 - dataVal; - dataVal += 32; - // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE / 1000 / 2) ? 3400 : 5000; - // CH4 sinus wave - float t = 2 * 3.1415f * cnt / (AUDIO_SAMPLE_RATE / 1000); - *p_buff++ = (uint16_t) ((int16_t) (sinf(t) * 750) + 6000); - } - -#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 - 2, usb_device_stack, &usb_device_taskdef); - - // Audio receive (I2S) ISR simulation - // To simulate a ISR the priority is set to the highest - xTaskCreateStatic(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_taskdef); -#else - xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); - xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); - xTaskCreate(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); -#endif - - // only start scheduler for non-espressif mcu - #ifndef ESP_PLATFORM - vTaskStartScheduler(); - #endif - - return 0; -} - -#ifdef ESP_PLATFORM -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); - - board_init_after_tusb(); - - // RTOS forever loop - while (1) { - // tinyusb device task - 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; -} - -//--------------------------------------------------------------------+ -// AUDIO Task -//--------------------------------------------------------------------+ - -// This task simulates an audio receive ISR, one frame is received every 1ms. -// We assume that the audio data is read from an I2S buffer. -// In a real application, this would be replaced with actual I2S receive callback. -void audio_isr_task(void *param) { - (void) param; - while (1) { - vTaskDelay(1); - tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); - } -} - -//--------------------------------------------------------------------+ -// Application Callback API Implementations -//--------------------------------------------------------------------+ - -// Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) ep; - - return false;// Yet not implemented -} - -// Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) itf; - - return false;// Yet not implemented -} - -// Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - (void) itf; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // If request is for our feature unit - if (entityID == 2) { - switch (ctrlSel) { - case AUDIO20_FU_CTRL_MUTE: - // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - - mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; - - TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; - - case AUDIO20_FU_CTRL_VOLUME: - // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - - volume[channelNum] = (uint16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; - TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) ep; - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) itf; - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Input terminal (Microphone input) - if (entityID == 1) { - switch (ctrlSel) { - case AUDIO20_TE_CTRL_CONNECTOR: { - // The terminal connector control only has a get request with only the CUR attribute. - audio20_desc_channel_cluster_t ret; - - // Those are dummy values for now - ret.bNrChannels = 1; - ret.bmChannelConfig = 0; - ret.iChannelNames = 0; - - TU_LOG1(" Get terminal connector\r\n"); - - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); - } break; - - // Unknown/Unsupported control selector - default: - TU_BREAKPOINT(); - return false; - } - } - - // Feature unit - if (entityID == 2) { - switch (ctrlSel) { - case AUDIO20_FU_CTRL_MUTE: - // Audio control mute cur parameter block consists of only one byte - we thus can send it right away - // There does not exist a range parameter block for mute - TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); - - case AUDIO20_FU_CTRL_VOLUME: - switch (p_request->bRequest) { - case AUDIO20_CS_REQ_CUR: - TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - - case AUDIO20_CS_REQ_RANGE: - TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); - - // Copy values - only for testing - better is version below - audio20_control_range_2_n_t(1) ret; - - ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90;// -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps - - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - break; - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - - // Clock Source unit - if (entityID == 4) { - switch (ctrlSel) { - case AUDIO20_CS_CTRL_SAM_FREQ: - // channelNum is always zero in this case - switch (p_request->bRequest) { - case AUDIO20_CS_REQ_CUR: - TU_LOG1(" Get Sample Freq.\r\n"); - // Buffered control transfer is needed for IN flow control to work - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - - case AUDIO20_CS_REQ_RANGE: - TU_LOG1(" Get Sample Freq. range\r\n"); - return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - break; - - case AUDIO20_CS_CTRL_CLK_VALID: - // Only cur attribute exists for this request - TU_LOG1(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - - TU_LOG1(" Unsupported entity: %d\r\n", entityID); - return false;// Yet not implemented -} - -///--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinking_task(void *param) { - (void) param; - static bool led_state = false; - - while (1) { - // Blink every interval ms - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - - board_led_write(led_state); - led_state = 1 - led_state;// toggle - } -} diff --git a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py deleted file mode 100755 index 3b3cd0d837..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -import sounddevice as sd -import matplotlib.pyplot as plt -import numpy as np -import platform - - -def find_windows_input_device(name_hint, channels, preferred_apis=None): - """Pick a Windows input device index from query_devices() output.""" - preferred_apis = preferred_apis or [] - name_hint = name_hint.lower() - candidates = [] - - for index in range(len(sd.query_devices())): - device_info = sd.query_devices(index) - max_input_channels = int(device_info.get('max_input_channels', 0)) - - if max_input_channels < channels: - continue - - device_name = str(device_info.get('name', '')).lower() - if name_hint not in device_name: - continue - - score = 0 - - # Prefer exact channel matches to avoid selecting a different stream layout. - if max_input_channels == channels: - score += 100 - else: - score += 10 - - hostapi_index = int(device_info.get('hostapi', -1)) - api_name = '' - if hostapi_index >= 0: - hostapi_info = sd.query_hostapis(hostapi_index) - api_name = str(hostapi_info.get('name', '')).lower() - - for priority, api_hint in enumerate(preferred_apis): - if api_hint in api_name: - score += 50 - priority - break - - candidates.append((score, index)) - - if not candidates: - raise ValueError( - 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels) - ) - - return max(candidates, key=lambda item: item[0])[1] - -if __name__ == '__main__': - - # If you got "ValueError: No input device matching", that is because your PC name example device - # differently from tested list below. Uncomment the next line to see full list and try to pick correct one - # print(sd.query_devices()) - - fs = 48000 # Sample rate - duration = 100e-3 # Duration of recording - - if platform.system() == 'Windows': - # Match by substring to support names like "Microphone (2- MicNode_4_Ch)". - device = find_windows_input_device('micnode_4_ch', channels=4, preferred_apis=['wdm-ks', 'wasapi', 'mme']) - elif platform.system() == 'Darwin': - device = 'MicNode_4_Ch' - else: - device ='default' - - myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=4, dtype='int16', device=device) - print('Waiting...') - sd.wait() # Wait until recording is finished - print('Done!') - - time = np.arange(0, duration, 1 / fs) # time vector - plt.plot(time, myrecording) - plt.xlabel('Time [s]') - plt.ylabel('Amplitude') - plt.title('MicNode 4 Channel') - plt.show() diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h deleted file mode 100644 index 74729695fd..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ /dev/null @@ -1,128 +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. - * - */ - -#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 - -// This examples use FreeRTOS -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH 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_AUDIO 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 - -//-------------------------------------------------------------------- -// AUDIO CLASS DRIVER CONFIGURATION -//-------------------------------------------------------------------- - -// Have a look into audio_device.h for all configurations -#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 - -#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) - -#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 - -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device - -#ifdef __cplusplus -} -#endif - -#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c deleted file mode 100644 index 216cd062a5..0000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c +++ /dev/null @@ -1,187 +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 "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] AUDIO | MIDI | HID | MSC | CDC [LSB] - */ -#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ - PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -static tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - - // Use Interface Association Descriptor (IAD) for Audio - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .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_AUDIO_CONTROL = 0, - ITF_NUM_AUDIO_STREAMING, - ITF_NUM_TOTAL -}; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_FOUR_CH_DESC_LEN) - -#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, 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_AUDIO 0x03 - -#elif TU_CHECK_MCU(OPT_MCU_NRF5X) - // nRF5x ISO can only be endpoint 8 - #define EPNUM_AUDIO 0x08 - -#elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) - // Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering - #define EPNUM_AUDIO 0x0A - -#else - #define EPNUM_AUDIO 0x01 -#endif - -uint8_t const desc_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_AUDIO20_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) -}; - -// 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 - return desc_configuration; -} - -//--------------------------------------------------------------------+ -// 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) - "PaniRCorp", // 1: Manufacturer - "MicNode_4_Ch", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "UAC2", // 4: Audio Interface -}; - -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); - 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; - } - - // 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/device/audio_test/CMakeLists.txt b/examples/device/audio_test/CMakeLists.txt index 3382530c6f..9dd74a62c5 100644 --- a/examples/device/audio_test/CMakeLists.txt +++ b/examples/device/audio_test/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) +# Need to set Espressif defaults before project() is called +if(FAMILY STREQUAL "espressif") + list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") +endif() + project(audio_test C CXX ASM) # Checks this example is valid for the family and initializes the project @@ -25,6 +30,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT_NAME} noos) +family_configure_device_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/device/audio_test_freertos/sdkconfig.defaults b/examples/device/audio_test/sdkconfig.defaults similarity index 100% rename from examples/device/audio_test_freertos/sdkconfig.defaults rename to examples/device/audio_test/sdkconfig.defaults diff --git a/examples/device/audio_test/skip.txt b/examples/device/audio_test/skip.txt index 42394bb117..86f089274b 100644 --- a/examples/device/audio_test/skip.txt +++ b/examples/device/audio_test/skip.txt @@ -1,5 +1,26 @@ -mcu:SAMD11 -mcu:SAME5X -mcu:SAMG -family:espressif -mcu:CH583 +rtos:noos mcu:SAMD11 +rtos:noos mcu:SAME5X +rtos:noos mcu:SAMG +rtos:noos family:espressif +rtos:noos mcu:CH583 + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V103 +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:CH32V307 +rtos:freertos mcu:CH583 +rtos:freertos mcu:CXD56 +rtos:freertos mcu:F1C100S +rtos:freertos mcu:GD32VF103 +rtos:freertos mcu:MCXA15 +rtos:freertos mcu:MKL25ZXX +rtos:freertos mcu:MSP430x5xx +rtos:freertos mcu:FT90X +rtos:freertos mcu:SAMD11 +rtos:freertos mcu:VALENTYUSB_EPTRI +rtos:freertos mcu:RAXXX +rtos:freertos family:broadcom_32bit +rtos:freertos family:broadcom_64bit +rtos:freertos board:stm32l0538disco +rtos:freertos family:nuc121_125 +rtos:freertos family:hpmicro diff --git a/examples/device/audio_test_freertos/src/CMakeLists.txt b/examples/device/audio_test/src/CMakeLists.txt similarity index 100% rename from examples/device/audio_test_freertos/src/CMakeLists.txt rename to examples/device/audio_test/src/CMakeLists.txt diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 876a41d06c..4f0fa30403 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -70,21 +70,18 @@ audio20_control_range_4_n_t(1) sampleFreqRng; uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; uint16_t startVal = 0; -void led_blinking_task(void); -void audio_task(void); +void led_blinking_task(void *param); +void audio_task(void *param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif /*------------- MAIN -------------*/ int main(void) { board_init(); - // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO}; - tusb_init(BOARD_TUD_RHPORT, &dev_init); - - board_init_after_tusb(); - // Init values sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; clkValid = 1; @@ -94,11 +91,25 @@ int main(void) { sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else + // init device stack on configured roothub port + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + while (1) { tud_task();// tinyusb device task - led_blinking_task(); - audio_task(); + led_blinking_task(NULL); + audio_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -136,17 +147,26 @@ void tud_resume_cb(void) { // This task simulates an audio receive callback, one frame is received every 1ms. // We assume that the audio data is read from an I2S buffer. // In a real application, this would be replaced with actual I2S receive callback. -void audio_task(void) { +void audio_task(void *param) { + (void) param; static uint32_t start_ms = 0; - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms == curr_ms) { - return; // not enough time - } - start_ms = curr_ms; - for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { - test_buffer_audio[cnt] = startVal++; + + while (1) { + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { + test_buffer_audio[cnt] = startVal++; + } + tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); + } + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); +#else + return; +#endif } - tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); } //--------------------------------------------------------------------+ @@ -397,16 +417,91 @@ bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) { - static uint32_t start_ms = 0; +void led_blinking_task(void *param) { + (void) param; static bool led_state = false; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; +#endif + + board_led_write(led_state); + led_state = 1 - led_state;// toggle } - start_ms += blink_interval_ms; +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 - board_led_write(led_state); - led_state = 1 - led_state;// toggle +void app_main(void) { + main(); } +#else + #define USBD_STACK_SIZE ((4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1)) +#endif + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE + +#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 audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; +#endif + +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + + while (1) { + tud_task();// tinyusb device task + } +} + +static void freertos_init(void) { +#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(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_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(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif +} + +#endif diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index e311d892f4..ffdb2d5c9a 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -57,6 +57,11 @@ extern "C" { #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/device/audio_test_freertos/CMakeLists.txt b/examples/device/audio_test_freertos/CMakeLists.txt deleted file mode 100644 index a39e568227..0000000000 --- a/examples/device/audio_test_freertos/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -# Need to set Espressif defaults before project() is called -if(FAMILY STREQUAL "espressif") - list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") -endif() - -project(audio_test_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} 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_NAME} freertos) diff --git a/examples/device/audio_test_freertos/CMakePresets.json b/examples/device/audio_test_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/device/audio_test_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile deleted file mode 100644 index 3c421af747..0000000000 --- a/examples/device/audio_test_freertos/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE = \ - src/main.c \ - src/usb_descriptors.c - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt deleted file mode 100644 index 660bacd259..0000000000 --- a/examples/device/audio_test_freertos/skip.txt +++ /dev/null @@ -1,20 +0,0 @@ -mcu:CH32F20X -mcu:CH32V103 -mcu:CH32V20X -mcu:CH32V307 -mcu:CH583 -mcu:CXD56 -mcu:F1C100S -mcu:GD32VF103 -mcu:MCXA15 -mcu:MKL25ZXX -mcu:MSP430x5xx -mcu:FT90X -mcu:SAMD11 -mcu:VALENTYUSB_EPTRI -mcu:RAXXX -family:broadcom_32bit -family:broadcom_64bit -board:stm32l0538disco -family:nuc121_125 -family:hpmicro diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c deleted file mode 100644 index cf2fb74d15..0000000000 --- a/examples/device/audio_test_freertos/src/main.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber - * - * 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. - * - */ - -/* plot_audio_samples.py requires following modules: - * $ sudo apt install libportaudio - * $ pip3 install sounddevice matplotlib - * - * Then run - * $ python3 plot_audio_samples.py - */ - -#include -#include -#include - -#include "bsp/board_api.h" -#include "tusb.h" - -#ifdef ESP_PLATFORM - // ESP-IDF need "freertos/" prefix in include path. - // CFG_TUSB_OS_INC_PATH should be defined accordingly. - #include "freertos/FreeRTOS.h" - #include "freertos/queue.h" - #include "freertos/semphr.h" - #include "freertos/task.h" - #include "freertos/timers.h" - - #define USBD_STACK_SIZE 4096 -#else - - #include "FreeRTOS.h" - #include "queue.h" - #include "semphr.h" - #include "task.h" - #include "timers.h" - - // Increase stack size when debug log is enabled - #define USBD_STACK_SIZE (4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1) -#endif - -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE -#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -/* 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 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 audio_stack[AUDIO_STACK_SIZE]; -StaticTask_t audio_taskdef; -#endif - -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; - -// Audio controls -// Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 -uint32_t sampFreq; -uint8_t clkValid; - -// Range states -audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state - -// Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; -uint16_t startVal = 0; - -void led_blinking_task(void *param); -void usb_device_task(void *param); -void audio_isr_task(void *param); - -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - // Init values - sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; - clkValid = 1; - - sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; - sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; - sampleFreqRng.subrange[0].bRes = 0; - -#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); - - // Audio receive (I2S) ISR simulation - // To simulate a ISR the priority is set to the highest - xTaskCreateStatic(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_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(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); -#endif - - // only start scheduler for non-espressif mcu - #ifndef ESP_PLATFORM - vTaskStartScheduler(); - #endif - - return 0; -} - -#ifdef ESP_PLATFORM -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); - - board_init_after_tusb(); - - // RTOS forever loop - while (1) { - // tinyusb device task - 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; -} - -//--------------------------------------------------------------------+ -// AUDIO Task -//--------------------------------------------------------------------+ - -// This task simulates an audio receive ISR, one frame is received every 1ms. -// We assume that the audio data is read from an I2S buffer. -// In a real application, this would be replaced with actual I2S receive callback. -void audio_isr_task(void *param) { - (void) param; - while (1) { - vTaskDelay(1); - for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { - test_buffer_audio[cnt] = startVal++; - } - tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); - } -} - -//--------------------------------------------------------------------+ -// Application Callback API Implementations -//--------------------------------------------------------------------+ - -// Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) ep; - - return false;// Yet not implemented -} - -// Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) itf; - - return false;// Yet not implemented -} - -// Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - (void) itf; - - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); - - // If request is for our feature unit - if (entityID == 2) { - switch (ctrlSel) { - case AUDIO20_FU_CTRL_MUTE: - // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - - mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; - - TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; - - case AUDIO20_FU_CTRL_VOLUME: - // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - - volume[channelNum] = (uint16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; - TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) ep; - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) itf; - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Input terminal (Microphone input) - if (entityID == 1) { - switch (ctrlSel) { - case AUDIO20_TE_CTRL_CONNECTOR: { - // The terminal connector control only has a get request with only the CUR attribute. - audio20_desc_channel_cluster_t ret; - - // Those are dummy values for now - ret.bNrChannels = 1; - ret.bmChannelConfig = (audio20_channel_config_t) 0; - ret.iChannelNames = 0; - - TU_LOG1(" Get terminal connector\r\n"); - - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); - } break; - - // Unknown/Unsupported control selector - default: - TU_BREAKPOINT(); - return false; - } - } - - // Feature unit - if (entityID == 2) { - switch (ctrlSel) { - case AUDIO20_FU_CTRL_MUTE: - // Audio control mute cur parameter block consists of only one byte - we thus can send it right away - // There does not exist a range parameter block for mute - TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); - - case AUDIO20_FU_CTRL_VOLUME: - switch (p_request->bRequest) { - case AUDIO20_CS_REQ_CUR: - TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - - case AUDIO20_CS_REQ_RANGE: - TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); - - // Copy values - only for testing - better is version below - audio20_control_range_2_n_t(1) - ret; - - ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90;// -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps - - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - break; - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - - // Clock Source unit - if (entityID == 4) { - switch (ctrlSel) { - case AUDIO20_CS_CTRL_SAM_FREQ: - // channelNum is always zero in this case - switch (p_request->bRequest) { - case AUDIO20_CS_REQ_CUR: - TU_LOG1(" Get Sample Freq.\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - - case AUDIO20_CS_REQ_RANGE: - TU_LOG1(" Get Sample Freq. range\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - break; - - case AUDIO20_CS_CTRL_CLK_VALID: - // Only cur attribute exists for this request - TU_LOG1(" Get Sample Freq. valid\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); - - // Unknown/Unsupported control - default: - TU_BREAKPOINT(); - return false; - } - } - - TU_LOG1(" Unsupported entity: %d\r\n", entityID); - return false;// Yet not implemented -} - -bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - (void) p_request; - startVal = 0; - - return true; -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinking_task(void *param) { - (void) param; - static bool led_state = false; - - while (1) { - // Blink every interval ms - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - - board_led_write(led_state); - led_state = 1 - led_state;// toggle - } -} diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py deleted file mode 100755 index b6a916be48..0000000000 --- a/examples/device/audio_test_freertos/src/plot_audio_samples.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -import sounddevice as sd -import matplotlib.pyplot as plt -import numpy as np -import platform - - -def find_windows_input_device(name_hint, channels, preferred_apis=None): - """Pick a Windows input device index from query_devices() output.""" - preferred_apis = preferred_apis or [] - name_hint = name_hint.lower() - candidates = [] - - for index in range(len(sd.query_devices())): - device_info = sd.query_devices(index) - max_input_channels = int(device_info.get('max_input_channels', 0)) - - if max_input_channels < channels: - continue - - device_name = str(device_info.get('name', '')).lower() - if name_hint not in device_name: - continue - - score = 0 - - # Prefer exact channel matches (for example 1ch source over a 4ch source). - if max_input_channels == channels: - score += 100 - else: - score += 10 - - hostapi_index = int(device_info.get('hostapi', -1)) - api_name = '' - if hostapi_index >= 0: - hostapi_info = sd.query_hostapis(hostapi_index) - api_name = str(hostapi_info.get('name', '')).lower() - - for priority, api_hint in enumerate(preferred_apis): - if api_hint in api_name: - score += 50 - priority - break - - candidates.append((score, index)) - - if not candidates: - raise ValueError( - 'No input device matching hint="{}" with at least {} channels'.format(name_hint, channels) - ) - - return max(candidates, key=lambda item: item[0])[1] - -if __name__ == '__main__': - - # If you got "ValueError: No input device matching", that is because your PC name example device - # differently from tested list below. Uncomment the next line to see full list and try to pick correct one - # print(sd.query_devices()) - - fs = 48000 # Sample rate - duration = 3 # Duration of recording - - if platform.system() == 'Windows': - # Match by substring to support names like "Microphone (2- MicNode)". - device = find_windows_input_device('micnode', channels=1, preferred_apis=['wasapi', 'mme', 'wdm-ks']) - elif platform.system() == 'Darwin': - device = 'MicNode' - else: - device ='default' - - myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype='int16', device=device) - print('Waiting...') - sd.wait() # Wait until recording is finished - print('Done!') - - time = np.arange(0, duration, 1 / fs) # time vector - plt.plot(time, myrecording) - plt.xlabel('Time [s]') - plt.ylabel('Amplitude') - plt.title('MicNode') - plt.show() diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h deleted file mode 100644 index 81f0c11f4e..0000000000 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ /dev/null @@ -1,128 +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. - * - */ - -#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 - -// This examples use FreeRTOS -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH 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 - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - -/* 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_AUDIO 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 - -//-------------------------------------------------------------------- -// AUDIO CLASS DRIVER CONFIGURATION -//-------------------------------------------------------------------- - -// Have a look into audio_device.h for all configurations -#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 - -#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below -#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device - -#ifdef __cplusplus -} -#endif - -#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c deleted file mode 100644 index 37ebf84d32..0000000000 --- a/examples/device/audio_test_freertos/src/usb_descriptors.c +++ /dev/null @@ -1,189 +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 "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] AUDIO | MIDI | HID | MSC | CDC [LSB] - */ -#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ - PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -static tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - - // Use Interface Association Descriptor (IAD) for Audio - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .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_AUDIO_CONTROL = 0, - ITF_NUM_AUDIO_STREAMING, - ITF_NUM_TOTAL -}; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_ONE_CH_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_AUDIO 0x03 - -#elif TU_CHECK_MCU(OPT_MCU_NRF5X) - // nRF5x ISO can only be endpoint 8 - #define EPNUM_AUDIO 0x08 - -#elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) - // Put audio iso on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering - #define EPNUM_AUDIO 0x0A - -#else - #define EPNUM_AUDIO 0x01 -#endif - -uint8_t const desc_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_AUDIO20_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) -}; - -// 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 - return desc_configuration; -} - -//--------------------------------------------------------------------+ -// 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) - "PaniRCorp", // 1: Manufacturer - "MicNode", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "UAC2", // 4: Audio Interface - -}; - -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); - 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; - } - - // 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/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt index 293b497a7f..b862b33b70 100644 --- a/examples/device/cdc_msc/CMakeLists.txt +++ b/examples/device/cdc_msc/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) +# Need to set Espressif defaults before project() is called +if(FAMILY STREQUAL "espressif") + list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") +endif() + project(cdc_msc C CXX ASM) # Checks this example is valid for the family and initializes the project @@ -31,6 +36,6 @@ target_include_directories(${EXE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${EXE_NAME} ${RTOS}) diff --git a/examples/device/cdc_msc_freertos/sdkconfig.defaults b/examples/device/cdc_msc/sdkconfig.defaults similarity index 100% rename from examples/device/cdc_msc_freertos/sdkconfig.defaults rename to examples/device/cdc_msc/sdkconfig.defaults diff --git a/examples/device/cdc_msc/skip.txt b/examples/device/cdc_msc/skip.txt index b6252e4050..72118c8dbe 100644 --- a/examples/device/cdc_msc/skip.txt +++ b/examples/device/cdc_msc/skip.txt @@ -1,3 +1,24 @@ -mcu:SAMD11 -family:espressif -board:ch32v203g_r0_1v0 +rtos:noos mcu:SAMD11 +rtos:noos family:espressif +rtos:noos board:ch32v203g_r0_1v0 + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V103 +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:CH32V307 +rtos:freertos mcu:CH583 +rtos:freertos mcu:CXD56 +rtos:freertos mcu:F1C100S +rtos:freertos mcu:GD32VF103 +rtos:freertos mcu:MCXA15 +rtos:freertos mcu:MKL25ZXX +rtos:freertos mcu:MSP430x5xx +rtos:freertos mcu:FT90X +rtos:freertos mcu:SAMD11 +rtos:freertos mcu:VALENTYUSB_EPTRI +rtos:freertos mcu:RAXXX +rtos:freertos mcu:STM32L0 +rtos:freertos family:broadcom_32bit +rtos:freertos family:broadcom_64bit +rtos:freertos family:nuc121_125 +rtos:freertos family:hpmicro diff --git a/examples/device/cdc_msc_freertos/src/CMakeLists.txt b/examples/device/cdc_msc/src/CMakeLists.txt similarity index 100% rename from examples/device/cdc_msc_freertos/src/CMakeLists.txt rename to examples/device/cdc_msc/src/CMakeLists.txt diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index b00a0e3a99..1318f6f321 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -44,25 +44,38 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; static bool blink_enable = true; -void led_blinking_task(void); -void cdc_task(void); +void led_blinking_task(void *param); +void cdc_task(void *param); +extern void msc_disk_init(void); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif /*------------- MAIN -------------*/ int main(void) { board_init(); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else // init device stack on configured roothub port tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); + msc_disk_init(); while (1) { tud_task(); // tinyusb device task - led_blinking_task(); + led_blinking_task(NULL); - cdc_task(); + cdc_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -96,38 +109,49 @@ void tud_resume_cb(void) { //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void) { - // connected() check for DTR bit - // Most but not all terminal client set this when making connection - // if ( tud_cdc_connected() ) - { - // connected and there are data available - if (tud_cdc_available()) { - // read data - char buf[64]; - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - (void)count; - - // Echo back - // Note: Skip echo by commenting out write() and write_flush() - // for throughput test e.g - // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 - tud_cdc_write(buf, count); +void cdc_task(void *param) { + (void) param; + + while (1) { + // connected() check for DTR bit + // Most but not all terminal client set this when making connection + // if ( tud_cdc_connected() ) + { + // connected and there are data available + while (tud_cdc_available()) { + // read data + char buf[64]; + uint32_t count = tud_cdc_read(buf, sizeof(buf)); + (void)count; + + // Echo back + // Note: Skip echo by commenting out write() and write_flush() + // for throughput test e.g + // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 + tud_cdc_write(buf, count); + } + tud_cdc_write_flush(); - } - // Press on-board button to send Uart status notification - static cdc_notify_uart_state_t uart_state = {.value = 0}; + // Press on-board button to send Uart status notification + static cdc_notify_uart_state_t uart_state = {.value = 0}; - static uint32_t btn_prev = 0; - const uint32_t btn = board_button_read(); + static uint32_t btn_prev = 0; + const uint32_t btn = board_button_read(); - if ((btn_prev == 0u) && (btn != 0u)) { - uart_state.dsr ^= 1; - uart_state.dcd ^= 1; - tud_cdc_notify_uart_state(&uart_state); + if ((btn_prev == 0u) && (btn != 0u)) { + uart_state.dsr ^= 1; + uart_state.dcd ^= 1; + tud_cdc_notify_uart_state(&uart_state); + } + btn_prev = btn; } - btn_prev = btn; + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); +#else + break; +#endif } } @@ -154,18 +178,109 @@ void tud_cdc_rx_cb(uint8_t itf) { //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) { - static uint32_t start_ms = 0; +void led_blinking_task(void *param) { + (void) param; static bool led_state = false; +#if CFG_TUSB_OS != OPT_OS_FREERTOS + static uint32_t start_ms = 0; +#endif - if (blink_enable) { + while (1) { + if (!blink_enable) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); + continue; +#else + return; +#endif + } + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else // Blink every interval ms if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; +#endif board_led_write(led_state); led_state = !led_state; + +#if CFG_TUSB_OS != OPT_OS_FREERTOS + break; +#endif } } + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 + +void app_main(void) { + main(); +} +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) +#endif + +#define CDC_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 3 : 2)) +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE + +#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 cdc_stack[CDC_STACK_SIZE]; +StaticTask_t cdc_taskdef; +#endif + +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + msc_disk_init(); + + while (1) { + tud_task();// tinyusb device task + tud_cdc_write_flush(); + } +} + +static void freertos_init(void) { +#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(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); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); +#endif + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif +} + +#endif diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 017acd0392..2684eec8e6 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -28,6 +28,40 @@ #if CFG_TUD_MSC +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#define CFG_EXAMPLE_MSC_ASYNC_IO 1 +#else +#define CFG_EXAMPLE_MSC_ASYNC_IO 0 +#endif + +// Simulate read/write operation delay +#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0 + +#if CFG_EXAMPLE_MSC_ASYNC_IO +#define IO_STACK_SIZE configMINIMAL_STACK_SIZE + +typedef struct { + uint8_t lun; + bool is_read; + uint32_t lba; + uint32_t offset; + void *buffer; + uint32_t bufsize; +} io_ops_t; + +QueueHandle_t io_queue; +#if configSUPPORT_STATIC_ALLOCATION +uint8_t io_queue_buf[sizeof(io_ops_t)]; +StaticQueue_t io_queue_static; +StackType_t io_stack[IO_STACK_SIZE]; +StaticTask_t io_taskdef; +#endif + +static void io_task(void *params); +#endif + +void msc_disk_init(void); + // whether host does safe-eject static bool ejected = false; @@ -118,6 +152,45 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { {README_CONTENTS} }; +void msc_disk_init(void) { +#if CFG_EXAMPLE_MSC_ASYNC_IO +#if configSUPPORT_STATIC_ALLOCATION + io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static); + xTaskCreateStatic(io_task, "io", IO_STACK_SIZE, NULL, 2, io_stack, &io_taskdef); +#else + io_queue = xQueueCreate(1, sizeof(io_ops_t)); + xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL); +#endif +#endif +} + +#if CFG_EXAMPLE_MSC_ASYNC_IO +static void io_task(void *params) { + (void) params; + io_ops_t io_ops; + + while (1) { + if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) { + uint8_t *addr = (uint8_t *) (uintptr_t) (msc_disk[io_ops.lba] + io_ops.offset); + int32_t nbytes = (int32_t) io_ops.bufsize; + + if (io_ops.is_read) { + memcpy(io_ops.buffer, addr, io_ops.bufsize); + } else { +#ifndef CFG_EXAMPLE_MSC_READONLY + memcpy(addr, io_ops.buffer, io_ops.bufsize); +#else + nbytes = -1; +#endif + } + + tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); + tud_msc_async_io_done(nbytes, false); + } + } +} +#endif + // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. @@ -183,18 +256,27 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff // out of ramdisk if (lba >= DISK_BLOCK_NUM) { - return -1; + return TUD_MSC_RET_ERROR; } // Check for overflow of offset + bufsize if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { - return -1; + return TUD_MSC_RET_ERROR; } +#if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = {.is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; + + // Send IO operation to IO task + TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); + + return TUD_MSC_RET_ASYNC; +#else uint8_t const *addr = msc_disk[lba] + offset; (void) memcpy(buffer, addr, bufsize); return (int32_t) bufsize; +#endif } bool tud_msc_is_writable_cb(uint8_t lun) { @@ -214,12 +296,27 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * // out of ramdisk if (lba >= DISK_BLOCK_NUM) { - return -1; + return TUD_MSC_RET_ERROR; + } + + // Check for overflow of offset + bufsize + if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { + return TUD_MSC_RET_ERROR; } #ifndef CFG_EXAMPLE_MSC_READONLY +#if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = {.is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; + + // Send IO operation to IO task + TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); + + return TUD_MSC_RET_ASYNC; +#else uint8_t *addr = msc_disk[lba] + offset; (void) memcpy(addr, buffer, bufsize); + tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); +#endif #else (void) lba; (void) offset; diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index f0709d8fbb..13e2701754 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt deleted file mode 100644 index 1eafd529ab..0000000000 --- a/examples/device/cdc_msc_freertos/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -# Need to set Espressif defaults before project() is called -if(FAMILY STREQUAL "espressif") - list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") -endif() - -project(cdc_msc_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} 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_NAME} freertos) diff --git a/examples/device/cdc_msc_freertos/CMakePresets.json b/examples/device/cdc_msc_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/device/cdc_msc_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile deleted file mode 100644 index dbab13395c..0000000000 --- a/examples/device/cdc_msc_freertos/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE = \ - src/main.c \ - src/msc_disk.c \ - src/usb_descriptors.c - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt deleted file mode 100644 index 48781de842..0000000000 --- a/examples/device/cdc_msc_freertos/skip.txt +++ /dev/null @@ -1,20 +0,0 @@ -mcu:CH32F20X -mcu:CH32V103 -mcu:CH32V20X -mcu:CH32V307 -mcu:CH583 -mcu:CXD56 -mcu:F1C100S -mcu:GD32VF103 -mcu:MCXA15 -mcu:MKL25ZXX -mcu:MSP430x5xx -mcu:FT90X -mcu:SAMD11 -mcu:VALENTYUSB_EPTRI -mcu:RAXXX -mcu:STM32L0 -family:broadcom_32bit -family:broadcom_64bit -family:nuc121_125 -family:hpmicro diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c deleted file mode 100644 index 4a920c90b3..0000000000 --- a/examples/device/cdc_msc_freertos/src/main.c +++ /dev/null @@ -1,239 +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 -#include - -#include "bsp/board_api.h" -#include "tusb.h" - -#ifdef ESP_PLATFORM - #define USBD_STACK_SIZE 4096 -#else - // Increase stack size when debug log is enabled - #define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) -#endif - -#define CDC_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 3 : 2)) -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTOTYPES -//--------------------------------------------------------------------+ - -/* Blink pattern - * - 250 ms : device not mounted - * - 1000 ms : device mounted - * - 2500 ms : device is suspended - */ -enum { - BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, -}; - -// static 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 cdc_stack[CDC_STACK_SIZE]; -StaticTask_t cdc_taskdef; -#endif - -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; - -static void usb_device_task(void *param); -void led_blinking_task(void* param); -void cdc_task(void *params); -extern void msc_disk_init(void); -//--------------------------------------------------------------------+ -// Main -//--------------------------------------------------------------------+ - -int main(void) { - board_init(); - - // Create task for: tinyusb, blinky, cdc -#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(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); - xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); - xTaskCreate(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); -#endif - -#ifndef ESP_PLATFORM - // only start scheduler for non-espressif mcu - vTaskStartScheduler(); -#endif - - return 0; -} - -#ifdef ESP_PLATFORM -void app_main(void) { - main(); -} -#endif - -// USB Device Driver task -// This top level thread process all usb events and invoke callbacks -static 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); - - board_init_after_tusb(); - - msc_disk_init(); - // RTOS forever loop - while (1) { - // put this thread to waiting state until there is new events - tud_task(); - - // following code only run if tud_task() process at least 1 event - tud_cdc_write_flush(); - } -} - -//--------------------------------------------------------------------+ -// 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; -} - -//--------------------------------------------------------------------+ -// USB CDC -//--------------------------------------------------------------------+ -void cdc_task(void *params) { - (void) params; - - // RTOS forever loop - while (1) { - // connected() check for DTR bit - // Most but not all terminal client set this when making connection - // if ( tud_cdc_connected() ) - { - // There are data available - while (tud_cdc_available()) { - uint8_t buf[64]; - - // read and echo back - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - (void) count; - - // Echo back - // Note: Skip echo by commenting out write() and write_flush() - // for throughput test e.g - // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 - tud_cdc_write(buf, count); - } - - tud_cdc_write_flush(); - - // Press on-board button to send Uart status notification - static uint32_t btn_prev = 0; - static cdc_notify_uart_state_t uart_state = { .value = 0 }; - const uint32_t btn = board_button_read(); - if (!btn_prev && btn) { - uart_state.dsr ^= 1; - tud_cdc_notify_uart_state(&uart_state); - } - btn_prev = btn; - } - - // For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog - vTaskDelay(1); - } -} - -// Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) rts; - - // TODO set some indicator - if (dtr) { - // Terminal connected - } else { - // Terminal disconnected - } -} - -// Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinking_task(void* param) { - (void) param; - static bool led_state = false; - - while (1) { - // Blink every interval ms - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - - board_led_write(led_state); - led_state = 1 - led_state; // toggle - } -} diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c deleted file mode 100644 index ab551c288b..0000000000 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ /dev/null @@ -1,340 +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 "bsp/board_api.h" -#include "tusb.h" - -#if CFG_TUD_MSC - -// Use async IO in example or not -#define CFG_EXAMPLE_MSC_ASYNC_IO 1 - -// Simulate read/write operation delay -#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0 - -#if CFG_EXAMPLE_MSC_ASYNC_IO -#define IO_STACK_SIZE configMINIMAL_STACK_SIZE - -typedef struct { - uint8_t lun; - bool is_read; - uint32_t lba; - uint32_t offset; - void* buffer; - uint32_t bufsize; -} io_ops_t; - -QueueHandle_t io_queue; -#if configSUPPORT_STATIC_ALLOCATION -uint8_t io_queue_buf[sizeof(io_ops_t)]; -StaticQueue_t io_queue_static; -StackType_t io_stack[IO_STACK_SIZE]; -StaticTask_t io_taskdef; -#endif - -static void io_task(void *params); -#endif - -void msc_disk_init(void); - -// whether host does safe-eject -static bool ejected = false; - -// Some MCU doesn't have enough 8KB SRAM to store the whole disk -// We will use Flash as read-only disk with board that has -// CFG_EXAMPLE_MSC_READONLY defined - -#define README_CONTENTS \ -"This is tinyusb's MassStorage Class demo.\r\n\r\n\ -If you find any bugs or get any questions, feel free to file an\r\n\ -issue at github.com/hathach/tinyusb" - -enum { - DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount - DISK_BLOCK_SIZE = 512 -}; - -static -#ifdef CFG_EXAMPLE_MSC_READONLY -const -#endif -uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = -{ - //------------- Block0: Boot Sector -------------// - // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; - // sector_per_cluster = 1; reserved_sectors = 1; - // fat_num = 1; fat12_root_entry_num = 16; - // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; - // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; - // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; - // FAT magic code at offset 510-511 - { - 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, - 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , - 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, - - // Zero up to 2 last bytes of FAT magic code - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA - }, - - //------------- Block1: FAT12 Table -------------// - { - 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file - }, - - //------------- Block2: Root Directory -------------// - { - // first entry is volume label - 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // second entry is readme file - 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, - 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, - sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) - }, - - //------------- Block3: Readme Content -------------// - README_CONTENTS -}; - -#if CFG_EXAMPLE_MSC_ASYNC_IO -void msc_disk_init(void) { - -#if configSUPPORT_STATIC_ALLOCATION - io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static); - xTaskCreateStatic(io_task, "io", IO_STACK_SIZE, NULL, 2, io_stack, &io_taskdef); -#else - io_queue = xQueueCreate(1, sizeof(io_ops_t)); - xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL); -#endif -} - -static void io_task(void *params) { - (void) params; - io_ops_t io_ops; - while (1) { - if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) { - uint8_t* addr = (uint8_t*) (uintptr_t) (msc_disk[io_ops.lba] + io_ops.offset); - int32_t nbytes = (int32_t) io_ops.bufsize; - if (io_ops.is_read) { - memcpy(io_ops.buffer, addr, io_ops.bufsize); - } else { -#ifndef CFG_EXAMPLE_MSC_READONLY - memcpy((uint8_t*) addr, io_ops.buffer, io_ops.bufsize); -#else - nbytes = -1; // failed to write -#endif - } - - tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); - tud_msc_async_io_done(nbytes, false); - } - } -} - -#else -void msc_disk_init() {} -#endif - -// Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response -// Some inquiry_resp's fields are already filled with default values, application can update them -// Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp, uint32_t bufsize) { - (void) lun; - (void) bufsize; - const char vid[] = "TinyUSB"; - const char pid[] = "Mass Storage"; - const char rev[] = "1.0"; - - strncpy((char*) inquiry_resp->vendor_id, vid, 8); - strncpy((char*) inquiry_resp->product_id, pid, 16); - strncpy((char*) inquiry_resp->product_rev, rev, 4); - - return sizeof(scsi_inquiry_resp_t); // 36 bytes -} - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun) { - (void) lun; - - // RAM disk is ready until ejected - if (ejected) { - // Additional Sense 3A-00 is NOT_FOUND - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); - return false; - } - - return true; -} - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { - (void) lun; - *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; -} - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { - (void) lun; - (void) power_condition; - - if (load_eject) { - if (start) { - // load disk storage - } else { - // unload disk storage - ejected = true; - } - } - - return true; -} - -// Callback invoked when received READ10 command. -// Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { - (void) lun; - - // out of ramdisk - if (lba >= DISK_BLOCK_NUM) { - return TUD_MSC_RET_ERROR; - } - - // Check for overflow of offset + bufsize - if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { - return TUD_MSC_RET_ERROR; - } - - #if CFG_EXAMPLE_MSC_ASYNC_IO - io_ops_t io_ops = {.is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; - - // Send IO operation to IO task - TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); - - return TUD_MSC_RET_ASYNC; - #else - uint8_t const *addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); - return bufsize; - #endif -} - -bool tud_msc_is_writable_cb (uint8_t lun) { - (void) lun; - - #ifdef CFG_EXAMPLE_MSC_READONLY - return false; - #else - return true; - #endif -} - -// Callback invoked when received WRITE10 command. -// Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { - // out of ramdisk - if (lba >= DISK_BLOCK_NUM) { - return TUD_MSC_RET_ERROR; - } - - // Check for overflow of offset + bufsize - if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { - return TUD_MSC_RET_ERROR; - } - -#ifdef CFG_EXAMPLE_MSC_READONLY - (void) lun; - (void) buffer; - return bufsize; -#elif CFG_EXAMPLE_MSC_ASYNC_IO - io_ops_t io_ops = {.is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; - - // Send IO operation to IO task - TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); - - return TUD_MSC_RET_ASYNC; - #else - uint8_t *addr = msc_disk[lba] + offset; - memcpy(addr, buffer, bufsize); - tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); - - return bufsize; -#endif -} - -// Callback invoked when received an SCSI command not in built-in list below -// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE -// - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { - (void) lun; - (void) scsi_cmd; - (void) buffer; - (void) bufsize; - - // currently no other commands are supported - - // Set Sense = Invalid Command Operation - (void) tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - return -1; // stall/failed command request; -} - -#endif diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h deleted file mode 100644 index a78f2ea05d..0000000000 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ /dev/null @@ -1,125 +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. - * - */ - -#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 board.mk -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -// This examples use FreeRTOS -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH freertos/ -#endif - -// can be defined by compiler in DEBUG build -#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 1 -#define CFG_TUD_MSC 1 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 - -#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint - -// CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster. -// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support -#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -// MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_EP_BUFSIZE 512 - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c deleted file mode 100644 index f5b015051c..0000000000 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ /dev/null @@ -1,288 +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 "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) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ - PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) - -#define USB_VID 0xCafe -#define USB_BCD 0x0200 - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -static tusb_desc_device_t const desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = USB_BCD, - - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = USB_VID, - .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_CDC = 0, - ITF_NUM_CDC_DATA, - ITF_NUM_MSC, - ITF_NUM_TOTAL -}; - -#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, 5 Bulk etc ... - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x82 - - #define EPNUM_MSC_OUT 0x05 - #define EPNUM_MSC_IN 0x85 - -#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_CDC_NOTIF 0x83 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x81 - - #define EPNUM_MSC_OUT 0x05 - #define EPNUM_MSC_IN 0x84 - -#elif CFG_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 - #if TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) - // Put bulk on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x08 - #define EPNUM_CDC_IN 0x89 - - #define EPNUM_MSC_OUT 0x0A - #define EPNUM_MSC_IN 0x8B - #else - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x83 - - #define EPNUM_MSC_OUT 0x04 - #define EPNUM_MSC_IN 0x85 - #endif - -#else - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_OUT 0x02 - #define EPNUM_CDC_IN 0x82 - - #define EPNUM_MSC_OUT 0x03 - #define EPNUM_MSC_IN 0x83 - -#endif - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) - -static 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 notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), - - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), -}; - -#if TUD_OPT_HIGH_SPEED -// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration - -// high speed configuration -static 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 notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), - - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), -}; - -// other speed configuration -static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; - -// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -static tusb_desc_device_qualifier_t const desc_device_qualifier = -{ - .bLength = sizeof(tusb_desc_device_qualifier_t), - .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, - .bcdUSB = USB_BCD, - - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .bNumConfigurations = 0x01, - .bReserved = 0x00 -}; - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. -// device_qualifier descriptor describes information about a high-speed capable device that would -// change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) { - return (uint8_t const*) &desc_device_qualifier; -} - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { - (void) index; // for multiple configurations - - // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG - memcpy(desc_other_speed_config, - (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, - CONFIG_TOTAL_LEN); - - desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; - - return desc_other_speed_config; -} - -#endif // highspeed - -// 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 -static 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 - "TinyUSB CDC", // 4: CDC Interface - "TinyUSB MSC", // 5: MSC Interface -}; - -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); - 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; } - - // 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/device/freertos_noos_merge_todo.md b/examples/device/freertos_noos_merge_todo.md new file mode 100644 index 0000000000..cb05c97dc9 --- /dev/null +++ b/examples/device/freertos_noos_merge_todo.md @@ -0,0 +1,14 @@ +# FreeRTOS/No-OS Example Merge TODO + +Goal: shrink paired no-OS and FreeRTOS examples into one directory where the build selects the RTOS with `RTOS=freertos` / `-DRTOS=freertos`. + +- [x] Add RTOS-aware `skip.txt` entries with `rtos: `. +- [x] Merge `audio_test_freertos` into `audio_test`. +- [x] Merge `audio_4_channel_mic_freertos` into `audio_4_channel_mic`. +- [x] Add FreeRTOS support to `uac2_speaker_fb`. +- [x] Merge `cdc_msc_freertos` into `cdc_msc`. +- [x] Merge `hid_composite_freertos` into `hid_composite`. +- [x] Merge `midi_test_freertos` into `midi_test`. +- [x] Add ESP-IDF component metadata for merged examples that support Espressif. +- [x] Update Espressif build discovery for merged example names. +- [x] Remove merged `_freertos` entries from the device CMake example list. diff --git a/examples/device/hid_composite/CMakeLists.txt b/examples/device/hid_composite/CMakeLists.txt index f1ddbd125d..5776ab9673 100644 --- a/examples/device/hid_composite/CMakeLists.txt +++ b/examples/device/hid_composite/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) +# Need to set Espressif defaults before project() is called +if(FAMILY STREQUAL "espressif") + list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") +endif() + project(hid_composite C CXX ASM) # Checks this example is valid for the family and initializes the project @@ -24,6 +29,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT_NAME} noos) +family_configure_device_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/device/hid_composite_freertos/sdkconfig.defaults b/examples/device/hid_composite/sdkconfig.defaults similarity index 100% rename from examples/device/hid_composite_freertos/sdkconfig.defaults rename to examples/device/hid_composite/sdkconfig.defaults diff --git a/examples/device/hid_composite/skip.txt b/examples/device/hid_composite/skip.txt index 2c6c2a64c6..e93f35f24b 100644 --- a/examples/device/hid_composite/skip.txt +++ b/examples/device/hid_composite/skip.txt @@ -1 +1,20 @@ -family:espressif +rtos:noos family:espressif + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V103 +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:CH32V307 +rtos:freertos mcu:CH583 +rtos:freertos mcu:CXD56 +rtos:freertos mcu:F1C100S +rtos:freertos mcu:GD32VF103 +rtos:freertos mcu:MCXA15 +rtos:freertos mcu:MKL25ZXX +rtos:freertos mcu:MSP430x5xx +rtos:freertos mcu:FT90X +rtos:freertos mcu:SAMD11 +rtos:freertos mcu:VALENTYUSB_EPTRI +rtos:freertos mcu:RAXXX +rtos:freertos family:broadcom_32bit +rtos:freertos family:broadcom_64bit +rtos:freertos family:hpmicro diff --git a/examples/device/hid_composite_freertos/src/CMakeLists.txt b/examples/device/hid_composite/src/CMakeLists.txt similarity index 100% rename from examples/device/hid_composite_freertos/src/CMakeLists.txt rename to examples/device/hid_composite/src/CMakeLists.txt diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 7c9d5af8df..089ff3ff1e 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -49,13 +49,21 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinking_task(void); -void hid_task(void); +void led_blinking_task(void *param); +void hid_task(void *param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif /*------------- MAIN -------------*/ int main(void) { board_init(); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else // init device stack on configured roothub port tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); @@ -64,9 +72,12 @@ int main(void) { while (1) { tud_task(); // tinyusb device task - led_blinking_task(); - hid_task(); + led_blinking_task(NULL); + hid_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -204,26 +215,38 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) { // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete -void hid_task(void) { - // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; +void hid_task(void *param) { + (void) param; - if (tusb_time_millis_api() - start_ms < interval_ms) { - return; // not enough time - } - start_ms += interval_ms; - - uint32_t const btn = board_button_read(); - - // Remote wakeup - if (tud_suspended() && btn != 0u) { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - tud_remote_wakeup(); - } else { - // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() - send_hid_report(REPORT_ID_KEYBOARD, btn); + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(pdMS_TO_TICKS(10)); +#else + // Poll every 10ms + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; + + if (tusb_time_millis_api() - start_ms < interval_ms) { + return; // not enough time + } + start_ms += interval_ms; +#endif + + uint32_t const btn = board_button_read(); + + // Remote wakeup + if (tud_suspended() && btn != 0u) { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + } else { + // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() + send_hid_report(REPORT_ID_KEYBOARD, btn); + } + +#if CFG_TUSB_OS != OPT_OS_FREERTOS + break; +#endif } } @@ -288,21 +311,108 @@ void tud_hid_set_report_cb( //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) { - static uint32_t start_ms = 0; +void led_blinking_task(void *param) { + (void) param; static bool led_state = false; +#if CFG_TUSB_OS != OPT_OS_FREERTOS + static uint32_t start_ms = 0; +#endif - // blink is disabled - if (0u == blink_interval_ms) { - return; + while (1) { + // blink is disabled + if (0u == blink_interval_ms) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); + continue; +#else + return; +#endif + } + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; +#endif + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + +#if CFG_TUSB_OS != OPT_OS_FREERTOS + break; +#endif } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 + +void app_main(void) { + main(); +} +#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 HID_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE + +#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 hid_stack[HID_STACK_SIZE]; +StaticTask_t hid_taskdef; +#endif + +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + + while (1) { + tud_task();// tinyusb device task } - start_ms += blink_interval_ms; +} - board_led_write(led_state); - led_state = 1 - led_state; // toggle +static void freertos_init(void) { +#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(hid_task, "hid", HID_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, hid_stack, &hid_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(hid_task, "hid", HID_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); +#endif + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif } + +#endif diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 895745ed28..3e11e846bd 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt deleted file mode 100644 index 2081a77829..0000000000 --- a/examples/device/hid_composite_freertos/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -# Need to set Espressif defaults before project() is called -if(FAMILY STREQUAL "espressif") - list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") -endif() - -project(hid_composite_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} 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_NAME} freertos) diff --git a/examples/device/hid_composite_freertos/CMakePresets.json b/examples/device/hid_composite_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/device/hid_composite_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile deleted file mode 100644 index 3c421af747..0000000000 --- a/examples/device/hid_composite_freertos/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE = \ - src/main.c \ - src/usb_descriptors.c - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt deleted file mode 100644 index 97d8e168b2..0000000000 --- a/examples/device/hid_composite_freertos/skip.txt +++ /dev/null @@ -1,18 +0,0 @@ -mcu:CH32F20X -mcu:CH32V103 -mcu:CH32V20X -mcu:CH32V307 -mcu:CH583 -mcu:CXD56 -mcu:F1C100S -mcu:GD32VF103 -mcu:MCXA15 -mcu:MKL25ZXX -mcu:MSP430x5xx -mcu:FT90X -mcu:SAMD11 -mcu:VALENTYUSB_EPTRI -mcu:RAXXX -family:broadcom_32bit -family:broadcom_64bit -family:hpmicro diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c deleted file mode 100644 index 391e3c42ad..0000000000 --- a/examples/device/hid_composite_freertos/src/main.c +++ /dev/null @@ -1,387 +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 -#include - -#include "bsp/board_api.h" -#include "tusb.h" -#include "usb_descriptors.h" - -#ifdef ESP_PLATFORM - // 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 - -#define HID_STACK_SZIE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -/* Blink pattern - * - 250 ms : device not mounted - * - 1000 ms : device mounted - * - 2500 ms : device is suspended - */ -enum { - BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, -}; - -// static timer & task -#if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; - -StackType_t usb_device_stack[USBD_STACK_SIZE]; -StaticTask_t usb_device_taskdef; - -StackType_t hid_stack[HID_STACK_SZIE]; -StaticTask_t hid_taskdef; -#endif - -TimerHandle_t blinky_tm; - -void led_blinky_cb(TimerHandle_t xTimer); -void usb_device_task(void* param); -void hid_task(void* params); - -//--------------------------------------------------------------------+ -// Main -//--------------------------------------------------------------------+ - -int main(void) -{ - board_init(); - -#if configSUPPORT_STATIC_ALLOCATION - // soft timer for blinky - blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); - - // 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 HID task - xTaskCreateStatic(hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, hid_stack, &hid_taskdef); -#else - blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); - xTaskCreate(hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); -#endif - - xTimerStart(blinky_tm, 0); - - // only start scheduler for non-espressif mcu -#ifndef ESP_PLATFORM - vTaskStartScheduler(); -#endif - - return 0; -} - -#ifdef ESP_PLATFORM -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); - - board_init_after_tusb(); - - // RTOS forever loop - while (1) - { - // put this thread to waiting state until there is new events - tud_task(); - - // following code only run if tud_task() process at least 1 event - } -} - -//--------------------------------------------------------------------+ -// Device callbacks -//--------------------------------------------------------------------+ - -// Invoked when device is mounted -void tud_mount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); -} - -// Invoked when device is unmounted -void tud_umount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); -} - -// Invoked when usb bus is suspended -// remote_wakeup_en : if host allow us to perform remote wakeup -// Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); -} - -// Invoked when usb bus is resumed -void tud_resume_cb(void) -{ - if (tud_mounted()) - { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); - } - else - { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); - } -} - -//--------------------------------------------------------------------+ -// USB HID -//--------------------------------------------------------------------+ - -static void send_hid_report(uint8_t report_id, uint32_t btn) -{ - // skip if hid is not ready yet - if ( !tud_hid_ready() ) return; - - switch(report_id) - { - case REPORT_ID_KEYBOARD: - { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_keyboard_key = false; - - if ( btn ) - { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_A; - - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); - has_keyboard_key = true; - }else - { - // send empty key report if previously has key pressed - if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); - has_keyboard_key = false; - } - } - break; - - case REPORT_ID_MOUSE: - { - int8_t const delta = 5; - - // no button, right + down, no scroll, no pan - tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); - } - break; - - case REPORT_ID_CONSUMER_CONTROL: - { - // use to avoid send multiple consecutive zero report - static bool has_consumer_key = false; - - if ( btn ) - { - // volume down - uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; - tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); - has_consumer_key = true; - }else - { - // send empty key report (release key) if previously has key pressed - uint16_t empty_key = 0; - if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); - has_consumer_key = false; - } - } - break; - - case REPORT_ID_GAMEPAD: - { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_gamepad_key = false; - - hid_gamepad_report_t report = - { - .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, - .hat = 0, .buttons = 0 - }; - - if ( btn ) - { - report.hat = GAMEPAD_HAT_UP; - report.buttons = GAMEPAD_BUTTON_A; - tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); - - has_gamepad_key = true; - }else - { - report.hat = GAMEPAD_HAT_CENTERED; - report.buttons = 0; - if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); - has_gamepad_key = false; - } - } - break; - - default: break; - } -} - -void hid_task(void* param) -{ - (void) param; - - while(1) - { - // Poll every 10ms - vTaskDelay(pdMS_TO_TICKS(10)); - - uint32_t const btn = board_button_read(); - - // Remote wakeup - if ( tud_suspended() && btn ) - { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - tud_remote_wakeup(); - } - else - { - // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() - send_hid_report(REPORT_ID_KEYBOARD, btn); - } - } -} - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) instance; - (void) len; - - uint8_t next_report_id = report[0] + 1; - - if (next_report_id < REPORT_ID_COUNT) - { - send_hid_report(next_report_id, board_button_read()); - } -} - - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ - // TODO not Implemented - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; - - return 0; -} - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ - (void) instance; - - if (report_type == HID_REPORT_TYPE_OUTPUT) - { - // Set keyboard LED e.g Capslock, Numlock etc... - if (report_id == REPORT_ID_KEYBOARD) - { - // bufsize should be (at least) 1 - if ( bufsize < 1 ) return; - - uint8_t const kbd_leds = buffer[0]; - - if (kbd_leds & KEYBOARD_LED_CAPSLOCK) - { - // Capslock On: disable blink, turn led on - xTimerStop(blinky_tm, portMAX_DELAY); - board_led_write(true); - }else - { - // Caplocks Off: back to normal blink - board_led_write(false); - xTimerStart(blinky_tm, portMAX_DELAY); - } - } - } -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinky_cb(TimerHandle_t xTimer) -{ - (void) xTimer; - static bool led_state = false; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle -} diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h deleted file mode 100644 index ad067ac828..0000000000 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ /dev/null @@ -1,114 +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. - * - */ - -#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 board.mk -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -// This examples use FreeRTOS -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH freertos/ -#endif - -// can be defined by compiler in DEBUG build -#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_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c deleted file mode 100644 index a745c17b52..0000000000 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ /dev/null @@ -1,238 +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 "bsp/board_api.h" -#include "tusb.h" -#include "usb_descriptors.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) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ - PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) - -#define USB_VID 0xCafe -#define USB_BCD 0x0200 - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -static tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = USB_BCD, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = USB_VID, - .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; -} - -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ - -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD )), - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE )), - TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), - TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) -}; - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) -{ - (void) instance; - return desc_hid_report; -} - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ - -enum -{ - ITF_NUM_HID, - ITF_NUM_TOTAL -}; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN) - -#define EPNUM_HID 0x81 - -uint8_t const desc_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) -}; - -#if TUD_OPT_HIGH_SPEED -// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration - -// other speed configuration -static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; - -// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -static tusb_desc_device_qualifier_t const desc_device_qualifier = -{ - .bLength = sizeof(tusb_desc_device_qualifier_t), - .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, - .bcdUSB = USB_BCD, - - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .bNumConfigurations = 0x01, - .bReserved = 0x00 -}; - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. -// device_qualifier descriptor describes information about a high-speed capable device that would -// change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) -{ - return (uint8_t const*) &desc_device_qualifier; -} - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations - - // other speed config is basically configuration with type = OTHER_SPEED_CONFIG - memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN); - desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; - - // this example use the same configuration for both high and full speed mode - return desc_other_speed_config; -} - -#endif // highspeed - -// 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 - return desc_configuration; -} - -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - -// String Descriptor Index -enum { - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, -}; - -// array of pointer to string descriptors -static 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); - 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; - - // 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/device/hid_composite_freertos/src/usb_descriptors.h b/examples/device/hid_composite_freertos/src/usb_descriptors.h deleted file mode 100644 index e733d31dde..0000000000 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.h +++ /dev/null @@ -1,37 +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. - */ - -#ifndef USB_DESCRIPTORS_H_ -#define USB_DESCRIPTORS_H_ - -enum -{ - REPORT_ID_KEYBOARD = 1, - REPORT_ID_MOUSE, - REPORT_ID_CONSUMER_CONTROL, - REPORT_ID_GAMEPAD, - REPORT_ID_COUNT -}; - -#endif /* USB_DESCRIPTORS_H_ */ diff --git a/examples/device/midi_test/CMakeLists.txt b/examples/device/midi_test/CMakeLists.txt index 09fbf20f04..496fc122b5 100644 --- a/examples/device/midi_test/CMakeLists.txt +++ b/examples/device/midi_test/CMakeLists.txt @@ -25,6 +25,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT_NAME} noos) +family_configure_device_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/device/midi_test/skip.txt b/examples/device/midi_test/skip.txt index 2c6c2a64c6..e93f35f24b 100644 --- a/examples/device/midi_test/skip.txt +++ b/examples/device/midi_test/skip.txt @@ -1 +1,20 @@ -family:espressif +rtos:noos family:espressif + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V103 +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:CH32V307 +rtos:freertos mcu:CH583 +rtos:freertos mcu:CXD56 +rtos:freertos mcu:F1C100S +rtos:freertos mcu:GD32VF103 +rtos:freertos mcu:MCXA15 +rtos:freertos mcu:MKL25ZXX +rtos:freertos mcu:MSP430x5xx +rtos:freertos mcu:FT90X +rtos:freertos mcu:SAMD11 +rtos:freertos mcu:VALENTYUSB_EPTRI +rtos:freertos mcu:RAXXX +rtos:freertos family:broadcom_32bit +rtos:freertos family:broadcom_64bit +rtos:freertos family:hpmicro diff --git a/examples/device/midi_test_freertos/src/CMakeLists.txt b/examples/device/midi_test/src/CMakeLists.txt similarity index 100% rename from examples/device/midi_test_freertos/src/CMakeLists.txt rename to examples/device/midi_test/src/CMakeLists.txt diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 1154c1d607..3e86d2dd6a 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -54,13 +54,21 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinking_task(void); -void midi_task(void); +void led_blinking_task(void *param); +void midi_task(void *param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif /*------------- MAIN -------------*/ int main(void) { board_init(); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, @@ -72,9 +80,12 @@ int main(void) { while (1) { tud_task(); // tinyusb device task - led_blinking_task(); - midi_task(); + led_blinking_task(NULL); + midi_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -118,65 +129,157 @@ const uint8_t note_sequence[] = { 56,61,64,68,74,78,81,86,90,93,98,102 }; -void midi_task(void) -{ - static uint32_t start_ms = 0; - +void midi_task(void *param) { + (void) param; uint8_t const cable_num = 0; // MIDI jack associated with USB endpoint uint8_t const channel = 0; // 0 for channel 1 - // 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); + while (1) { + // 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); + } + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(286 / portTICK_PERIOD_MS); +#else + static uint32_t start_ms = 0; + // send note periodically + if (tusb_time_millis_api() - start_ms < 286) { + return; // not enough time + } + start_ms += 286; +#endif + + // 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; + } + +#if CFG_TUSB_OS != OPT_OS_FREERTOS + break; +#endif } +} - // send note periodically - if (tusb_time_millis_api() - start_ms < 286) { - return; // not enough time +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void *param) { + (void) param; + static bool led_state = false; +#if CFG_TUSB_OS != OPT_OS_FREERTOS + static uint32_t start_ms = 0; +#endif + + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; +#endif + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + +#if CFG_TUSB_OS != OPT_OS_FREERTOS + break; +#endif } - start_ms += 286; +} - // Previous positions in the note sequence. - int previous = (int) (note_pos - 1); +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS - // 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; - } +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 - // 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); +void app_main(void) { + main(); +} +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE ((3 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1)) +#endif - // 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); +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define MIDI_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) - // Increment position - note_pos++; +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; - // If we are at the end of the sequence, start over. - if (note_pos >= sizeof(note_sequence)) { - note_pos = 0; - } -} +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +StackType_t midi_stack[MIDI_STACK_SIZE]; +StaticTask_t midi_taskdef; +#endif - // Blink every interval ms - if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static void usb_device_task(void *param) { + (void) param; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + // 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + + while (1) { + tud_task();// tinyusb device task + } +} + +static void freertos_init(void) { +#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 + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif } + +#endif diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index f4282b2d79..3e47af7bb1 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/device/midi_test_freertos/CMakeLists.txt b/examples/device/midi_test_freertos/CMakeLists.txt deleted file mode 100644 index 7e5d3e89ed..0000000000 --- a/examples/device/midi_test_freertos/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -project(midi_test_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} 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_NAME} freertos) diff --git a/examples/device/midi_test_freertos/CMakePresets.json b/examples/device/midi_test_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/device/midi_test_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/midi_test_freertos/Makefile b/examples/device/midi_test_freertos/Makefile deleted file mode 100644 index ebacfecdf5..0000000000 --- a/examples/device/midi_test_freertos/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE += \ - src/main.c \ - src/usb_descriptors.c \ - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt deleted file mode 100644 index 97d8e168b2..0000000000 --- a/examples/device/midi_test_freertos/skip.txt +++ /dev/null @@ -1,18 +0,0 @@ -mcu:CH32F20X -mcu:CH32V103 -mcu:CH32V20X -mcu:CH32V307 -mcu:CH583 -mcu:CXD56 -mcu:F1C100S -mcu:GD32VF103 -mcu:MCXA15 -mcu:MKL25ZXX -mcu:MSP430x5xx -mcu:FT90X -mcu:SAMD11 -mcu:VALENTYUSB_EPTRI -mcu:RAXXX -family:broadcom_32bit -family:broadcom_64bit -family:hpmicro diff --git a/examples/device/midi_test_freertos/src/main.c b/examples/device/midi_test_freertos/src/main.c deleted file mode 100644 index f5267214e8..0000000000 --- a/examples/device/midi_test_freertos/src/main.c +++ /dev/null @@ -1,235 +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 -#include - -#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 -//--------------------------------------------------------------------+ -#ifdef ESP_PLATFORM - #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 * (CFG_TUSB_DEBUG ? 2 : 1)) - -// 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 - -#ifndef ESP_PLATFORM - // only start scheduler for non-espressif mcu - vTaskStartScheduler(); -#endif - - return 0; -} - -#ifdef ESP_PLATFORM -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); - - 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 bool led_state = false; - - while (1) { - // Blink every interval ms - vTaskDelay(blink_interval_ms / portTICK_PERIOD_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 deleted file mode 100644 index c158f51977..0000000000 --- a/examples/device/midi_test_freertos/src/tusb_config.h +++ /dev/null @@ -1,108 +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. - * - */ - -#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 deleted file mode 100644 index 99c798ce1d..0000000000 --- a/examples/device/midi_test_freertos/src/usb_descriptors.c +++ /dev/null @@ -1,199 +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 "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) ? (1 << (n)) : 0) -#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 -//--------------------------------------------------------------------+ -static 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 CFG_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 - -static 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 -static 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 -static 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/device/uac2_speaker_fb/CMakeLists.txt b/examples/device/uac2_speaker_fb/CMakeLists.txt index cddbf6a31d..1965596e1b 100644 --- a/examples/device/uac2_speaker_fb/CMakeLists.txt +++ b/examples/device/uac2_speaker_fb/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) +# Need to set Espressif defaults before project() is called +if(FAMILY STREQUAL "espressif") + list(APPEND SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults") +endif() + project(uac2_speaker_fb C CXX ASM) # Checks this example is valid for the family and initializes the project @@ -25,6 +30,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT_NAME} noos) +family_configure_device_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/device/uac2_speaker_fb/freertos_merge_todo.md b/examples/device/uac2_speaker_fb/freertos_merge_todo.md new file mode 100644 index 0000000000..c1e7450c33 --- /dev/null +++ b/examples/device/uac2_speaker_fb/freertos_merge_todo.md @@ -0,0 +1,11 @@ +# UAC2 Speaker FreeRTOS Merge TODO + +Goal: keep `uac2_speaker_fb` as one example that can build in no-OS mode by default and FreeRTOS mode with the existing `RTOS=freertos` / `-DRTOS=freertos` build switch. + +- [x] Keep the existing no-OS speaker behavior unchanged. +- [x] Fold the FreeRTOS task setup from `uac2_speaker_freertos` into `src/main.c`. +- [x] Add ESP-IDF component metadata and FreeRTOS sdkconfig defaults. +- [x] Let CMake choose the RTOS through `${RTOS}` instead of hardcoding `noos`. +- [x] Keep Make defaulting to no-OS while allowing `RTOS=freertos`. +- [x] Keep Espressif build discovery aware of the merged example. +- [x] Verify at least CMake configure/build targets for no-OS and FreeRTOS. diff --git a/examples/device/uac2_speaker_fb/sdkconfig.defaults b/examples/device/uac2_speaker_fb/sdkconfig.defaults new file mode 100644 index 0000000000..eaa9fb9021 --- /dev/null +++ b/examples/device/uac2_speaker_fb/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/uac2_speaker_fb/src/CMakeLists.txt b/examples/device/uac2_speaker_fb/src/CMakeLists.txt new file mode 100644 index 0000000000..cef2b46ee7 --- /dev/null +++ b/examples/device/uac2_speaker_fb/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/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index 7e4d27f1c4..e09015382f 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -74,8 +74,13 @@ uint32_t current_sample_rate = 44100; // Buffer for speaker data uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 2]; -void led_blinking_task(void); -void audio_task(void); +void led_blinking_task(void *param); +void audio_task(void *param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void usb_device_task(void *param); +static void freertos_init(void); +#endif #if CFG_AUDIO_DEBUG void audio_debug_task(void); @@ -88,6 +93,9 @@ volatile uint32_t fifo_count_avg; int main(void) { board_init(); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); +#else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, @@ -100,12 +108,15 @@ int main(void) { while (1) { tud_task();// TinyUSB device task - led_blinking_task(); + led_blinking_task(NULL); #if CFG_AUDIO_DEBUG audio_debug_task(); #endif - audio_task(); + audio_task(NULL); } +#endif + + return 0; } //--------------------------------------------------------------------+ @@ -587,40 +598,58 @@ bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t fu // This task simulates an audio transmit callback, one frame is sent every 1ms. // In a real application, this would be replaced with actual I2S transmit callback. -void audio_task(void) { +void audio_task(void *param) { + (void) param; static uint32_t start_ms = 0; - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms == curr_ms) return;// not enough time - start_ms = curr_ms; - uint16_t length = (uint16_t) (current_sample_rate / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); + while (1) { + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + + uint16_t length = (uint16_t) (current_sample_rate / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); + + if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) { + // Take one more sample every 10 cycles, to have a average reading speed of 44.1 + // This correction is not needed in real world cases + length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; + } else if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) { + // Take one more sample every 5 cycles, to have a average reading speed of 88.2 + // This correction is not needed in real world cases + length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; + } - if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) { - // Take one more sample every 10 cycles, to have a average reading speed of 44.1 - // This correction is not needed in real world cases - length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; - } else if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) { - // Take one more sample every 5 cycles, to have a average reading speed of 88.2 - // This correction is not needed in real world cases - length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; - } + tud_audio_read(i2s_dummy_buffer, length); + } - tud_audio_read(i2s_dummy_buffer, length); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); +#else + return; +#endif + } } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) { - static uint32_t start_ms = 0; +void led_blinking_task(void *param) { + (void) param; static bool led_state = false; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; - start_ms += blink_interval_ms; + while (1) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); +#else + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; + start_ms += blink_interval_ms; +#endif - board_led_write(led_state); - led_state = 1 - led_state; + board_led_write(led_state); + led_state = 1 - led_state; + } } #if CFG_AUDIO_DEBUG @@ -674,3 +703,76 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep } #endif + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 3 : 2)) + +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 + +void app_main(void) { + main(); +} +#else + #define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) +#endif + +#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 audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; +#endif + +// USB Device Driver task +// This top level thread processes all USB events and invokes callbacks. +static 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 uses RTOS queue API. + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + + board_init_after_tusb(); + + TU_LOG1("Speaker running\r\n"); + + while (1) { + tud_task();// TinyUSB device task +#if CFG_AUDIO_DEBUG + audio_debug_task(); +#endif + } +} + +static void freertos_init(void) { +#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(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, audio_stack, &audio_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(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); +#endif + +#ifndef ESP_PLATFORM + vTaskStartScheduler(); +#endif +} + +#endif diff --git a/examples/device/uac2_speaker_fb/src/tusb_config.h b/examples/device/uac2_speaker_fb/src/tusb_config.h index 46f5703c87..0e42bb29ce 100644 --- a/examples/device/uac2_speaker_fb/src/tusb_config.h +++ b/examples/device/uac2_speaker_fb/src/tusb_config.h @@ -60,6 +60,11 @@ extern "C" { #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + // It's recommended to disable debug unless for control requests debugging, // as the extra time needed will impact data stream ! #ifndef CFG_TUSB_DEBUG From 2ec4d7a437834fe304b2717eaa1f9baee438793f Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 29 Jun 2026 14:26:12 +0200 Subject: [PATCH 3/4] Consolidate FreeRTOS host examples Merge paired host FreeRTOS/no-OS examples into their base directories. --- examples/host/CMakeLists.txt | 2 - examples/host/cdc_msc_hid/CMakeLists.txt | 4 +- examples/host/cdc_msc_hid/README.md | 2 +- examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid/skip.txt | 12 +- .../src/CMakeLists.txt | 0 examples/host/cdc_msc_hid/src/app.h | 8 + examples/host/cdc_msc_hid/src/cdc_app.c | 79 +- examples/host/cdc_msc_hid/src/hid_app.c | 6 + examples/host/cdc_msc_hid/src/main.c | 110 ++- examples/host/cdc_msc_hid/src/msc_app.c | 14 +- examples/host/cdc_msc_hid/src/tusb_config.h | 5 + .../host/cdc_msc_hid_freertos/CMakeLists.txt | 32 - .../cdc_msc_hid_freertos/CMakePresets.json | 6 - examples/host/cdc_msc_hid_freertos/Makefile | 17 - examples/host/cdc_msc_hid_freertos/only.txt | 28 - examples/host/cdc_msc_hid_freertos/skip.txt | 3 - examples/host/cdc_msc_hid_freertos/src/app.h | 35 - .../host/cdc_msc_hid_freertos/src/cdc_app.c | 134 ---- .../host/cdc_msc_hid_freertos/src/hid_app.c | 269 ------- examples/host/cdc_msc_hid_freertos/src/main.c | 161 ---- .../host/cdc_msc_hid_freertos/src/msc_app.c | 73 -- .../cdc_msc_hid_freertos/src/tusb_config.h | 142 ---- examples/host/freertos_noos_merge_todo.md | 11 + .../host/msc_file_explorer/CMakeLists.txt | 4 +- examples/host/msc_file_explorer/README.md | 2 +- examples/host/msc_file_explorer/only.txt | 1 + examples/host/msc_file_explorer/skip.txt | 12 +- .../src/CMakeLists.txt | 0 examples/host/msc_file_explorer/src/main.c | 107 ++- examples/host/msc_file_explorer/src/msc_app.c | 118 ++- examples/host/msc_file_explorer/src/msc_app.h | 4 +- .../host/msc_file_explorer/src/tusb_config.h | 5 + .../msc_file_explorer_freertos/CMakeLists.txt | 42 -- .../CMakePresets.json | 6 - .../host/msc_file_explorer_freertos/Makefile | 27 - .../host/msc_file_explorer_freertos/only.txt | 28 - .../host/msc_file_explorer_freertos/skip.txt | 4 - .../msc_file_explorer_freertos/src/ffconf.h | 313 -------- .../msc_file_explorer_freertos/src/main.c | 158 ---- .../msc_file_explorer_freertos/src/msc_app.c | 709 ------------------ .../msc_file_explorer_freertos/src/msc_app.h | 34 - .../src/tusb_config.h | 126 ---- 43 files changed, 486 insertions(+), 2368 deletions(-) rename examples/host/{cdc_msc_hid_freertos => cdc_msc_hid}/src/CMakeLists.txt (100%) delete mode 100644 examples/host/cdc_msc_hid_freertos/CMakeLists.txt delete mode 100644 examples/host/cdc_msc_hid_freertos/CMakePresets.json delete mode 100644 examples/host/cdc_msc_hid_freertos/Makefile delete mode 100644 examples/host/cdc_msc_hid_freertos/only.txt delete mode 100644 examples/host/cdc_msc_hid_freertos/skip.txt delete mode 100644 examples/host/cdc_msc_hid_freertos/src/app.h delete mode 100644 examples/host/cdc_msc_hid_freertos/src/cdc_app.c delete mode 100644 examples/host/cdc_msc_hid_freertos/src/hid_app.c delete mode 100644 examples/host/cdc_msc_hid_freertos/src/main.c delete mode 100644 examples/host/cdc_msc_hid_freertos/src/msc_app.c delete mode 100644 examples/host/cdc_msc_hid_freertos/src/tusb_config.h create mode 100644 examples/host/freertos_noos_merge_todo.md rename examples/host/{msc_file_explorer_freertos => msc_file_explorer}/src/CMakeLists.txt (100%) delete mode 100644 examples/host/msc_file_explorer_freertos/CMakeLists.txt delete mode 100644 examples/host/msc_file_explorer_freertos/CMakePresets.json delete mode 100644 examples/host/msc_file_explorer_freertos/Makefile delete mode 100644 examples/host/msc_file_explorer_freertos/only.txt delete mode 100644 examples/host/msc_file_explorer_freertos/skip.txt delete mode 100644 examples/host/msc_file_explorer_freertos/src/ffconf.h delete mode 100644 examples/host/msc_file_explorer_freertos/src/main.c delete mode 100644 examples/host/msc_file_explorer_freertos/src/msc_app.c delete mode 100644 examples/host/msc_file_explorer_freertos/src/msc_app.h delete mode 100644 examples/host/msc_file_explorer_freertos/src/tusb_config.h diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 7c74e3c73a..b5e41bae07 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -9,13 +9,11 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) set(EXAMPLE_LIST bare_api cdc_msc_hid - cdc_msc_hid_freertos device_info hid_controller midi_rx midi2_host msc_file_explorer - msc_file_explorer_freertos ) foreach (example ${EXAMPLE_LIST}) diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index 3098c37faf..e26614928c 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -27,6 +27,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT_NAME} noos) +family_configure_host_example(${PROJECT_NAME} ${RTOS}) diff --git a/examples/host/cdc_msc_hid/README.md b/examples/host/cdc_msc_hid/README.md index 74b3f53179..c0ff3fcece 100644 --- a/examples/host/cdc_msc_hid/README.md +++ b/examples/host/cdc_msc_hid/README.md @@ -52,7 +52,7 @@ make BOARD=raspberry_pi_pico all ## FreeRTOS variant -A FreeRTOS build is in `examples/host/cdc_msc_hid_freertos` — identical CDC/MSC/HID host behavior, running the host stack in a FreeRTOS task with a software-timer LED. +Build this example with `RTOS=freertos` / `-DRTOS=freertos` for the FreeRTOS variant. It keeps the same CDC/MSC/HID host behavior, running the host stack in a FreeRTOS task with a software-timer LED. ## How to use diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index a2ff93be53..4c2cb0f357 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -1,3 +1,4 @@ +family:espressif family:hpmicro family:samd21 family:samd5x_e5x diff --git a/examples/host/cdc_msc_hid/skip.txt b/examples/host/cdc_msc_hid/skip.txt index 3087968690..cb67253814 100644 --- a/examples/host/cdc_msc_hid/skip.txt +++ b/examples/host/cdc_msc_hid/skip.txt @@ -1 +1,11 @@ -board:lpcxpresso54114 +rtos:noos family:espressif +rtos:noos board:lpcxpresso54114 + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:FT90X +rtos:freertos mcu:KINETIS_KL +rtos:freertos mcu:RAXXX +rtos:freertos mcu:RP2040 +rtos:freertos board:lpcxpresso54114 +rtos:freertos family:hpmicro diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt b/examples/host/cdc_msc_hid/src/CMakeLists.txt similarity index 100% rename from examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt rename to examples/host/cdc_msc_hid/src/CMakeLists.txt diff --git a/examples/host/cdc_msc_hid/src/app.h b/examples/host/cdc_msc_hid/src/app.h index 49783b4ae8..aa89e31eca 100644 --- a/examples/host/cdc_msc_hid/src/app.h +++ b/examples/host/cdc_msc_hid/src/app.h @@ -27,8 +27,16 @@ #define TUSB_TINYUSB_EXAMPLES_APP_H #include +#include "tusb.h" +void msc_app_init(void); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void cdc_app_init(void); +void hid_app_init(void); +#else void cdc_app_task(void); void hid_app_task(void); +#endif #endif diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index e6c190715d..8d44e0d428 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -28,6 +28,82 @@ #include "bsp/board_api.h" #include "app.h" +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#ifdef ESP_PLATFORM + #define CDC_STACK_SIZE 2048 +#else + #define CDC_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) +#endif + +#if configSUPPORT_STATIC_ALLOCATION +StackType_t cdc_stack[CDC_STACK_SIZE]; +StaticTask_t cdc_taskdef; +#endif + +static void cdc_app_task(void* param); + +void cdc_app_init(void) { + #if configSUPPORT_STATIC_ALLOCATION + (void) xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + #else + (void) xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES-2, NULL); + #endif +} + +static size_t console_read(uint8_t *buf, size_t bufsize) { + size_t count = 0; + while (count < bufsize) { + int ch = board_getchar(); + if (ch <= 0) { + break; + } + + buf[count] = (uint8_t) ch; + count++; + } + + return count; +} + +static void cdc_app_task(void* param) { + (void) param; + + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; + + while (1) { + uint32_t count = console_read(buf, bufsize); + buf[count] = 0; + + if (count) { + // loop over all mounted interfaces + for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { + if (tuh_cdc_mounted(idx)) { + // console --> cdc interfaces + tuh_cdc_write(idx, buf, count); + tuh_cdc_write_flush(idx); + } + } + } + + vTaskDelay(1); + } +} + +// Invoked when received new data +void tuh_cdc_rx_cb(uint8_t idx) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; + + // forward cdc interfaces -> console + uint32_t count = tuh_cdc_read(idx, buf, bufsize); + buf[count] = 0; + + printf("%s", (char *) buf); +} + +#else + static size_t console_read(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { @@ -81,6 +157,7 @@ void cdc_app_task(void) { tuh_cdc_write_flush(idx); } +#endif //--------------------------------------------------------------------+ // TinyUSB callbacks @@ -96,7 +173,7 @@ void tuh_cdc_mount_cb(uint8_t idx) { itf_info.desc.bInterfaceNumber); // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack - // while eneumerating new cdc device + // while enumerating new cdc device cdc_line_coding_t line_coding = {0}; if (tuh_cdc_get_line_coding_local(idx, &line_coding)) { printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index eb20356cb5..d95fb2aa44 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -43,9 +43,15 @@ static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const *report); static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void hid_app_init(void) { + // nothing to do +} +#else void hid_app_task(void) { // nothing to do } +#endif //--------------------------------------------------------------------+ // TinyUSB Callbacks diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c27ad93fe6..c2685e8472 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -31,10 +31,39 @@ #include "tusb.h" #include "app.h" +#if CFG_TUSB_OS == OPT_OS_FREERTOS + #ifdef ESP_PLATFORM + #include "freertos/timers.h" + #define USBH_STACK_SIZE 4096 + #else + #include "timers.h" + // Increase stack size when debug log is enabled + #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) + #endif +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +enum { + BLINK_MOUNTED = 1000, +}; + +#if configSUPPORT_STATIC_ALLOCATION +static StaticTimer_t blinky_tmdef; + +static StackType_t usb_host_stack[USBH_STACK_SIZE]; +static StaticTask_t usb_host_taskdef; +#endif + +static TimerHandle_t blinky_tm; + +static void led_blinky_cb(TimerHandle_t xTimer); +static void usb_host_task(void* param); +#else void led_blinking_task(void); +#endif /*------------- MAIN -------------*/ int main(void) { @@ -42,6 +71,23 @@ int main(void) { printf("TinyUSB Host CDC MSC HID Example\r\n"); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // Create soft timer for blinky, task for tinyusb stack + #if configSUPPORT_STATIC_ALLOCATION + blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); + xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); + #else + blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb); + xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); + #endif + + xTimerStart(blinky_tm, 0); + + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM + vTaskStartScheduler(); + #endif +#else // init host stack on configured roothub port tusb_rhport_init_t host_init = { .role = TUSB_ROLE_HOST, @@ -51,11 +97,11 @@ int main(void) { board_init_after_tusb(); -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 - // FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable + #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 + // FeatherWing MAX3421E uses MAX3421E GPIO0 for VBUS enable. enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ }; tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false); -#endif + #endif while (1) { // tinyusb host task @@ -65,8 +111,54 @@ int main(void) { cdc_app_task(); hid_app_task(); } +#endif + + return 0; } +#ifdef ESP_PLATFORM +void app_main(void) { + main(); +} +#endif + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +// USB Host task +// This top level thread processes all USB events and invokes callbacks. +static void usb_host_task(void *param) { + (void) param; + + // init host stack on configured roothub port + tusb_rhport_init_t host_init = { + .role = TUSB_ROLE_HOST, + .speed = TUSB_SPEED_AUTO + }; + + if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) { + printf("Failed to init USB Host Stack\r\n"); + vTaskSuspend(NULL); + } + + board_init_after_tusb(); + + #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 + // FeatherWing MAX3421E uses MAX3421E GPIO0 for VBUS enable. + enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ }; + tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false); + #endif + + cdc_app_init(); + hid_app_init(); + msc_app_init(); + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tuh_task(); + } +} +#endif + //--------------------------------------------------------------------+ // TinyUSB Callbacks //--------------------------------------------------------------------+ @@ -85,6 +177,15 @@ void tuh_umount_cb(uint8_t dev_addr) { //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void led_blinky_cb(TimerHandle_t xTimer) { + (void) xTimer; + static bool led_state = false; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} +#else void led_blinking_task(void) { const uint32_t interval_ms = 1000; static uint32_t start_ms = 0; @@ -93,10 +194,11 @@ void led_blinking_task(void) { // Blink every interval ms if (tusb_time_millis_api() - start_ms < interval_ms) { - return;// not enough time + return; // not enough time } start_ms += interval_ms; board_led_write(led_state); led_state = 1 - led_state; // toggle } +#endif diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 8181bdcb91..5840894e72 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -25,11 +25,19 @@ #include #include "tusb.h" +#include "app.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ -static scsi_inquiry_resp_t inquiry_resp; +// define the buffer to be place in USB/DMA memory with correct alignment/cache line size +CFG_TUH_MEM_SECTION static struct { + TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry); +} scsi_resp; + +void msc_app_init(void) { + // nothing to do +} static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) { msc_cbw_t const* cbw = cb_data->cbw; @@ -41,7 +49,7 @@ static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const } // Print out Vendor ID, Product ID and Rev - printf("%.8s %.16s %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + printf("%.8s %.16s %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.product_rev); // Get capacity of device uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); @@ -58,7 +66,7 @@ void tuh_msc_mount_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); uint8_t const lun = 0; - tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0); + tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0); } void tuh_msc_umount_cb(uint8_t dev_addr) { diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 26fcdd1cb8..978465b81e 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -43,6 +43,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt deleted file mode 100644 index 3ceefb3f43..0000000000 --- a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -project(cdc_msc_hid_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - -# Configure compilation flags and libraries for the example without RTOS. -# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT_NAME} freertos) diff --git a/examples/host/cdc_msc_hid_freertos/CMakePresets.json b/examples/host/cdc_msc_hid_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/host/cdc_msc_hid_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile deleted file mode 100644 index 2e323ed561..0000000000 --- a/examples/host/cdc_msc_hid_freertos/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - - -# Example source -EXAMPLE_SOURCE = \ - src/cdc_app.c \ - src/hid_app.c \ - src/main.c \ - src/msc_app.c \ - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt deleted file mode 100644 index 4ab8a906e6..0000000000 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ /dev/null @@ -1,28 +0,0 @@ -family:espressif -family:samd21 -family:samd5x_e5x -mcu:LPC175X_6X -mcu:LPC177X_8X -mcu:LPC18XX -mcu:LPC40XX -mcu:LPC43XX -mcu:LPC54 -mcu:LPC55 -mcu:MAX3421 -mcu:MIMXRT10XX -mcu:MIMXRT11XX -mcu:MIMXRT1XXX -mcu:MSP432E4 -mcu:RW61X -mcu:RX65X -mcu:STM32C0 -mcu:STM32C5 -mcu:STM32F4 -mcu:STM32F7 -mcu:STM32G0 -mcu:STM32H5 -mcu:STM32H7 -mcu:STM32H7RS -mcu:STM32N6 -mcu:STM32U3 -mcu:STM32U5 diff --git a/examples/host/cdc_msc_hid_freertos/skip.txt b/examples/host/cdc_msc_hid_freertos/skip.txt deleted file mode 100644 index f0be07d251..0000000000 --- a/examples/host/cdc_msc_hid_freertos/skip.txt +++ /dev/null @@ -1,3 +0,0 @@ -mcu:CH32F20X -board:lpcxpresso54114 -mcu:FT90X diff --git a/examples/host/cdc_msc_hid_freertos/src/app.h b/examples/host/cdc_msc_hid_freertos/src/app.h deleted file mode 100644 index 8892a1b6b7..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/app.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2025 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef TUSB_TINYUSB_EXAMPLES_APP_H -#define TUSB_TINYUSB_EXAMPLES_APP_H - -#include - -void cdc_app_init(void); -void hid_app_init(void); -void msc_app_init(void); - -#endif diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c deleted file mode 100644 index 9fad775e99..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2022, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb.h" -#include "bsp/board_api.h" -#include "app.h" - -#ifdef ESP_PLATFORM - #define CDC_STACK_SIZE 2048 -#else - #define CDC_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ -#if configSUPPORT_STATIC_ALLOCATION -StackType_t cdc_stack[CDC_STACK_SIZE]; -StaticTask_t cdc_taskdef; -#endif - -static void cdc_app_task(void* param); - -void cdc_app_init(void) { - #if configSUPPORT_STATIC_ALLOCATION - (void) xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); - #else - (void) xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES-2, NULL); - #endif -} - -// helper -static size_t console_read(uint8_t *buf, size_t bufsize) { - size_t count = 0; - while (count < bufsize) { - int ch = board_getchar(); - if (ch <= 0) { - break; - } - - buf[count] = (uint8_t) ch; - count++; - } - - return count; -} - -static void cdc_app_task(void* param) { - (void) param; - - uint8_t buf[64 + 1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf) - 1; - - while (1) { - uint32_t count = console_read(buf, bufsize); - buf[count] = 0; - - if (count) { - // loop over all mounted interfaces - for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { - if (tuh_cdc_mounted(idx)) { - // console --> cdc interfaces - tuh_cdc_write(idx, buf, count); - tuh_cdc_write_flush(idx); - } - } - } - - vTaskDelay(1); - } -} - -//--------------------------------------------------------------------+ -// TinyUSB Callbacks -//--------------------------------------------------------------------+ - -// Invoked when received new data -void tuh_cdc_rx_cb(uint8_t idx) { - uint8_t buf[64 + 1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf) - 1; - - // forward cdc interfaces -> console - uint32_t count = tuh_cdc_read(idx, buf, bufsize); - buf[count] = 0; - - printf("%s", (char *) buf); -} - -void tuh_cdc_mount_cb(uint8_t idx) { - tuh_itf_info_t itf_info = { 0 }; - tuh_cdc_itf_get_info(idx, &itf_info); - - printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); - -#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration - // otherwise you need to call tuh_cdc_set_line_coding() first - cdc_line_coding_t line_coding = { 0 }; - if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { - printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); - printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); - } -#endif -} - -void tuh_cdc_umount_cb(uint8_t idx) { - tuh_itf_info_t itf_info = { 0 }; - tuh_cdc_itf_get_info(idx, &itf_info); - - printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); -} diff --git a/examples/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c deleted file mode 100644 index 79e0b5a280..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/hid_app.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "bsp/board_api.h" -#include "tusb.h" -#include "app.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -// If your host terminal support ansi escape code such as TeraTerm -// it can be use to simulate mouse cursor movement within terminal -#define USE_ANSI_ESCAPE 0 - -#define MAX_REPORT 4 - -static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; - -// Each HID instance can has multiple reports -static struct { - uint8_t report_count; - tuh_hid_report_info_t report_info[MAX_REPORT]; -} hid_info[CFG_TUH_HID]; - -static void process_kbd_report(hid_keyboard_report_t const *report); -static void process_mouse_report(hid_mouse_report_t const *report); -static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); - -void hid_app_init(void) { - // nothing to do -} - -//--------------------------------------------------------------------+ -// TinyUSB Callbacks -//--------------------------------------------------------------------+ - -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { - printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); - - // Interface protocol (hid_interface_protocol_enum_t) - const char *protocol_str[] = { "None", "Keyboard", "Mouse" }; - uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - - printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); - - // By default host stack will use activate boot protocol on supported interface. - // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) - if (itf_protocol == HID_ITF_PROTOCOL_NONE) { - hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, - desc_report, desc_len); - printf("HID has %u reports \r\n", hid_info[instance].report_count); - } - - // request to receive report - // tuh_hid_report_received_cb() will be invoked when report is available - if (!tuh_hid_receive_report(dev_addr, instance)) { - printf("Error: cannot request to receive report\r\n"); - } -} - -// Invoked when device with hid interface is un-mounted -void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { - printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); -} - -// Invoked when received report from device via interrupt endpoint -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { - uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - - switch (itf_protocol) { - case HID_ITF_PROTOCOL_KEYBOARD: - TU_LOG2("HID receive boot keyboard report\r\n"); - process_kbd_report((hid_keyboard_report_t const *) report); - break; - - case HID_ITF_PROTOCOL_MOUSE: - TU_LOG2("HID receive boot mouse report\r\n"); - process_mouse_report((hid_mouse_report_t const *) report); - break; - - default: - // Generic report requires matching ReportID and contents with previous parsed report info - process_generic_report(dev_addr, instance, report, len); - break; - } - - // continue to request to receive report - if (!tuh_hid_receive_report(dev_addr, instance)) { - printf("Error: cannot request to receive report\r\n"); - } -} - -//--------------------------------------------------------------------+ -// Keyboard -//--------------------------------------------------------------------+ - -// look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) { - for (uint8_t i = 0; i < 6; i++) { - if (report->keycode[i] == keycode) return true; - } - - return false; -} - -static void process_kbd_report(hid_keyboard_report_t const *report) { - static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released - - //------------- example code ignore control (non-printable) key affects -------------// - for (uint8_t i = 0; i < 6; i++) { - if (report->keycode[i]) { - if (find_key_in_report(&prev_report, report->keycode[i])) { - // exist in previous report means the current key is holding - } else { - // not existed in previous report means the current key is pressed - bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); - uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; - putchar(ch); - if (ch == '\r') putchar('\n'); // added new line for enter key - - #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? - fflush(stdout); // flush right away, else nanolib will wait for newline - #endif - } - } - // TODO example skips key released - } - - prev_report = *report; -} - -//--------------------------------------------------------------------+ -// Mouse -//--------------------------------------------------------------------+ - -static void cursor_movement(int8_t x, int8_t y, int8_t wheel) { -#if USE_ANSI_ESCAPE - // Move X using ansi escape - if ( x < 0) { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - } - - // Move Y using ansi escape - if ( y < 0) { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - } - - // Scroll using ansi escape - if (wheel < 0) { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - } - - printf("\r\n"); -#else - printf("(%d %d %d)\r\n", x, y, wheel); -#endif -} - -static void process_mouse_report(hid_mouse_report_t const *report) { - static hid_mouse_report_t prev_report = { 0 }; - - //------------- button state -------------// - uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; - if (button_changed_mask & report->buttons) { - printf(" %c%c%c ", - report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); - } - - //------------- cursor movement -------------// - cursor_movement(report->x, report->y, report->wheel); -} - -//--------------------------------------------------------------------+ -// Generic Report -//--------------------------------------------------------------------+ -static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { - (void) dev_addr; - (void) len; - - uint8_t const rpt_count = hid_info[instance].report_count; - tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info; - tuh_hid_report_info_t *rpt_info = NULL; - - if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) { - // Simple report without report ID as 1st byte - rpt_info = &rpt_info_arr[0]; - } else { - // Composite report, 1st byte is report ID, data starts from 2nd byte - uint8_t const rpt_id = report[0]; - - // Find report id in the array - for (uint8_t i = 0; i < rpt_count; i++) { - if (rpt_id == rpt_info_arr[i].report_id) { - rpt_info = &rpt_info_arr[i]; - break; - } - } - - report++; - len--; - } - - if (!rpt_info) { - printf("Couldn't find report info !\r\n"); - return; - } - - // For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples: - // - Keyboard : Desktop, Keyboard - // - Mouse : Desktop, Mouse - // - Gamepad : Desktop, Gamepad - // - Consumer Control (Media Key) : Consumer, Consumer Control - // - System Control (Power key) : Desktop, System Control - // - Generic (vendor) : 0xFFxx, xx - if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) { - switch (rpt_info->usage) { - case HID_USAGE_DESKTOP_KEYBOARD: - TU_LOG1("HID receive keyboard report\r\n"); - // Assume keyboard follow boot report layout - process_kbd_report((hid_keyboard_report_t const *) report); - break; - - case HID_USAGE_DESKTOP_MOUSE: - TU_LOG1("HID receive mouse report\r\n"); - // Assume mouse follow boot report layout - process_mouse_report((hid_mouse_report_t const *) report); - break; - - default: - break; - } - } -} diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c deleted file mode 100644 index a41de2769b..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ /dev/null @@ -1,161 +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 -#include - -#include "bsp/board_api.h" -#include "tusb.h" -#include "app.h" - -#ifdef ESP_PLATFORM - #define USBH_STACK_SIZE 4096 -#else - // Increase stack size when debug log is enabled - #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) -#endif - - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTOTYPES -//--------------------------------------------------------------------+ -/* Blink pattern - * - 250 ms : device not mounted - * - 1000 ms : device mounted - * - 2500 ms : device is suspended - */ -enum { - BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, -}; - -// static timer & task -#if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; - -StackType_t usb_host_stack[USBH_STACK_SIZE]; -StaticTask_t usb_host_taskdef; -#endif - -TimerHandle_t blinky_tm; - -static void led_blinky_cb(TimerHandle_t xTimer); -static void usb_host_task(void* param); - - -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n"); - - // Create soft timer for blinky, task for tinyusb stack -#if configSUPPORT_STATIC_ALLOCATION - blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); - xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); -#else - blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); -#endif - - xTimerStart(blinky_tm, 0); - - // only start scheduler for non-espressif mcu -#ifndef ESP_PLATFORM - vTaskStartScheduler(); -#endif - - return 0; -} - -#ifdef ESP_PLATFORM -void app_main(void) { - main(); -} -#endif - -// USB Host task -// This top level thread process all usb events and invoke callbacks -static void usb_host_task(void *param) { - (void) param; - - // init host stack on configured roothub port - tusb_rhport_init_t host_init = { - .role = TUSB_ROLE_HOST, - .speed = TUSB_SPEED_AUTO - }; - - if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) { - printf("Failed to init USB Host Stack\r\n"); - vTaskSuspend(NULL); - } - - board_init_after_tusb(); - -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 - // FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable - enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ }; - tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false); -#endif - - cdc_app_init(); - hid_app_init(); - msc_app_init(); - - // RTOS forever loop - while (1) { - // put this thread to waiting state until there is new events - tuh_task(); - - // following code only run if tuh_task() process at least 1 event - } -} - -//--------------------------------------------------------------------+ -// TinyUSB Callbacks -//--------------------------------------------------------------------+ - -void tuh_mount_cb(uint8_t dev_addr) { - // application set-up - printf("A device with address %d is mounted\r\n", dev_addr); -} - -void tuh_umount_cb(uint8_t dev_addr) { - // application tear-down - printf("A device with address %d is unmounted \r\n", dev_addr); -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -static void led_blinky_cb(TimerHandle_t xTimer) { - (void) xTimer; - static bool led_state = false; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle -} diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c deleted file mode 100644 index 17df11951f..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ /dev/null @@ -1,73 +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 "tusb.h" -#include "app.h" - -// define the buffer to be place in USB/DMA memory with correct alignment/cache line size -CFG_TUH_MEM_SECTION static struct { - TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry); -} scsi_resp; - -void msc_app_init(void) { - // nothing to do -} - -static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { - msc_cbw_t const *cbw = cb_data->cbw; - msc_csw_t const *csw = cb_data->csw; - - if (csw->status != 0) { - printf("Inquiry failed\r\n"); - return false; - } - - // Print out Vendor ID, Product ID and Rev - printf("%.8s %.16s %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.product_rev); - - // Get capacity of device - uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); - uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - - printf("Disk Size: %" PRIu32 " %" PRIu32 "-byte blocks: %" PRIu32 " MB\r\n", - block_count, block_size, block_count / ((1024 * 1024) / block_size)); - - return true; -} - -//------------- IMPLEMENTATION -------------// -void tuh_msc_mount_cb(uint8_t dev_addr) { - printf("A MassStorage device is mounted\r\n"); - - uint8_t const lun = 0; - tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0); -} - -void tuh_msc_umount_cb(uint8_t dev_addr) { - (void) dev_addr; - printf("A MassStorage device is unmounted\r\n"); -} diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h deleted file mode 100644 index 8583e7176c..0000000000 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ /dev/null @@ -1,142 +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. - * - */ - -#ifndef TUSB_CONFIG_H_ -#define TUSB_CONFIG_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//-------------------------------------------------------------------- -// Common Configuration -//-------------------------------------------------------------------- - -// defined by compiler flags for flexibility -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH freertos/ -#endif - -#ifndef CFG_TUSB_DEBUG -#define CFG_TUSB_DEBUG 0 -#endif - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. - * Tinyusb use follows macros to declare transferring memory so that they can be put - * into those specific section. - * e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUH_MEM_SECTION -#define CFG_TUH_MEM_SECTION -#endif - -#ifndef CFG_TUH_MEM_ALIGN -#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// Host Configuration -//-------------------------------------------------------------------- - -// Enable Host stack -#define CFG_TUH_ENABLED 1 - -// #define CFG_TUH_MAX3421 1 // use max3421 as host controller - -#if CFG_TUSB_MCU == OPT_MCU_RP2040 - // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - - // host roothub port is 1 if using either pio-usb or max3421 - #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) - #define BOARD_TUH_RHPORT 1 - #endif -#endif - -// Default is max speed that hardware controller could support with on-chip PHY -#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED - -//------------------------- Board Specific -------------------------- - -// RHPort number used for host can be defined by board.mk, default to port 0 -#ifndef BOARD_TUH_RHPORT -#define BOARD_TUH_RHPORT 0 -#endif - -// RHPort max operational speed can defined by board.mk -#ifndef BOARD_TUH_MAX_SPEED -#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED -#endif - -//-------------------------------------------------------------------- -// Driver Configuration -//-------------------------------------------------------------------- - -// Size of buffer to hold descriptors and other data used for enumeration -#define CFG_TUH_ENUMERATION_BUFSIZE 256 - -#define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM -#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API -#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API -#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API -#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API -#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces -#define CFG_TUH_MSC 1 -#define CFG_TUH_VENDOR 0 - -// max device support (excluding hub device): 1 hub typically has 4 ports -#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) - -//------------- HID -------------// -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 - -//------------- CDC -------------// - -// Set Line Control state on enumeration/mounted: -// DTR ( bit 0), RTS (bit 1) -#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS) - -// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t -// bit rate = 115200, 1 stop bit, no parity, 8 bit data width -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } - - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/freertos_noos_merge_todo.md b/examples/host/freertos_noos_merge_todo.md new file mode 100644 index 0000000000..97f8229e12 --- /dev/null +++ b/examples/host/freertos_noos_merge_todo.md @@ -0,0 +1,11 @@ +# Host FreeRTOS/No-OS Example Merge TODO + +Goal: shrink paired host no-OS and FreeRTOS examples into one directory where the build selects the RTOS with `RTOS=freertos` / `-DRTOS=freertos`. + +- [x] Merge `cdc_msc_hid_freertos` into `cdc_msc_hid`. +- [x] Merge `msc_file_explorer_freertos` into `msc_file_explorer`. +- [x] Add RTOS-aware `skip.txt` entries for host FreeRTOS-only exclusions. +- [x] Add ESP-IDF component metadata to the merged host examples. +- [x] Remove merged `_freertos` entries from the host CMake example list. +- [x] Keep Make defaulting to no-OS while allowing `RTOS=freertos`. +- [x] Verify CMake builds for no-OS and FreeRTOS host examples. diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index c8d1964479..9ff8d28d63 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -30,9 +30,9 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${TOP}/lib/embedded-cli ) -# Configure compilation flags and libraries for the example without RTOS. +# Configure compilation flags and libraries for the selected RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT_NAME} noos) +family_configure_host_example(${PROJECT_NAME} ${RTOS}) # Suppress warnings on fatfs if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/examples/host/msc_file_explorer/README.md b/examples/host/msc_file_explorer/README.md index b80ca8f6cc..0fadd1919e 100644 --- a/examples/host/msc_file_explorer/README.md +++ b/examples/host/msc_file_explorer/README.md @@ -57,7 +57,7 @@ make BOARD=raspberry_pi_pico all ## FreeRTOS variant -A FreeRTOS build is in `examples/host/msc_file_explorer_freertos` — identical MSC FatFS file-explorer CLI, running the host stack and CLI as FreeRTOS tasks. +Build this example with `RTOS=freertos` / `-DRTOS=freertos` for the FreeRTOS variant. It keeps the same MSC FatFS file-explorer CLI, running the host stack and CLI as FreeRTOS tasks. ## Usage diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index a2ff93be53..4c2cb0f357 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -1,3 +1,4 @@ +family:espressif family:hpmicro family:samd21 family:samd5x_e5x diff --git a/examples/host/msc_file_explorer/skip.txt b/examples/host/msc_file_explorer/skip.txt index 3087968690..4cc7e4ad6c 100644 --- a/examples/host/msc_file_explorer/skip.txt +++ b/examples/host/msc_file_explorer/skip.txt @@ -1 +1,11 @@ -board:lpcxpresso54114 +rtos:noos family:espressif +rtos:noos board:lpcxpresso54114 + +rtos:freertos mcu:CH32F20X +rtos:freertos mcu:CH32V20X +rtos:freertos mcu:FT90X +rtos:freertos mcu:KINETIS_KL +rtos:freertos mcu:RAXXX +rtos:freertos board:lpcxpresso54114 +rtos:freertos board:stm32h7s3nucleo +rtos:freertos family:hpmicro diff --git a/examples/host/msc_file_explorer_freertos/src/CMakeLists.txt b/examples/host/msc_file_explorer/src/CMakeLists.txt similarity index 100% rename from examples/host/msc_file_explorer_freertos/src/CMakeLists.txt rename to examples/host/msc_file_explorer/src/CMakeLists.txt diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index 07515e6263..58b51761b0 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -28,12 +28,41 @@ #include "bsp/board_api.h" #include "tusb.h" +#if CFG_TUSB_OS == OPT_OS_FREERTOS + #ifdef ESP_PLATFORM + #include "freertos/timers.h" + #define USBH_STACK_SIZE 4096 + #else + #include "timers.h" + // Increase stack size when debug log is enabled. + #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 3)) + #endif +#endif + #include "msc_app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +enum { + BLINK_MOUNTED = 1000, +}; + +#if configSUPPORT_STATIC_ALLOCATION +static StaticTimer_t blinky_tmdef; + +static StackType_t usb_host_stack[USBH_STACK_SIZE]; +static StaticTask_t usb_host_taskdef; +#endif + +static TimerHandle_t blinky_tm; + +static void led_blinky_cb(TimerHandle_t xTimer); +static void usb_host_task(void* param); +#else void led_blinking_task(void); +#endif /*------------- MAIN -------------*/ int main(void) { @@ -41,6 +70,24 @@ int main(void) { printf("TinyUSB Host MassStorage Explorer Example\r\n"); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // Create soft timer for blinky and task for TinyUSB host stack. + #if configSUPPORT_STATIC_ALLOCATION + blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); + xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, usb_host_stack, + &usb_host_taskdef); + #else + blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb); + xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + #endif + + xTimerStart(blinky_tm, 0); + + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM + vTaskStartScheduler(); + #endif +#else // init host stack on configured roothub port tusb_rhport_init_t host_init = { .role = TUSB_ROLE_HOST, @@ -59,7 +106,53 @@ int main(void) { msc_app_task(); led_blinking_task(); } +#endif + + return 0; +} + +#ifdef ESP_PLATFORM +void app_main(void) { + main(); } +#endif + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +// USB Host task +// This top-level thread processes all USB events and invokes callbacks. +static void usb_host_task(void* param) { + (void) param; + + // init host stack on configured roothub port + tusb_rhport_init_t host_init = { + .role = TUSB_ROLE_HOST, + .speed = TUSB_SPEED_AUTO + }; + + if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) { + printf("Failed to init USB Host Stack\r\n"); + vTaskSuspend(NULL); + } + + board_init_after_tusb(); + + #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 + // FeatherWing MAX3421E uses MAX3421E GPIO0 for VBUS enable. + enum { IOPINS1_ADDR = 20u << 3 }; + tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false); + #endif + + if (!msc_app_init()) { + printf("Failed to init MSC app\r\n"); + vTaskSuspend(NULL); + } + + while (1) { + // TinyUSB host task. + tuh_task(); + } +} +#endif //--------------------------------------------------------------------+ // TinyUSB Callbacks @@ -76,6 +169,15 @@ void tuh_umount_cb(uint8_t dev_addr) { //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void led_blinky_cb(TimerHandle_t xTimer) { + (void) xTimer; + static bool led_state = false; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} +#else void led_blinking_task(void) { const uint32_t interval_ms = 1000; static uint32_t start_ms = 0; @@ -83,9 +185,12 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < interval_ms) { + return; // not enough time + } start_ms += interval_ms; board_led_write(led_state); led_state = 1 - led_state; // toggle } +#endif diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c index 3f15bb84fc..8fcd708e9c 100644 --- a/examples/host/msc_file_explorer/src/msc_app.c +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -48,12 +48,30 @@ #define CLI_HISTORY_SIZE 32 #define CLI_BINDING_COUNT 9 +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#ifdef ESP_PLATFORM + #define MSC_APP_STACK_SIZE 4096 +#else + #define MSC_APP_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 3 : 2)) +#endif +#endif + static EmbeddedCli *_cli; static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)]; +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if configSUPPORT_STATIC_ALLOCATION +static StackType_t msc_app_stack[MSC_APP_STACK_SIZE]; +static StaticTask_t msc_app_taskdef; +#endif +#endif + //------------- Elm Chan FatFS -------------// static CFG_TUH_MEM_SECTION FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity only support 1 LUN per device static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX]; +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static volatile bool _mount_pending[CFG_TUH_DEVICE_MAX]; +#endif static CFG_TUH_MEM_SECTION FIL file1, file2; @@ -73,10 +91,17 @@ CFG_TUH_MEM_SECTION static struct { //--------------------------------------------------------------------+ bool cli_init(void); +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void msc_app_task(void* param); +static void process_pending_mount(void); +#endif bool msc_app_init(void) { for (size_t i = 0; i < CFG_TUH_DEVICE_MAX; i++) { _disk_busy[i] = false; + #if CFG_TUSB_OS == OPT_OS_FREERTOS + _mount_pending[i] = false; + #endif } // disable stdout buffered for echoing typing command @@ -86,9 +111,73 @@ bool msc_app_init(void) { cli_init(); +#if CFG_TUSB_OS == OPT_OS_FREERTOS + #if configSUPPORT_STATIC_ALLOCATION + TaskHandle_t task_hdl = xTaskCreateStatic(msc_app_task, "msc", MSC_APP_STACK_SIZE, NULL, + configMAX_PRIORITIES - 2, msc_app_stack, &msc_app_taskdef); + TU_ASSERT(task_hdl != NULL); + #else + TU_ASSERT(xTaskCreate(msc_app_task, "msc", MSC_APP_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL) == pdPASS); + #endif +#endif + return true; } +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void msc_app_task(void* param) { + (void) param; + + while (1) { + process_pending_mount(); + + if (!_cli) { + vTaskDelay(1); + continue; + } + + int ch = board_getchar(); + if (ch > 0) { + while (ch > 0) { + embeddedCliReceiveChar(_cli, (char) ch); + ch = board_getchar(); + } + embeddedCliProcess(_cli); + } + + vTaskDelay(1); + } +} + +static void process_pending_mount(void) { + for (uint8_t drive_num = 0; drive_num < CFG_TUH_DEVICE_MAX; drive_num++) { + if (!_mount_pending[drive_num]) { + continue; + } + + _mount_pending[drive_num] = false; + + const uint8_t dev_addr = drive_num + 1; + if (!tuh_msc_mounted(dev_addr)) { + continue; + } + + char drive_path[3] = "0:"; + drive_path[0] += drive_num; + + if (f_mount(&fatfs[drive_num], drive_path, 1) != FR_OK) { + printf("mount failed\r\n"); + continue; + } + + f_chdrive(drive_path); + FRESULT rc = f_chdir("/"); + if (rc != FR_OK) { + printf("chdir failed: %d\r\n", rc); + } + } +} +#else void msc_app_task(void) { if (!_cli) { return; @@ -103,6 +192,7 @@ void msc_app_task(void) { embeddedCliProcess(_cli); } } +#endif //--------------------------------------------------------------------+ // @@ -130,6 +220,9 @@ static bool inquiry_complete_cb(uint8_t dev_addr, const tuh_msc_complete_data_t // For simplicity: we only mount 1 LUN per device const uint8_t drive_num = dev_addr - 1; +#if CFG_TUSB_OS == OPT_OS_FREERTOS + _mount_pending[drive_num] = true; +#else char drive_path[3] = "0:"; drive_path[0] += drive_num; @@ -144,6 +237,7 @@ static bool inquiry_complete_cb(uint8_t dev_addr, const tuh_msc_complete_data_t if (rc != FR_OK) { printf("chdir failed: %d\r\n", rc); } +#endif // print the drive label // char label[34]; @@ -170,6 +264,10 @@ void tuh_msc_umount_cb(uint8_t dev_addr) { char drive_path[3] = "0:"; drive_path[0] += drive_num; +#if CFG_TUSB_OS == OPT_OS_FREERTOS + _mount_pending[drive_num] = false; +#endif + f_unmount(drive_path); // if ( phy_disk == f_get_current_drive() ) @@ -191,7 +289,11 @@ void tuh_msc_umount_cb(uint8_t dev_addr) { static void wait_for_disk_io(BYTE pdrv) { while (_disk_busy[pdrv]) { +#if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(1); +#else tuh_task(); +#endif } } @@ -387,14 +489,26 @@ void cli_cmd_dd(EmbeddedCli *cli, char *args, void *context) { const uint32_t start_ms = tusb_time_millis_api(); const uint8_t pdrv = dev_addr - 1; + bool submit_failed = false; for (uint32_t i = 0; i < count; i += sectors_per_xfer) { const uint16_t n = (uint16_t)((count - i < sectors_per_xfer) ? (count - i) : sectors_per_xfer); _disk_busy[pdrv] = true; - tuh_msc_read10(dev_addr, lun, rw_buf, i, n, disk_io_complete, 0); + + if (!tuh_msc_read10(dev_addr, lun, rw_buf, i, n, disk_io_complete, 0)) { + _disk_busy[pdrv] = false; + printf("dd: failed to submit read at sector %" PRIu32 " (%u sectors)\r\n", i, n); + submit_failed = true; + break; + } + wait_for_disk_io(pdrv); } + if (submit_failed) { + return; + } + const uint32_t elapsed_ms = tusb_time_millis_api() - start_ms; const uint32_t total_data = count * block_size; // each SCSI transaction has 31-byte CBW + data + 13-byte CSW @@ -491,6 +605,7 @@ void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context) { if (FR_OK != f_open(f_dst, dst, FA_WRITE | FA_CREATE_ALWAYS)) { printf("cannot create '%s'\r\n", dst); + f_close(f_src); return; } else { UINT rd_count = 0; @@ -566,6 +681,7 @@ void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context) { char path[256]; if (FR_OK != f_getcwd(path, sizeof(path))) { printf("cannot get current working directory\r\n"); + return; } puts(path); diff --git a/examples/host/msc_file_explorer/src/msc_app.h b/examples/host/msc_file_explorer/src/msc_app.h index a99da5b5cd..3ede5244d5 100644 --- a/examples/host/msc_file_explorer/src/msc_app.h +++ b/examples/host/msc_file_explorer/src/msc_app.h @@ -28,9 +28,11 @@ #include #include +#include "tusb.h" bool msc_app_init(void); +#if CFG_TUSB_OS != OPT_OS_FREERTOS void msc_app_task(void); - +#endif #endif diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index a9d24c89f7..3056a4abb5 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -43,6 +43,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#ifdef ESP_PLATFORM +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif diff --git a/examples/host/msc_file_explorer_freertos/CMakeLists.txt b/examples/host/msc_file_explorer_freertos/CMakeLists.txt deleted file mode 100644 index 4893dd1fbd..0000000000 --- a/examples/host/msc_file_explorer_freertos/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -project(msc_file_explorer_freertos C CXX ASM) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# Espressif has its own cmake build system -if(FAMILY STREQUAL "espressif") - return() -endif() - -add_executable(${PROJECT_NAME}) - -# Example source -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c - ${TOP}/lib/fatfs/source/ff.c - ${TOP}/lib/fatfs/source/ffsystem.c - ${TOP}/lib/fatfs/source/ffunicode.c - ) - -# Example include -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${TOP}/lib/fatfs/source - ${TOP}/lib/embedded-cli - ) - -# Configure compilation flags and libraries for the example with FreeRTOS. -# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT_NAME} freertos) - -# Suppress warnings on fatfs -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - set_source_files_properties(${TOP}/lib/fatfs/source/ff.c PROPERTIES - COMPILE_OPTIONS "-Wno-conversion;-Wno-cast-qual" - ) -endif () diff --git a/examples/host/msc_file_explorer_freertos/CMakePresets.json b/examples/host/msc_file_explorer_freertos/CMakePresets.json deleted file mode 100644 index 5cd8971e9a..0000000000 --- a/examples/host/msc_file_explorer_freertos/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/host/msc_file_explorer_freertos/Makefile b/examples/host/msc_file_explorer_freertos/Makefile deleted file mode 100644 index 15c7420d47..0000000000 --- a/examples/host/msc_file_explorer_freertos/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -RTOS = freertos -include ../../../hw/bsp/family_support.mk - -FATFS_PATH = lib/fatfs/source - -INC += \ - src \ - $(TOP)/$(FATFS_PATH) \ - $(TOP)/lib/embedded-cli \ - -# Example source -EXAMPLE_SOURCE = \ - src/main.c \ - src/msc_app.c \ - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -# FatFS source -SRC_C += \ - $(FATFS_PATH)/ff.c \ - $(FATFS_PATH)/ffsystem.c \ - $(FATFS_PATH)/ffunicode.c \ - -# suppress warning caused by fatfs -CFLAGS += -Wno-error=cast-qual - -include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/msc_file_explorer_freertos/only.txt b/examples/host/msc_file_explorer_freertos/only.txt deleted file mode 100644 index 519ac2ebde..0000000000 --- a/examples/host/msc_file_explorer_freertos/only.txt +++ /dev/null @@ -1,28 +0,0 @@ -family:espressif -family:samd21 -family:samd5x_e5x -mcu:LPC175X_6X -mcu:LPC177X_8X -mcu:LPC18XX -mcu:LPC40XX -mcu:LPC43XX -mcu:LPC54 -mcu:LPC55 -mcu:MAX3421 -mcu:MIMXRT10XX -mcu:MIMXRT11XX -mcu:MIMXRT1XXX -mcu:MSP432E4 -mcu:RP2040 -mcu:RW61X -mcu:RX65X -mcu:STM32C0 -mcu:STM32F4 -mcu:STM32F7 -mcu:STM32G0 -mcu:STM32H5 -mcu:STM32H7 -mcu:STM32H7RS -mcu:STM32N6 -mcu:STM32U3 -mcu:STM32U5 diff --git a/examples/host/msc_file_explorer_freertos/skip.txt b/examples/host/msc_file_explorer_freertos/skip.txt deleted file mode 100644 index a8c9bea2a8..0000000000 --- a/examples/host/msc_file_explorer_freertos/skip.txt +++ /dev/null @@ -1,4 +0,0 @@ -mcu:CH32F20X -board:lpcxpresso54114 -mcu:FT90X -board:stm32h7s3nucleo diff --git a/examples/host/msc_file_explorer_freertos/src/ffconf.h b/examples/host/msc_file_explorer_freertos/src/ffconf.h deleted file mode 100644 index 5c89136fed..0000000000 --- a/examples/host/msc_file_explorer_freertos/src/ffconf.h +++ /dev/null @@ -1,313 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ Configurations of FatFs Module -/---------------------------------------------------------------------------*/ - -#define FFCONF_DEF 80386 /* Revision ID */ - -/*---------------------------------------------------------------------------/ -/ Function Configurations -/---------------------------------------------------------------------------*/ - -#define FF_FS_READONLY 0 -/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) -/ Read-only configuration removes writing API functions, f_write(), f_sync(), -/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() -/ and optional writing functions as well. */ - - -#define FF_FS_MINIMIZE 0 -/* This option defines minimization level to remove some basic API functions. -/ -/ 0: Basic functions are fully enabled. -/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() -/ are removed. -/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. -/ 3: f_lseek() function is removed in addition to 2. */ - - -#define FF_USE_FIND 0 -/* This option switches filtered directory read functions, f_findfirst() and -/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ - - -#define FF_USE_MKFS 0 -/* This option switches f_mkfs(). (0:Disable or 1:Enable) */ - - -#define FF_USE_FASTSEEK 0 -/* This option switches fast seek feature. (0:Disable or 1:Enable) */ - - -#define FF_USE_EXPAND 0 -/* This option switches f_expand(). (0:Disable or 1:Enable) */ - - -#define FF_USE_CHMOD 0 -/* This option switches attribute control API functions, f_chmod() and f_utime(). -/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ - - -#define FF_USE_LABEL 0 -/* This option switches volume label API functions, f_getlabel() and f_setlabel(). -/ (0:Disable or 1:Enable) */ - - -#define FF_USE_FORWARD 0 -/* This option switches f_forward(). (0:Disable or 1:Enable) */ - - -#define FF_USE_STRFUNC 0 -#define FF_PRINT_LLI 0 -#define FF_PRINT_FLOAT 0 -#define FF_STRF_ENCODE 0 -/* FF_USE_STRFUNC switches string API functions, f_gets(), f_putc(), f_puts() and -/ f_printf(). -/ -/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. -/ 1: Enable without LF-CRLF conversion. -/ 2: Enable with LF-CRLF conversion. -/ -/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 -/ makes f_printf() support floating point argument. These features want C99 or later. -/ When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character -/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE -/ to be read/written via those functions. -/ -/ 0: ANSI/OEM in current CP -/ 1: Unicode in UTF-16LE -/ 2: Unicode in UTF-16BE -/ 3: Unicode in UTF-8 -*/ - - -/*---------------------------------------------------------------------------/ -/ Locale and Namespace Configurations -/---------------------------------------------------------------------------*/ - -#define FF_CODE_PAGE 437 -/* This option specifies the OEM code page to be used on the target system. -/ Incorrect code page setting can cause a file open failure. -/ -/ 437 - U.S. -/ 720 - Arabic -/ 737 - Greek -/ 771 - KBL -/ 775 - Baltic -/ 850 - Latin 1 -/ 852 - Latin 2 -/ 855 - Cyrillic -/ 857 - Turkish -/ 860 - Portuguese -/ 861 - Icelandic -/ 862 - Hebrew -/ 863 - Canadian French -/ 864 - Arabic -/ 865 - Nordic -/ 866 - Russian -/ 869 - Greek 2 -/ 932 - Japanese (DBCS) -/ 936 - Simplified Chinese (DBCS) -/ 949 - Korean (DBCS) -/ 950 - Traditional Chinese (DBCS) -/ 0 - Include all code pages above and configured by f_setcp() -*/ - - -#define FF_USE_LFN 1 -#define FF_MAX_LFN 255 -/* The FF_USE_LFN switches the support for LFN (long file name). -/ -/ 0: Disable LFN. FF_MAX_LFN has no effect. -/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. -/ 2: Enable LFN with dynamic working buffer on the STACK. -/ 3: Enable LFN with dynamic working buffer on the HEAP. -/ -/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN feature -/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and -/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. -/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can -/ be in range of 12 to 255. It is recommended to be set 255 to fully support the LFN -/ specification. -/ When use stack for the working buffer, take care on stack overflow. When use heap -/ memory for the working buffer, memory management functions, ff_memalloc() and -/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ - - -#define FF_LFN_UNICODE 0 -/* This option switches the character encoding on the API when LFN is enabled. -/ -/ 0: ANSI/OEM in current CP (TCHAR = char) -/ 1: Unicode in UTF-16 (TCHAR = WCHAR) -/ 2: Unicode in UTF-8 (TCHAR = char) -/ 3: Unicode in UTF-32 (TCHAR = DWORD) -/ -/ Also behavior of string I/O functions will be affected by this option. -/ When LFN is not enabled, this option has no effect. */ - - -#define FF_LFN_BUF 255 -#define FF_SFN_BUF 12 -/* This set of options defines size of file name members in the FILINFO structure -/ which is used to read out directory items. These values should be sufficient for -/ the file names to read. The maximum possible length of the read file name depends -/ on character encoding. When LFN is not enabled, these options have no effect. */ - - -#define FF_FS_RPATH 2 -/* This option configures support for relative path feature. -/ -/ 0: Disable relative path and remove related API functions. -/ 1: Enable relative path and dot names. f_chdir() and f_chdrive() are available. -/ 2: f_getcwd() is available in addition to 1. -*/ - - -#define FF_PATH_DEPTH 10 -/* This option defines maximum depth of directory in the exFAT volume. It is NOT -/ relevant to FAT/FAT32 volume. -/ For example, FF_PATH_DEPTH = 3 will able to follow a path "/dir1/dir2/dir3/file" -/ but a sub-directory in the dir3 will not able to be followed and set current -/ directory. -/ The size of filesystem object (FATFS) increases FF_PATH_DEPTH * 24 bytes. -/ When FF_FS_EXFAT == 0 or FF_FS_RPATH == 0, this option has no effect. -*/ - - - -/*---------------------------------------------------------------------------/ -/ Drive/Volume Configurations -/---------------------------------------------------------------------------*/ - -#define FF_VOLUMES 4 -/* Number of volumes (logical drives) to be used. (1-10) */ - - -#define FF_STR_VOLUME_ID 0 -#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" -/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. -/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive -/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each -/ logical drive. Number of items must not be less than FF_VOLUMES. Valid -/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are -/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is -/ not defined, a user defined volume string table is needed as: -/ -/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... -*/ - - -#define FF_MULTI_PARTITION 0 -/* This option switches support for multiple volumes on the physical drive. -/ By default (0), each logical drive number is bound to the same physical drive -/ number and only an FAT volume found on the physical drive will be mounted. -/ When this feature is enabled (1), each logical drive number can be bound to -/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() -/ will be available. */ - - -#define FF_MIN_SS 512 -#define FF_MAX_SS 512 -/* This set of options configures the range of sector size to be supported. (512, -/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and -/ harddisk, but a larger value may be required for on-board flash memory and some -/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is -/ configured for variable sector size mode and disk_ioctl() needs to implement -/ GET_SECTOR_SIZE command. */ - - -#define FF_LBA64 0 -/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) -/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ - - -#define FF_MIN_GPT 0x10000000 -/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and -/ f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */ - - -#define FF_USE_TRIM 0 -/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) -/ To enable this feature, also CTRL_TRIM command should be implemented to -/ the disk_ioctl(). */ - - - -/*---------------------------------------------------------------------------/ -/ System Configurations -/---------------------------------------------------------------------------*/ - -#define FF_FS_TINY 0 -/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) -/ At the tiny configuration, size of file object (FIL) is reduced FF_MAX_SS bytes. -/ Instead of private sector buffer eliminated from the file object, common sector -/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ - - -#define FF_FS_EXFAT 0 -/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) -/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) -/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ - - -#define FF_FS_NORTC 1 -#define FF_NORTC_MON 1 -#define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2025 -/* The option FF_FS_NORTC switches timestamp feature. If the system does not have -/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the -/ timestamp feature. Every object modified by FatFs will have a fixed timestamp -/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. -/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added -/ to the project to read current time form real-time clock. FF_NORTC_MON, -/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. -/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ - - -#define FF_FS_CRTIME 0 -/* This option enables(1)/disables(0) the timestamp of the file created. When -/ set 1, the file created time is available in FILINFO structure. */ - - -#define FF_FS_NOFSINFO 0 -/* If you need to know the correct free space on the FAT32 volume, set bit 0 of -/ this option, and f_getfree() on the first time after volume mount will force -/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. -/ -/ bit0=0: Use free cluster count in the FSINFO if available. -/ bit0=1: Do not trust free cluster count in the FSINFO. -/ bit1=0: Use last allocated cluster number in the FSINFO if available. -/ bit1=1: Do not trust last allocated cluster number in the FSINFO. -*/ - - -#define FF_FS_LOCK 0 -/* The option FF_FS_LOCK switches file lock function to control duplicated file open -/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY -/ is 1. -/ -/ 0: Disable file lock function. To avoid volume corruption, application program -/ should avoid illegal open, remove and rename to the open objects. -/ >0: Enable file lock function. The value defines how many files/sub-directories -/ can be opened simultaneously under file lock control. Note that the file -/ lock control is independent of re-entrancy. */ - - -#define FF_FS_REENTRANT 0 -#define FF_FS_TIMEOUT 1000 -/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs -/ module itself. Note that regardless of this option, file access to different -/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() -/ and f_fdisk(), are always not re-entrant. Only file/directory access to -/ the same volume is under control of this featuer. -/ -/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. -/ 1: Enable re-entrancy. Also user provided synchronization handlers, -/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(), -/ must be added to the project. Samples are available in ffsystem.c. -/ -/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. -*/ - - - -/*--- End of configuration options ---*/ diff --git a/examples/host/msc_file_explorer_freertos/src/main.c b/examples/host/msc_file_explorer_freertos/src/main.c deleted file mode 100644 index d1e627f4f5..0000000000 --- a/examples/host/msc_file_explorer_freertos/src/main.c +++ /dev/null @@ -1,158 +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 "bsp/board_api.h" -#include "tusb.h" -#ifdef ESP_PLATFORM - // ESP-IDF need "freertos/" prefix in include path. - // CFG_TUSB_OS_INC_PATH should be defined accordingly. - #include "freertos/FreeRTOS.h" - #include "freertos/task.h" - #include "freertos/timers.h" -#else - #include "FreeRTOS.h" - #include "task.h" - #include "timers.h" -#endif - -#include "msc_app.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ -#ifdef ESP_PLATFORM - #define USBH_STACK_SIZE 4096 -#else - // Increase stack size when debug log is enabled. - #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 3)) -#endif - -enum { - BLINK_MOUNTED = 1000, -}; - -#if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; - -StackType_t usb_host_stack[USBH_STACK_SIZE]; -StaticTask_t usb_host_taskdef; -#endif - -TimerHandle_t blinky_tm; - -static void led_blinky_cb(TimerHandle_t xTimer); -static void usb_host_task(void* param); - -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - printf("TinyUSB Host MassStorage Explorer FreeRTOS Example\r\n"); - - // Create soft timer for blinky and task for TinyUSB host stack. -#if configSUPPORT_STATIC_ALLOCATION - blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); - xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, usb_host_stack, - &usb_host_taskdef); -#else - blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); -#endif - - xTimerStart(blinky_tm, 0); - - // only start scheduler for non-espressif mcu -#ifndef ESP_PLATFORM - vTaskStartScheduler(); -#endif - - return 0; -} - -#ifdef ESP_PLATFORM -void app_main(void) { - main(); -} -#endif - -// USB Host task -// This top-level thread processes all USB events and invokes callbacks. -static void usb_host_task(void* param) { - (void) param; - - // init host stack on configured roothub port - tusb_rhport_init_t host_init = { - .role = TUSB_ROLE_HOST, - .speed = TUSB_SPEED_AUTO - }; - - if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) { - printf("Failed to init USB Host Stack\r\n"); - vTaskSuspend(NULL); - } - - board_init_after_tusb(); - -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 - // FeatherWing MAX3421E uses MAX3421E GPIO0 for VBUS enable. - enum { IOPINS1_ADDR = 20u << 3 }; - tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false); -#endif - - if (!msc_app_init()) { - printf("Failed to init MSC app\r\n"); - vTaskSuspend(NULL); - } - - while (1) { - // TinyUSB host task. - tuh_task(); - } -} - -//--------------------------------------------------------------------+ -// TinyUSB Callbacks -//--------------------------------------------------------------------+ - -void tuh_mount_cb(uint8_t dev_addr) { - (void) dev_addr; -} - -void tuh_umount_cb(uint8_t dev_addr) { - (void) dev_addr; -} - -//--------------------------------------------------------------------+ -// Blinking Task -//--------------------------------------------------------------------+ -static void led_blinky_cb(TimerHandle_t xTimer) { - (void) xTimer; - static bool led_state = false; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle -} diff --git a/examples/host/msc_file_explorer_freertos/src/msc_app.c b/examples/host/msc_file_explorer_freertos/src/msc_app.c deleted file mode 100644 index c7e00e52ab..0000000000 --- a/examples/host/msc_file_explorer_freertos/src/msc_app.c +++ /dev/null @@ -1,709 +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 "tusb.h" -#include "bsp/board_api.h" -#ifdef ESP_PLATFORM - // ESP-IDF need "freertos/" prefix in include path. - // CFG_TUSB_OS_INC_PATH should be defined accordingly. - #include "freertos/FreeRTOS.h" - #include "freertos/task.h" - #include "freertos/timers.h" -#else - #include "FreeRTOS.h" - #include "task.h" - #include "timers.h" -#endif - -#include "ff.h" -#include "diskio.h" - -// lib/embedded-cli -#define EMBEDDED_CLI_IMPL -#include "embedded_cli.h" - -#include "msc_app.h" - - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -//------------- embedded-cli -------------// -#define CLI_BUFFER_SIZE 512 -#define CLI_RX_BUFFER_SIZE 16 -#define CLI_CMD_BUFFER_SIZE 64 -#define CLI_HISTORY_SIZE 32 -#define CLI_BINDING_COUNT 9 - -#ifdef ESP_PLATFORM - #define MSC_APP_STACK_SIZE 4096 -#else - #define MSC_APP_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 3 : 2)) -#endif - -static EmbeddedCli *_cli; -static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)]; - -#if configSUPPORT_STATIC_ALLOCATION -StackType_t msc_app_stack[MSC_APP_STACK_SIZE]; -StaticTask_t msc_app_taskdef; -#endif - -//------------- Elm Chan FatFS -------------// -static CFG_TUH_MEM_SECTION FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity only support 1 LUN per device -static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX]; -static volatile bool _mount_pending[CFG_TUH_DEVICE_MAX]; - -static CFG_TUH_MEM_SECTION FIL file1, file2; - -#ifndef CFG_EXAMPLE_MSC_FILE_EXPLORER_RW_BUFSIZE -#define CFG_EXAMPLE_MSC_FILE_EXPLORER_RW_BUFSIZE 4096 -#endif -static CFG_TUH_MEM_SECTION uint8_t rw_buf[CFG_EXAMPLE_MSC_FILE_EXPLORER_RW_BUFSIZE]; - -// define the buffer to be place in USB/DMA memory with correct alignment/cache line size -CFG_TUH_MEM_SECTION static struct { - TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry); -} scsi_resp; - - -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -static bool cli_init(void); -static void msc_app_task(void* param); -static void process_pending_mount(void); - -bool msc_app_init(void) { - for (size_t i = 0; i < CFG_TUH_DEVICE_MAX; i++) { - _disk_busy[i] = false; - _mount_pending[i] = false; - } - -// disable stdout buffered for echoing typing command -#ifndef __ICCARM__ // TODO IAR doesn't support stream control ? - setbuf(stdout, NULL); -#endif - - cli_init(); - -#if configSUPPORT_STATIC_ALLOCATION - TaskHandle_t task_hdl = xTaskCreateStatic(msc_app_task, "msc", MSC_APP_STACK_SIZE, NULL, - configMAX_PRIORITIES - 2, msc_app_stack, &msc_app_taskdef); - TU_ASSERT(task_hdl != NULL); -#else - TU_ASSERT(xTaskCreate(msc_app_task, "msc", MSC_APP_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL) == pdPASS); -#endif - - return true; -} - -static void msc_app_task(void* param) { - (void) param; - - while (1) { - process_pending_mount(); - - if (!_cli) { - vTaskDelay(1); - continue; - } - - int ch = board_getchar(); - if (ch > 0) { - while (ch > 0) { - embeddedCliReceiveChar(_cli, (char) ch); - ch = board_getchar(); - } - embeddedCliProcess(_cli); - } - - vTaskDelay(1); - } -} - -static void process_pending_mount(void) { - for (uint8_t drive_num = 0; drive_num < CFG_TUH_DEVICE_MAX; drive_num++) { - if (!_mount_pending[drive_num]) { - continue; - } - - _mount_pending[drive_num] = false; - - const uint8_t dev_addr = drive_num + 1; - if (!tuh_msc_mounted(dev_addr)) { - continue; - } - - char drive_path[3] = "0:"; - drive_path[0] += drive_num; - - if (f_mount(&fatfs[drive_num], drive_path, 1) != FR_OK) { - printf("mount failed\r\n"); - continue; - } - - f_chdrive(drive_path); - FRESULT rc = f_chdir("/"); - if (rc != FR_OK) { - printf("chdir failed: %d\r\n", rc); - } - } -} - -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -static bool inquiry_complete_cb(uint8_t dev_addr, const tuh_msc_complete_data_t *cb_data) { - const msc_cbw_t *cbw = cb_data->cbw; - const msc_csw_t *csw = cb_data->csw; - - if (csw->status != 0) { - printf("Inquiry failed\r\n"); - return false; - } - - // Print out Vendor ID, Product ID and Rev - printf("%.8s %.16s %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, - scsi_resp.inquiry.product_rev); - - // Get capacity of device - const uint32_t block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); - const uint32_t block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - - printf("Disk Size: %" PRIu32 " %" PRIu32 "-byte blocks: %" PRIu32 " MB\r\n", - block_count, block_size, block_count / ((1024 * 1024) / block_size)); - - // For simplicity: we only mount 1 LUN per device - const uint8_t drive_num = dev_addr - 1; - _mount_pending[drive_num] = true; - - // print the drive label - // char label[34]; - // if ( FR_OK == f_getlabel(drive_path, label, NULL) ) - // { - // puts(label); - // } - - return true; -} - -//------------- IMPLEMENTATION -------------// -void tuh_msc_mount_cb(uint8_t dev_addr) { - printf("A MassStorage device (addr = %u) is mounted\r\n", dev_addr); - - const uint8_t lun = 0; - tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0); -} - -void tuh_msc_umount_cb(uint8_t dev_addr) { - printf("A MassStorage device is unmounted\r\n"); - - const uint8_t drive_num = dev_addr - 1; - char drive_path[3] = "0:"; - drive_path[0] += drive_num; - - _mount_pending[drive_num] = false; - - f_unmount(drive_path); - - // if ( phy_disk == f_get_current_drive() ) - // { // active drive is unplugged --> change to other drive - // for(uint8_t i=0; icliBuffer = cli_buffer; - config->cliBufferSize = CLI_BUFFER_SIZE; - config->rxBufferSize = CLI_RX_BUFFER_SIZE; - config->cmdBufferSize = CLI_CMD_BUFFER_SIZE; - config->historyBufferSize = CLI_HISTORY_SIZE; - config->maxBindingCount = CLI_BINDING_COUNT; - - TU_ASSERT(embeddedCliRequiredSize(config) <= CLI_BUFFER_SIZE); - - _cli = embeddedCliNew(config); - TU_ASSERT(_cli != NULL); - - _cli->writeChar = cli_write_char; - - embeddedCliAddBinding(_cli, - (CliCommandBinding){"cat", "Usage: cat [FILE]...\r\n\tConcatenate FILE(s) to standard output..", - true, NULL, cli_cmd_cat}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"cd", "Usage: cd [DIR]...\r\n\tChange the current directory to DIR.", - true, NULL, cli_cmd_cd}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"cp", "Usage: cp SOURCE DEST\r\n\tCopy SOURCE to DEST.", true, NULL, - cli_cmd_cp}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"dd", "Usage: dd [COUNT]\r\n\t" "Read COUNT sectors (default 1024) and report speed.", true, NULL, - cli_cmd_dd}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"ls", - "Usage: ls [DIR]...\r\n\tList information about the FILEs (the " - "current directory by default).", - true, NULL, cli_cmd_ls}); - - embeddedCliAddBinding(_cli, - (CliCommandBinding){"pwd", "Usage: pwd\r\n\tPrint the name of the current working directory.", - true, NULL, cli_cmd_pwd}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"mkdir", - "Usage: mkdir DIR...\r\n\tCreate the DIRECTORY(ies), if they do not " - "already exist..", - true, NULL, cli_cmd_mkdir}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"mv", "Usage: mv SOURCE DEST...\r\n\tRename SOURCE to DEST.", true, - NULL, cli_cmd_mv}); - - embeddedCliAddBinding(_cli, (CliCommandBinding){"rm", "Usage: rm [FILE]...\r\n\tRemove (unlink) the FILE(s).", true, - NULL, cli_cmd_rm}); - - return true; -} - -void cli_cmd_dd(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint32_t count = 1024; // default sectors to read - if (embeddedCliGetTokenCount(args) >= 1) { - count = (uint32_t)atoi(embeddedCliGetToken(args, 1)); - if (count == 0) { - count = 1024; - } - } - - // find first mounted MSC device - uint8_t dev_addr = 0; - for (uint8_t i = 1; i <= CFG_TUH_DEVICE_MAX; i++) { - if (tuh_msc_mounted(i)) { - dev_addr = i; - break; - } - } - if (dev_addr == 0) { - printf("no MSC device mounted\r\n"); - return; - } - - const uint8_t lun = 0; - const uint32_t block_size = tuh_msc_get_block_size(dev_addr, lun); - const uint32_t block_count = tuh_msc_get_block_count(dev_addr, lun); - if (count > block_count) { - count = block_count; - } - - const uint16_t sectors_per_xfer = (uint16_t)(sizeof(rw_buf) / block_size); - const uint32_t xfer_count = (count + sectors_per_xfer - 1) / sectors_per_xfer; - - printf("dd: reading %" PRIu32 " sectors (%" PRIu32 " bytes), %u sectors/xfer ...\r\n", - count, count * block_size, sectors_per_xfer); - - const uint32_t start_ms = tusb_time_millis_api(); - const uint8_t pdrv = dev_addr - 1; - bool submit_failed = false; - - for (uint32_t i = 0; i < count; i += sectors_per_xfer) { - const uint16_t n = (uint16_t)((count - i < sectors_per_xfer) ? (count - i) : sectors_per_xfer); - _disk_busy[pdrv] = true; - - if (!tuh_msc_read10(dev_addr, lun, rw_buf, i, n, disk_io_complete, 0)) { - _disk_busy[pdrv] = false; - printf("dd: failed to submit read at sector %" PRIu32 " (%u sectors)\r\n", i, n); - submit_failed = true; - break; - } - - wait_for_disk_io(pdrv); - } - - if (submit_failed) { - return; - } - - const uint32_t elapsed_ms = tusb_time_millis_api() - start_ms; - const uint32_t total_data = count * block_size; - // each SCSI transaction has 31-byte CBW + data + 13-byte CSW - const uint32_t total_bus = total_data + xfer_count * (31 + 13); - - if (elapsed_ms > 0) { - const uint32_t data_kbs = total_data / elapsed_ms; // KB/s (bytes/ms = KB/s) - const uint32_t bus_kbs = total_bus / elapsed_ms; - printf("dd: %" PRIu32 " bytes in %" PRIu32 " ms = %" PRIu32 " KB/s (bus %" PRIu32 " KB/s)\r\n", - total_data, elapsed_ms, data_kbs, bus_kbs); - } else { - printf("dd: %" PRIu32 " bytes in <1 ms\r\n", total_data); - } -} - -void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - - // need at least 1 argument - if (argc == 0) { - printf("invalid arguments\r\n"); - return; - } - - for (uint16_t i = 0; i < argc; i++) { - FIL *fi = &file1; - const char *fpath = embeddedCliGetToken(args, i + 1); // token count from 1 - - if (FR_OK != f_open(fi, fpath, FA_READ)) { - printf("%s: No such file or directory\r\n", fpath); - } else { - UINT count = 0; - while ((FR_OK == f_read(fi, rw_buf, sizeof(rw_buf), &count)) && (count > 0)) { - for (UINT c = 0; c < count; c++) { - const uint8_t ch = rw_buf[c]; - if (isprint(ch) || iscntrl(ch)) { - putchar(ch); - } else { - putchar('.'); - } - } - } - } - - f_close(fi); - } -} - -void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - - // only support 1 argument - if (argc != 1) { - printf("invalid arguments\r\n"); - return; - } - - // default is current directory - const char *dpath = args; - - if (FR_OK != f_chdir(dpath)) { - printf("%s: No such file or directory\r\n", dpath); - return; - } -} - -void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - if (argc != 2) { - printf("invalid arguments\r\n"); - return; - } - - // default is current directory - const char *src = embeddedCliGetToken(args, 1); - const char *dst = embeddedCliGetToken(args, 2); - - FIL *f_src = &file1; - FIL *f_dst = &file2; - - if (FR_OK != f_open(f_src, src, FA_READ)) { - printf("cannot stat '%s': No such file or directory\r\n", src); - return; - } - - if (FR_OK != f_open(f_dst, dst, FA_WRITE | FA_CREATE_ALWAYS)) { - printf("cannot create '%s'\r\n", dst); - f_close(f_src); - return; - } else { - UINT rd_count = 0; - while ((FR_OK == f_read(f_src, rw_buf, sizeof(rw_buf), &rd_count)) && (rd_count > 0)) { - UINT wr_count = 0; - - if (FR_OK != f_write(f_dst, rw_buf, rd_count, &wr_count)) { - printf("cannot write to '%s'\r\n", dst); - break; - } - } - } - - f_close(f_src); - f_close(f_dst); -} - -void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - - // only support 1 argument - if (argc > 1) { - printf("invalid arguments\r\n"); - return; - } - - // default is current directory - const char *dpath = "."; - if (argc) { - dpath = args; - } - - DIR dir; - if (FR_OK != f_opendir(&dir, dpath)) { - printf("cannot access '%s': No such file or directory\r\n", dpath); - return; - } - - FILINFO fno; - while ((f_readdir(&dir, &fno) == FR_OK) && (fno.fname[0] != 0)) { - if (fno.fname[0] != '.') // ignore . and .. entry - { - if (fno.fattrib & AM_DIR) { - // directory - printf("/%s\r\n", fno.fname); - } else { - printf("%-40s", fno.fname); - if (fno.fsize < 1024) { - printf("%" PRIu32 " B\r\n", fno.fsize); - } else { - printf("%" PRIu32 " KB\r\n", fno.fsize / 1024); - } - } - } - } - - f_closedir(&dir); -} - -void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - uint16_t argc = embeddedCliGetTokenCount(args); - - if (argc != 0) { - printf("invalid arguments\r\n"); - return; - } - - char path[256]; - if (FR_OK != f_getcwd(path, sizeof(path))) { - printf("cannot get current working directory\r\n"); - return; - } - - puts(path); -} - -void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - - // only support 1 argument - if (argc != 1) { - printf("invalid arguments\r\n"); - return; - } - - // default is current directory - const char *dpath = args; - - if (FR_OK != f_mkdir(dpath)) { - printf("%s: cannot create this directory\r\n", dpath); - return; - } -} - -void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - if (argc != 2) { - printf("invalid arguments\r\n"); - return; - } - - // default is current directory - const char *src = embeddedCliGetToken(args, 1); - const char *dst = embeddedCliGetToken(args, 2); - - if (FR_OK != f_rename(src, dst)) { - printf("cannot mv %s to %s\r\n", src, dst); - return; - } -} - -void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context) { - (void)cli; - (void)context; - - uint16_t argc = embeddedCliGetTokenCount(args); - - // need at least 1 argument - if (argc == 0) { - printf("invalid arguments\r\n"); - return; - } - - for (uint16_t i = 0; i < argc; i++) { - const char *fpath = embeddedCliGetToken(args, i + 1); // token count from 1 - - if (FR_OK != f_unlink(fpath)) { - printf("cannot remove '%s': No such file or directory\r\n", fpath); - } - } -} diff --git a/examples/host/msc_file_explorer_freertos/src/msc_app.h b/examples/host/msc_file_explorer_freertos/src/msc_app.h deleted file mode 100644 index eff195b1a1..0000000000 --- a/examples/host/msc_file_explorer_freertos/src/msc_app.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2025 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef MSC_APP_H -#define MSC_APP_H - -#include -#include - -bool msc_app_init(void); - -#endif diff --git a/examples/host/msc_file_explorer_freertos/src/tusb_config.h b/examples/host/msc_file_explorer_freertos/src/tusb_config.h deleted file mode 100644 index c3fc4624f1..0000000000 --- a/examples/host/msc_file_explorer_freertos/src/tusb_config.h +++ /dev/null @@ -1,126 +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. - * - */ - -#ifndef TUSB_CONFIG_H_ -#define TUSB_CONFIG_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//-------------------------------------------------------------------- -// Common Configuration -//-------------------------------------------------------------------- - -// defined by compiler flags for flexibility -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_FREERTOS -#endif - -// Espressif IDF requires "freertos/" prefix in include path -#ifdef ESP_PLATFORM -#define CFG_TUSB_OS_INC_PATH freertos/ -#endif - -#ifndef CFG_TUSB_DEBUG -#define CFG_TUSB_DEBUG 0 -#endif - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. - * Tinyusb use follows macros to declare transferring memory so that they can be put - * into those specific section. - * e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUH_MEM_SECTION -#define CFG_TUH_MEM_SECTION -#endif - -#ifndef CFG_TUH_MEM_ALIGN -#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// Host Configuration -//-------------------------------------------------------------------- - -// Enable Host stack -#define CFG_TUH_ENABLED 1 - -// #define CFG_TUH_MAX3421 1 // use max3421 as host controller - -#if CFG_TUSB_MCU == OPT_MCU_RP2040 - // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - - // host roothub port is 1 if using either pio-usb or max3421 - #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) - #define BOARD_TUH_RHPORT 1 - #endif -#endif - -// Default is max speed that hardware controller could support with on-chip PHY -#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED - -//------------------------- Board Specific -------------------------- - -// RHPort number used for host can be defined by board.mk, default to port 0 -#ifndef BOARD_TUH_RHPORT -#define BOARD_TUH_RHPORT 0 -#endif - -// RHPort max operational speed can defined by board.mk -#ifndef BOARD_TUH_MAX_SPEED -#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED -#endif - -//-------------------------------------------------------------------- -// Driver Configuration -//-------------------------------------------------------------------- - -// Size of buffer to hold descriptors and other data used for enumeration -#define CFG_TUH_ENUMERATION_BUFSIZE 256 - -#define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_MSC 1 -#define CFG_TUH_CDC 0 -#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces -#define CFG_TUH_VENDOR 0 - -// max device support (excluding hub device): 1 hub typically has 4 ports -#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) - -//------------- MSC -------------// -#define CFG_TUH_MSC_MAXLUN 4 // typical for most card reader - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_CONFIG_H_ */ From e657a8705252e0d41f045232852ccce09aede816 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 29 Jun 2026 14:58:32 +0200 Subject: [PATCH 4/4] Fix merged example Sonar warnings --- .../device/audio_4_channel_mic/src/main.c | 42 +++---- examples/device/audio_test/src/main.c | 46 ++++---- examples/device/cdc_msc/src/main.c | 110 +++++++++--------- examples/device/hid_composite/src/main.c | 82 ++++++------- examples/device/midi_test/src/main.c | 97 ++++++++------- examples/device/uac2_speaker_fb/src/main.c | 62 +++++----- examples/host/cdc_msc_hid/src/main.c | 4 +- examples/host/msc_file_explorer/src/main.c | 4 +- 8 files changed, 226 insertions(+), 221 deletions(-) diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 38f42d11f8..0729b4da1d 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -111,6 +111,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -126,8 +127,6 @@ int main(void) { audio_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -168,19 +167,19 @@ void audio_task(void *param) { (void) param; static uint32_t start_ms = 0; +#if CFG_TUSB_OS == OPT_OS_FREERTOS while (1) { - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms != curr_ms) { - start_ms = curr_ms; - tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); - } +#endif + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); + } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); -#else - return; -#endif + vTaskDelay(1); } +#endif } //--------------------------------------------------------------------+ @@ -427,21 +426,24 @@ void led_blinking_task(void *param) { (void) param; static bool led_state = false; - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - static uint32_t start_ms = 0; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } - start_ms += blink_interval_ms; + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = 1 - led_state;// toggle + board_led_write(led_state); + led_state = 1 - led_state;// toggle + +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 4f0fa30403..e286dc4f07 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -93,6 +93,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -108,8 +109,6 @@ int main(void) { audio_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -151,22 +150,22 @@ void audio_task(void *param) { (void) param; static uint32_t start_ms = 0; +#if CFG_TUSB_OS == OPT_OS_FREERTOS while (1) { - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms != curr_ms) { - start_ms = curr_ms; - for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { - test_buffer_audio[cnt] = startVal++; - } - tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); +#endif + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { + test_buffer_audio[cnt] = startVal++; } + tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); + } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); -#else - return; -#endif + vTaskDelay(1); } +#endif } //--------------------------------------------------------------------+ @@ -421,21 +420,24 @@ void led_blinking_task(void *param) { (void) param; static bool led_state = false; - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - static uint32_t start_ms = 0; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } - start_ms += blink_interval_ms; + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = 1 - led_state;// toggle + board_led_write(led_state); + led_state = 1 - led_state;// toggle + +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 1318f6f321..f47da4d1ea 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -59,6 +59,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; @@ -74,8 +75,6 @@ int main(void) { cdc_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -112,47 +111,47 @@ void tud_resume_cb(void) { void cdc_task(void *param) { (void) param; +#if CFG_TUSB_OS == OPT_OS_FREERTOS while (1) { - // connected() check for DTR bit - // Most but not all terminal client set this when making connection - // if ( tud_cdc_connected() ) - { - // connected and there are data available - while (tud_cdc_available()) { - // read data - char buf[64]; - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - (void)count; - - // Echo back - // Note: Skip echo by commenting out write() and write_flush() - // for throughput test e.g - // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 - tud_cdc_write(buf, count); - } - - tud_cdc_write_flush(); - - // Press on-board button to send Uart status notification - static cdc_notify_uart_state_t uart_state = {.value = 0}; - - static uint32_t btn_prev = 0; - const uint32_t btn = board_button_read(); - - if ((btn_prev == 0u) && (btn != 0u)) { - uart_state.dsr ^= 1; - uart_state.dcd ^= 1; - tud_cdc_notify_uart_state(&uart_state); - } - btn_prev = btn; +#endif + // connected() check for DTR bit + // Most but not all terminal client set this when making connection + // if ( tud_cdc_connected() ) + { + // connected and there are data available + while (tud_cdc_available()) { + // read data + char buf[64]; + uint32_t count = tud_cdc_read(buf, sizeof(buf)); + (void)count; + + // Echo back + // Note: Skip echo by commenting out write() and write_flush() + // for throughput test e.g + // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 + tud_cdc_write(buf, count); + } + + tud_cdc_write_flush(); + + // Press on-board button to send Uart status notification + static cdc_notify_uart_state_t uart_state = {.value = 0}; + + static uint32_t btn_prev = 0; + const uint32_t btn = board_button_read(); + + if ((btn_prev == 0u) && (btn != 0u)) { + uart_state.dsr ^= 1; + uart_state.dcd ^= 1; + tud_cdc_notify_uart_state(&uart_state); } + btn_prev = btn; + } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); -#else - break; -#endif + vTaskDelay(1); } +#endif } // Invoked when cdc when line state changed e.g connected/disconnected @@ -185,33 +184,34 @@ void led_blinking_task(void *param) { static uint32_t start_ms = 0; #endif - while (1) { - if (!blink_enable) { #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); - continue; + while (1) { + if (!blink_enable) { + vTaskDelay(1); + continue; + } #else - return; + if (!blink_enable) { + return; + } #endif - } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } - start_ms += blink_interval_ms; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = !led_state; + board_led_write(led_state); + led_state = !led_state; -#if CFG_TUSB_OS != OPT_OS_FREERTOS - break; -#endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 089ff3ff1e..5bfd048a13 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -63,6 +63,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; @@ -76,8 +77,6 @@ int main(void) { hid_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -218,36 +217,35 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) { void hid_task(void *param) { (void) param; - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(pdMS_TO_TICKS(10)); #else - // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; + // Poll every 10ms + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - if (tusb_time_millis_api() - start_ms < interval_ms) { - return; // not enough time - } - start_ms += interval_ms; + if (tusb_time_millis_api() - start_ms < interval_ms) { + return; // not enough time + } + start_ms += interval_ms; #endif - uint32_t const btn = board_button_read(); + uint32_t const btn = board_button_read(); - // Remote wakeup - if (tud_suspended() && btn != 0u) { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - tud_remote_wakeup(); - } else { - // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() - send_hid_report(REPORT_ID_KEYBOARD, btn); - } + // Remote wakeup + if (tud_suspended() && btn != 0u) { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + } else { + // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() + send_hid_report(REPORT_ID_KEYBOARD, btn); + } -#if CFG_TUSB_OS != OPT_OS_FREERTOS - break; -#endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } // Invoked when sent REPORT successfully to host @@ -318,34 +316,36 @@ void led_blinking_task(void *param) { static uint32_t start_ms = 0; #endif - while (1) { - // blink is disabled - if (0u == blink_interval_ms) { #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); - continue; + while (1) { + // blink is disabled + if (0u == blink_interval_ms) { + vTaskDelay(1); + continue; + } #else - return; + // blink is disabled + if (0u == blink_interval_ms) { + return; + } #endif - } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } - start_ms += blink_interval_ms; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = 1 - led_state; // toggle -#if CFG_TUSB_OS != OPT_OS_FREERTOS - break; -#endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 3e86d2dd6a..95dc11433b 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -68,6 +68,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -84,8 +85,6 @@ int main(void) { midi_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -134,55 +133,56 @@ void midi_task(void *param) { uint8_t const cable_num = 0; // MIDI jack associated with USB endpoint uint8_t const channel = 0; // 0 for channel 1 +#if CFG_TUSB_OS == OPT_OS_FREERTOS while (1) { - // 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); - } +#endif + // 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); + } #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(286 / portTICK_PERIOD_MS); + vTaskDelay(286 / portTICK_PERIOD_MS); #else - static uint32_t start_ms = 0; - // send note periodically - if (tusb_time_millis_api() - start_ms < 286) { - return; // not enough time - } - start_ms += 286; + static uint32_t start_ms = 0; + // send note periodically + if (tusb_time_millis_api() - start_ms < 286) { + return; // not enough time + } + start_ms += 286; #endif - // Previous positions in the note sequence. - int previous = (int) (note_pos - 1); + // 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; - } + // 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 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); + // 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++; + // Increment position + note_pos++; - // If we are at the end of the sequence, start over. - if (note_pos >= sizeof(note_sequence)) { - note_pos = 0; - } + // If we are at the end of the sequence, start over. + if (note_pos >= sizeof(note_sequence)) { + note_pos = 0; + } -#if CFG_TUSB_OS != OPT_OS_FREERTOS - break; -#endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ @@ -195,24 +195,23 @@ void led_blinking_task(void *param) { static uint32_t start_ms = 0; #endif - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } - start_ms += blink_interval_ms; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = 1 - led_state; // toggle -#if CFG_TUSB_OS != OPT_OS_FREERTOS - break; -#endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index e09015382f..c57203a8cc 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -95,6 +95,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS freertos_init(); + return 0; #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -115,8 +116,6 @@ int main(void) { audio_task(NULL); } #endif - - return 0; } //--------------------------------------------------------------------+ @@ -602,32 +601,32 @@ void audio_task(void *param) { (void) param; static uint32_t start_ms = 0; +#if CFG_TUSB_OS == OPT_OS_FREERTOS while (1) { - uint32_t curr_ms = tusb_time_millis_api(); - if (start_ms != curr_ms) { - start_ms = curr_ms; - - uint16_t length = (uint16_t) (current_sample_rate / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); - - if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) { - // Take one more sample every 10 cycles, to have a average reading speed of 44.1 - // This correction is not needed in real world cases - length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; - } else if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) { - // Take one more sample every 5 cycles, to have a average reading speed of 88.2 - // This correction is not needed in real world cases - length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; - } - - tud_audio_read(i2s_dummy_buffer, length); +#endif + uint32_t curr_ms = tusb_time_millis_api(); + if (start_ms != curr_ms) { + start_ms = curr_ms; + + uint16_t length = (uint16_t) (current_sample_rate / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); + + if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) { + // Take one more sample every 10 cycles, to have a average reading speed of 44.1 + // This correction is not needed in real world cases + length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; + } else if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) { + // Take one more sample every 5 cycles, to have a average reading speed of 88.2 + // This correction is not needed in real world cases + length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; } + tud_audio_read(i2s_dummy_buffer, length); + } + #if CFG_TUSB_OS == OPT_OS_FREERTOS - vTaskDelay(1); -#else - return; -#endif + vTaskDelay(1); } +#endif } //--------------------------------------------------------------------+ @@ -637,19 +636,22 @@ void led_blinking_task(void *param) { (void) param; static bool led_state = false; - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - static uint32_t start_ms = 0; - // Blink every interval ms - if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; - start_ms += blink_interval_ms; + static uint32_t start_ms = 0; + // Blink every interval ms + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; + start_ms += blink_interval_ms; #endif - board_led_write(led_state); - led_state = 1 - led_state; + board_led_write(led_state); + led_state = 1 - led_state; + +#if CFG_TUSB_OS == OPT_OS_FREERTOS } +#endif } #if CFG_AUDIO_DEBUG diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c2685e8472..3ed5883a25 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -87,6 +87,8 @@ int main(void) { #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif + + return 0; #else // init host stack on configured roothub port tusb_rhport_init_t host_init = { @@ -112,8 +114,6 @@ int main(void) { hid_app_task(); } #endif - - return 0; } #ifdef ESP_PLATFORM diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index 58b51761b0..d1002bbee9 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -87,6 +87,8 @@ int main(void) { #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif + + return 0; #else // init host stack on configured roothub port tusb_rhport_init_t host_init = { @@ -107,8 +109,6 @@ int main(void) { led_blinking_task(); } #endif - - return 0; } #ifdef ESP_PLATFORM