diff options
| author | copilot-swe-agent[bot] <[email protected]> | 2026-04-23 09:49:02 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-23 09:49:02 +0000 |
| commit | 5c0c1662464e48681533e8ecc1217613fb6e3820 (patch) | |
| tree | c3610534cb8307504707bd0c27eab5f461fc863d /examples | |
| parent | b46147a497bf68d680e9a8a898eeca2d255ce53b (diff) | |
| parent | 1e644339fd984fd6168b8cc09728d3bb56f2eea2 (diff) | |
Merge upstream master into net descriptor-based ep_size branch
- Resolve .gitignore conflict: incorporate upstream's .worktrees entry and
expand dependency path patterns to cover all tools/get_deps.py fetched dirs
(lib/, tools/linkermap, tools/uf2, hw/mcu/*) instead of listing only a few
- Auto-merged upstream changes: build system cleanups, BSP updates,
portability fixes, new boards (nrf54lm20dk, stm32h743_weact),
fatfs relocation, and many other upstream improvements
- Net driver changes (ecm_rndis_device.c, ncm_device.c, net_device.h,
usbd.h, usb_descriptors.c) retain our PR's descriptor-based ep_size
approach as our branch takes precedence
Co-authored-by: HiFiPhile <[email protected]>
Diffstat (limited to 'examples')
46 files changed, 571 insertions, 291 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b458c9ce3..7669290a8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -26,9 +26,3 @@ add_custom_target(tinyusb_metrics COMMENT "Generating average code size metrics" VERBATIM ) - -#add_custom_command(TARGET tinyusb_metrics POST_BUILD -# COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../tools/metrics.py compare ${TOP}/cmake-build/cmake-build-${BOARD}/metrics.json ${CMAKE_BINARY_DIR}/metrics.json -# COMMENT "Generating average code size metrics" -# VERBATIM -# ) diff --git a/examples/build_system/make/cpu/arm1176jzf-s.mk b/examples/build_system/make/cpu/arm1176jzf-s.mk index 022ccf7ad..c0cef8784 100644 --- a/examples/build_system/make/cpu/arm1176jzf-s.mk +++ b/examples/build_system/make/cpu/arm1176jzf-s.mk @@ -2,8 +2,4 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ -mcpu=arm1176jzf-s \ -else ifeq ($(TOOLCHAIN),iar) - #CFLAGS += --cpu cortex-a53 - #ASFLAGS += --cpu cortex-a53 - endif diff --git a/examples/build_system/make/cpu/arm926ej-s.mk b/examples/build_system/make/cpu/arm926ej-s.mk index 5b84f514f..e0558eca7 100644 --- a/examples/build_system/make/cpu/arm926ej-s.mk +++ b/examples/build_system/make/cpu/arm926ej-s.mk @@ -2,8 +2,4 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ -mcpu=arm926ej-s \ -else ifeq ($(TOOLCHAIN),iar) - #CFLAGS += --cpu cortex-a53 - #ASFLAGS += --cpu cortex-a53 - endif diff --git a/examples/build_system/make/cpu/cortex-a53.mk b/examples/build_system/make/cpu/cortex-a53.mk index 42e522ecf..20ed8f0cc 100644 --- a/examples/build_system/make/cpu/cortex-a53.mk +++ b/examples/build_system/make/cpu/cortex-a53.mk @@ -2,11 +2,4 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ -mcpu=cortex-a53 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-a53 \ - - ASFLAGS += \ - --cpu cortex-a53 \ - endif diff --git a/examples/build_system/make/cpu/cortex-a72.mk b/examples/build_system/make/cpu/cortex-a72.mk index 1b3d8da4a..b2b3d9181 100644 --- a/examples/build_system/make/cpu/cortex-a72.mk +++ b/examples/build_system/make/cpu/cortex-a72.mk @@ -2,11 +2,4 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ -mcpu=cortex-a72 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-a72 \ - - ASFLAGS += \ - --cpu cortex-a72 \ - endif diff --git a/examples/build_system/make/cpu/cortex-m0.mk b/examples/build_system/make/cpu/cortex-m0.mk index c2c33a2ee..1d618982e 100644 --- a/examples/build_system/make/cpu/cortex-m0.mk +++ b/examples/build_system/make/cpu/cortex-m0.mk @@ -9,11 +9,6 @@ else ifeq ($(TOOLCHAIN),clang) --target=arm-none-eabi \ -mcpu=cortex-m0 \ -else ifeq ($(TOOLCHAIN),iar) - # IAR Flags - CFLAGS += --cpu cortex-m0 - ASFLAGS += --cpu cortex-m0 - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m0plus.mk b/examples/build_system/make/cpu/cortex-m0plus.mk index fe8feb227..029ce09d1 100644 --- a/examples/build_system/make/cpu/cortex-m0plus.mk +++ b/examples/build_system/make/cpu/cortex-m0plus.mk @@ -9,11 +9,6 @@ else ifeq ($(TOOLCHAIN),clang) --target=arm-none-eabi \ -mcpu=cortex-m0plus \ -else ifeq ($(TOOLCHAIN),iar) - # IAR Flags - CFLAGS += --cpu cortex-m0+ - ASFLAGS += --cpu cortex-m0+ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m23.mk b/examples/build_system/make/cpu/cortex-m23.mk index 7ab758352..b92e24401 100644 --- a/examples/build_system/make/cpu/cortex-m23.mk +++ b/examples/build_system/make/cpu/cortex-m23.mk @@ -9,11 +9,6 @@ else ifeq ($(TOOLCHAIN),clang) --target=arm-none-eabi \ -mcpu=cortex-m23 \ -else ifeq ($(TOOLCHAIN),iar) - # IAR Flags - CFLAGS += --cpu cortex-m23 - ASFLAGS += --cpu cortex-m23 - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m3.mk b/examples/build_system/make/cpu/cortex-m3.mk index b6325313f..b58f0203b 100644 --- a/examples/build_system/make/cpu/cortex-m3.mk +++ b/examples/build_system/make/cpu/cortex-m3.mk @@ -9,11 +9,6 @@ else ifeq ($(TOOLCHAIN),clang) --target=arm-none-eabi \ -mcpu=cortex-m3 \ -else ifeq ($(TOOLCHAIN),iar) - # IAR Flags - CFLAGS += --cpu cortex-m3 - ASFLAGS += --cpu cortex-m3 - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk index 405053dd0..858a721fd 100644 --- a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk +++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk @@ -10,13 +10,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m33 \ -mfpu=softvp \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m33+nodsp \ - - ASFLAGS += \ - --cpu cortex-m33+nodsp \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m33.mk b/examples/build_system/make/cpu/cortex-m33.mk index 47b0eaecd..5699fef7b 100644 --- a/examples/build_system/make/cpu/cortex-m33.mk +++ b/examples/build_system/make/cpu/cortex-m33.mk @@ -11,15 +11,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m33 \ -mfpu=fpv5-sp-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m33 \ - --fpu VFPv5-SP \ - - ASFLAGS += \ - --cpu cortex-m33 \ - --fpu VFPv5-SP \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m4-nofpu.mk b/examples/build_system/make/cpu/cortex-m4-nofpu.mk index ac2916005..62ab21e31 100644 --- a/examples/build_system/make/cpu/cortex-m4-nofpu.mk +++ b/examples/build_system/make/cpu/cortex-m4-nofpu.mk @@ -9,10 +9,6 @@ else ifeq ($(TOOLCHAIN),clang) --target=arm-none-eabi \ -mcpu=cortex-m4 -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += --cpu cortex-m4 --fpu none - ASFLAGS += --cpu cortex-m4 --fpu none - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m4.mk b/examples/build_system/make/cpu/cortex-m4.mk index 57d6e126d..e50fe00ef 100644 --- a/examples/build_system/make/cpu/cortex-m4.mk +++ b/examples/build_system/make/cpu/cortex-m4.mk @@ -11,10 +11,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m4 \ -mfpu=fpv4-sp-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += --cpu cortex-m4 --fpu VFPv4-SP - ASFLAGS += --cpu cortex-m4 --fpu VFPv4-SP - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m55.mk b/examples/build_system/make/cpu/cortex-m55.mk index de627caed..94cca1a5e 100644 --- a/examples/build_system/make/cpu/cortex-m55.mk +++ b/examples/build_system/make/cpu/cortex-m55.mk @@ -12,15 +12,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m55 \ -mfpu=fpv5-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m55 \ - --fpu VFPv5_D16 \ - - ASFLAGS += \ - --cpu cortex-m55 \ - --fpu VFPv5_D16 \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m7-fpsp.mk b/examples/build_system/make/cpu/cortex-m7-fpsp.mk index cd42c6fb8..e79ff6d73 100644 --- a/examples/build_system/make/cpu/cortex-m7-fpsp.mk +++ b/examples/build_system/make/cpu/cortex-m7-fpsp.mk @@ -11,15 +11,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m7 \ -mfpu=fpv5-sp-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m7 \ - --fpu VFPv5_sp \ - - ASFLAGS += \ - --cpu cortex-m7 \ - --fpu VFPv5_sp \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m7.mk b/examples/build_system/make/cpu/cortex-m7.mk index 3e6116179..3bd5c1155 100644 --- a/examples/build_system/make/cpu/cortex-m7.mk +++ b/examples/build_system/make/cpu/cortex-m7.mk @@ -11,15 +11,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m7 \ -mfpu=fpv5-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m7 \ - --fpu VFPv5_D16 \ - - ASFLAGS += \ - --cpu cortex-m7 \ - --fpu VFPv5_D16 \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/cortex-m85.mk b/examples/build_system/make/cpu/cortex-m85.mk index 75e8f3aaf..d66e26418 100644 --- a/examples/build_system/make/cpu/cortex-m85.mk +++ b/examples/build_system/make/cpu/cortex-m85.mk @@ -11,15 +11,6 @@ else ifeq ($(TOOLCHAIN),clang) -mcpu=cortex-m85 \ -mfpu=fpv5-d16 \ -else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ - --cpu cortex-m85 \ - --fpu VFPv5_D16 \ - - ASFLAGS += \ - --cpu cortex-m85 \ - --fpu VFPv5_D16 \ - else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/msp430.mk b/examples/build_system/make/cpu/msp430.mk index 6daa2c38d..83a35140f 100644 --- a/examples/build_system/make/cpu/msp430.mk +++ b/examples/build_system/make/cpu/msp430.mk @@ -2,8 +2,6 @@ ifeq ($(TOOLCHAIN),gcc) # nothing to add else ifeq ($(TOOLCHAIN),clang) # nothing to add -else ifeq ($(TOOLCHAIN),iar) - # nothing to add else $(error "TOOLCHAIN is not supported") endif diff --git a/examples/build_system/make/cpu/rv32i-ilp32.mk b/examples/build_system/make/cpu/rv32i-ilp32.mk index af764afc5..6b2306008 100644 --- a/examples/build_system/make/cpu/rv32i-ilp32.mk +++ b/examples/build_system/make/cpu/rv32i-ilp32.mk @@ -8,8 +8,6 @@ else ifeq ($(TOOLCHAIN),clang) -march=rv32i_zicsr \ -mabi=ilp32 \ -else ifeq ($(TOOLCHAIN),iar) - $(error not support) endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/rv32imac-ilp32.mk b/examples/build_system/make/cpu/rv32imac-ilp32.mk index a7b2258d7..e4a3ad24f 100644 --- a/examples/build_system/make/cpu/rv32imac-ilp32.mk +++ b/examples/build_system/make/cpu/rv32imac-ilp32.mk @@ -8,9 +8,6 @@ else ifeq ($(TOOLCHAIN),clang) -march=rv32imac_zicsr_zifencei \ -mabi=ilp32 \ -else ifeq ($(TOOLCHAIN),iar) - $(error not support) - endif # For freeRTOS port source diff --git a/examples/build_system/make/toolchain/arm_iar.mk b/examples/build_system/make/toolchain/arm_iar.mk deleted file mode 100644 index 17967b41a..000000000 --- a/examples/build_system/make/toolchain/arm_iar.mk +++ /dev/null @@ -1,13 +0,0 @@ -# makefile for arm iar toolchain - -CC = iccarm -AS = iasmarm -LD = ilinkarm -OBJCOPY = ielftool --silent -SIZE = size - -# Enable extension mode (gcc compatible) -CFLAGS += -e --debug --silent - -# silent mode -ASFLAGS += -S $(addprefix -I,$(INC)) diff --git a/examples/build_system/make/toolchain/gcc_rules.mk b/examples/build_system/make/toolchain/gcc_rules.mk index fc5225503..3463cad48 100644 --- a/examples/build_system/make/toolchain/gcc_rules.mk +++ b/examples/build_system/make/toolchain/gcc_rules.mk @@ -1,5 +1,3 @@ -SRC_S += $(SRC_S_GCC) - # Assembly files can be name with upper case .S, convert it to .s SRC_S := $(SRC_S:.S=.s) @@ -9,7 +7,7 @@ SRC_S := $(SRC_S:.S=.s) OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) -CFLAGS += $(CFLAGS_GCC) -MD +CFLAGS += -MD # LTO makes it difficult to analyze map file for optimizing size purpose # We will run this option in ci @@ -25,18 +23,13 @@ ifeq ($(TOOLCHAIN),clang) CFLAGS += $(CFLAGS_CLANG) LDFLAGS += $(CFLAGS) $(LDFLAGS_CLANG) else -LDFLAGS += $(CFLAGS) $(LDFLAGS_GCC) +LDFLAGS += $(CFLAGS) endif -# TODO should be removed after all examples are updated ifdef LD_FILE LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE) endif -ifdef LD_FILE_GCC -LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE_GCC) -endif - ASFLAGS += $(CFLAGS) # libc diff --git a/examples/build_system/make/toolchain/iar_rules.mk b/examples/build_system/make/toolchain/iar_rules.mk deleted file mode 100644 index 2c066f6da..000000000 --- a/examples/build_system/make/toolchain/iar_rules.mk +++ /dev/null @@ -1,44 +0,0 @@ -SRC_S += $(SRC_S_IAR) - -# Assembly files can be name with upper case .S, convert it to .s -SRC_S := $(SRC_S:.S=.s) - -# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 -# assembly file should be placed first in linking order -# '_asm' suffix is added to object of assembly file -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) - -# Linker script -LDFLAGS += --config $(TOP)/$(LD_FILE_IAR) - -# --------------------------------------- -# Rules -# --------------------------------------- - -# Compile .c file -$(BUILD)/obj/%.o: %.c - @echo CC $(notdir $@) - @$(CC) $(CFLAGS) -c -o $@ $< - -# ASM sources lower case .s -$(BUILD)/obj/%_asm.o: %.s - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -# ASM sources upper case .S -$(BUILD)/obj/%_asm.o: %.S - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - @$(OBJCOPY) --bin $^ $@ - -$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - @$(OBJCOPY) --ihex $^ $@ - -$(BUILD)/$(PROJECT).elf: $(OBJ) - @echo LINK $@ - @$(LD) -o $@ $(LDFLAGS) $^ diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index be44cb2c0..61a7b0605 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MCXA15 mcu:MKL25ZXX mcu:MSP430x5xx mcu:FT90X -mcu:RP2040 mcu:SAMD11 mcu:VALENTYUSB_EPTRI mcu:RAXXX diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 4572bbb3c..eac66a4ef 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -310,7 +310,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = ((audio20_control_cur_2_t *) pBuff)->bCur; + 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; diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 007fece53..386a0cdfb 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MCXA15 mcu:MKL25ZXX mcu:MSP430x5xx mcu:FT90X -mcu:RP2040 mcu:SAMD11 mcu:VALENTYUSB_EPTRI mcu:RAXXX diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index 31d808d8e..429c62d93 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MCXA15 mcu:MKL25ZXX mcu:MSP430x5xx mcu:FT90X -mcu:RP2040 mcu:SAMD11 mcu:VALENTYUSB_EPTRI mcu:RAXXX diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index ff918205e..ab551c288 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -168,7 +168,7 @@ static void io_task(void *params) { 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 = io_ops.bufsize; + int32_t nbytes = (int32_t) io_ops.bufsize; if (io_ops.is_read) { memcpy(io_ops.buffer, addr, io_ops.bufsize); } else { diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index 8ae238584..d2ee8d636 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MCXA15 mcu:MKL25ZXX mcu:MSP430x5xx mcu:FT90X -mcu:RP2040 mcu:SAMD11 mcu:VALENTYUSB_EPTRI mcu:RAXXX diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt index 8ae238584..d2ee8d636 100644 --- a/examples/device/midi_test_freertos/skip.txt +++ b/examples/device/midi_test_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MCXA15 mcu:MKL25ZXX mcu:MSP430x5xx mcu:FT90X -mcu:RP2040 mcu:SAMD11 mcu:VALENTYUSB_EPTRI mcu:RAXXX diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c index 60fc9f79e..09697693e 100644 --- a/examples/device/mtp/src/mtp_fs_example.c +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -275,11 +275,11 @@ int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) { resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; } else { resp_code = handler(cb_data); - if (resp_code > MTP_RESP_UNDEFINED) { - // send response if needed - io_container->header->code = (uint16_t)resp_code; - tud_mtp_response_send(io_container); - } + } + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); } return resp_code; @@ -302,11 +302,11 @@ int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data) { resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; } else { resp_code = handler(cb_data); - if (resp_code > MTP_RESP_UNDEFINED) { - // send response if needed - io_container->header->code = (uint16_t)resp_code; - tud_mtp_response_send(io_container); - } + } + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); } return 0; diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 9d8e8ec77..6002039b3 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -1,7 +1,7 @@ include ../../../hw/bsp/family_support.mk # suppress warning caused by lwip -CFLAGS_GCC += \ +CFLAGS += \ -Wno-error=null-dereference \ -Wno-error=unused-parameter \ -Wno-error=unused-variable diff --git a/examples/dual/host_hid_to_device_cdc/Makefile b/examples/dual/host_hid_to_device_cdc/Makefile index a51251bf9..595cd7dec 100644 --- a/examples/dual/host_hid_to_device_cdc/Makefile +++ b/examples/dual/host_hid_to_device_cdc/Makefile @@ -8,7 +8,7 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference SRC_C += \ src/class/hid/hid_host.c \ diff --git a/examples/dual/host_info_to_device_cdc/Makefile b/examples/dual/host_info_to_device_cdc/Makefile index 659cf6ff9..3a1d87f57 100644 --- a/examples/dual/host_info_to_device_cdc/Makefile +++ b/examples/dual/host_info_to_device_cdc/Makefile @@ -8,7 +8,7 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference SRC_C += \ src/host/hub.c \ diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 4c2c5e807..20033981e 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -28,11 +28,13 @@ #include "bsp/board_api.h" #include "app.h" -static size_t get_console_inputs(uint8_t* buf, size_t bufsize) { +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; } + const int ch = board_getchar(); + if (ch < 0) { + break; + } buf[count] = (uint8_t) ch; count++; } @@ -40,46 +42,50 @@ static size_t get_console_inputs(uint8_t* buf, size_t bufsize) { return count; } +static size_t console_write(const uint8_t *buf, size_t bufsize) { + // Use board_uart_write directly for non-blocking behavior. + // board_putchar -> sys_write has a blocking retry loop that causes UART RX overrun. + int wr = board_uart_write(buf, (int) bufsize); + return (wr > 0) ? (size_t) wr : 0; +} + +// forward from console to usbh +static void console_to_usbh(uint8_t idx) { + uint8_t buf[64]; + size_t count = console_read(buf, sizeof(buf)); + if (count > 0) { + tuh_cdc_write(idx, buf, count); + } +} + void cdc_app_task(void) { - uint8_t buf[64 + 1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf) - 1; + const uint8_t idx = 0; + + // Bidirectional forwarding: console <-> host cdc interfaces + if (!tuh_cdc_mounted(idx)) { + return; + } - uint32_t count = get_console_inputs(buf, bufsize); - buf[count] = 0; + // usbh -> uart + uint8_t buf[64]; + uint32_t count = tuh_cdc_read(idx, buf, sizeof(buf)); + uint32_t wr = 0; - // loop over all mounted interfaces - for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { - if (tuh_cdc_mounted(idx)) { - // console --> cdc interfaces - if (count > 0) { - tuh_cdc_write(idx, buf, count); - tuh_cdc_write_flush(idx); - } + do { + // uart write is slow, while waiting forward uart -> usbh else uart rx can be overflow + if (count) { + wr += console_write(buf + wr, count - wr); } - } + console_to_usbh(idx); + } while (wr < count); + + tuh_cdc_write_flush(idx); } //--------------------------------------------------------------------+ // 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 - const uint32_t count = tuh_cdc_read(idx, buf, bufsize); - if (count) { - buf[count] = 0; - printf("%s", (char*) buf); - - #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? - fflush(stdout);// flush right away, else nanolib will wait for newline - #endif - } -} - // Invoked when a device with CDC interface is mounted // idx is index of cdc interface in the internal pool. void tuh_cdc_mount_cb(uint8_t idx) { diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index dd4e22d7f..8181bdcb9 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -41,14 +41,14 @@ 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 rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + printf("%.8s %.16s %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); // Get capacity of device uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size)); - printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size); + printf("Disk Size: %" PRIu32 " %" PRIu32 "-byte blocks: %" PRIu32 " MB\r\n", + block_count, block_size, block_count / ((1024 * 1024) / block_size)); return true; } diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 75de3511c..26fcdd1cb 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -102,8 +102,11 @@ // Size of buffer to hold descriptors and other data used for enumeration #define CFG_TUH_ENUMERATION_BUFSIZE 256 +// Increase task event queue to handle rapid bulk transfer completions +#define CFG_TUH_TASK_QUEUE_SZ 64 + #define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 2 // number of supported CDC devices. also activates CDC ACM +#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 diff --git a/examples/host/cdc_msc_hid_freertos/skip.txt b/examples/host/cdc_msc_hid_freertos/skip.txt index bb62547a6..f0be07d25 100644 --- a/examples/host/cdc_msc_hid_freertos/skip.txt +++ b/examples/host/cdc_msc_hid_freertos/skip.txt @@ -1,4 +1,3 @@ mcu:CH32F20X -mcu:RP2040 board:lpcxpresso54114 mcu:FT90X diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 0e0105980..30baacaac 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -53,7 +53,7 @@ void cdc_app_init(void) { } // helper -static size_t get_console_inputs(uint8_t *buf, size_t bufsize) { +static size_t console_read(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { int ch = board_getchar(); @@ -75,7 +75,7 @@ static void cdc_app_task(void* param) { uint32_t const bufsize = sizeof(buf) - 1; while (1) { - uint32_t count = get_console_inputs(buf, bufsize); + uint32_t count = console_read(buf, bufsize); buf[count] = 0; if (count) { diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index fa864c364..17df11951 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -47,14 +47,14 @@ 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 rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.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); uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size)); - printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size); + printf("Disk Size: %" PRIu32 " %" PRIu32 "-byte blocks: %" PRIu32 " MB\r\n", + block_count, block_size, block_count / ((1024 * 1024) / block_size)); return true; } diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 21703030c..c8d196447 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -23,13 +23,6 @@ target_sources(${PROJECT_NAME} PUBLIC ${TOP}/lib/fatfs/source/ffunicode.c ) -# 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_FLAGS "-Wno-conversion -Wno-cast-qual" - ) -endif () - # Example include target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -40,3 +33,10 @@ target_include_directories(${PROJECT_NAME} PUBLIC # 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} noos) + +# 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/Makefile b/examples/host/msc_file_explorer/Makefile index 39d00d982..8c0b012ad 100644 --- a/examples/host/msc_file_explorer/Makefile +++ b/examples/host/msc_file_explorer/Makefile @@ -21,6 +21,6 @@ SRC_C += \ $(FATFS_PATH)/ffunicode.c \ # suppress warning caused by fatfs -CFLAGS_GCC += -Wno-error=cast-qual +CFLAGS += -Wno-error=cast-qual include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/msc_file_explorer/README.md b/examples/host/msc_file_explorer/README.md new file mode 100644 index 000000000..e220bedea --- /dev/null +++ b/examples/host/msc_file_explorer/README.md @@ -0,0 +1,105 @@ +# MSC File Explorer + +This host example implements an interactive command-line file browser for USB Mass Storage devices. +When a USB flash drive is connected, the device is automatically mounted using FatFS and a shell-like +CLI is presented over the board's serial console. + +## Features + +- Automatic mount/unmount of USB storage devices +- FAT12/16/32 filesystem support via FatFS +- Interactive CLI with command history +- Read speed benchmarking with `dd` +- Support for up to 4 simultaneous USB storage devices (via hub) + +## Supported Commands + +| Command | Usage | Description | +|---------|--------------------|------------------------------------------------------| +| help | `help` | Print list of available commands | +| cat | `cat <file>` | Print file contents to the console | +| cd | `cd <dir>` | Change current working directory | +| cp | `cp <src> <dest>` | Copy a file | +| dd | `dd [count]` | Read sectors and report speed (default 1024 sectors) | +| ls | `ls [dir]` | List directory contents | +| pwd | `pwd` | Print current working directory | +| mkdir | `mkdir <dir>` | Create a directory | +| mv | `mv <src> <dest>` | Rename/move a file or directory | +| rm | `rm <file>` | Remove a file | + +## Build + +Build for a specific board using CMake (see [Getting Started](https://docs.tinyusb.org/en/latest/getting_started.html)): + +```bash +# Example: build for Raspberry Pi Pico +cmake -B build -DBOARD=raspberry_pi_pico -DFAMILY=rp2040 examples/host/msc_file_explorer +cmake --build build +``` + +## Usage + +1. Flash the firmware to your board. +2. Open a serial terminal (e.g. `minicom`, `screen`, `PuTTY`) at 115200 baud. +3. Plug a USB flash drive into the board's USB host port. +4. The device is auto-mounted and the prompt appears: + +``` +TinyUSB MSC File Explorer Example + +Device connected + Vendor : Kingston + Product : DataTraveler 2.0 + Rev : 1.0 + Capacity: 1.9 GB + +0:/> _ +``` + +### Browsing Files + +``` +0:/> ls +----a 1234 readme.txt +d---- 0 photos +d---- 0 docs + +0:/> cd photos +0:/photos> ls +----a 520432 vacation.jpg +----a 312088 family.png + +0:/> cat readme.txt +Hello from USB drive! +``` + +### Copying and Moving Files + +``` +0:/> cp readme.txt backup.txt +0:/> mv backup.txt docs/backup.txt +``` + +### Measuring Read Speed + +``` +0:/> dd +Reading 1024 sectors... + Data speed: 823 KB/s +``` + +### Multiple Devices + +When using a USB hub, multiple drives are mounted as `0:`, `1:`, etc. Use the drive prefix to +navigate between them: + +``` +0:/> cd 1: +1:/> ls +``` + +## Testing + +This example is part of the TinyUSB HIL (Hardware-in-the-Loop) test suite. The HIL test +automatically flashes, runs the example, and verifies MSC enumeration and file operations +against a known USB drive. diff --git a/examples/host/msc_file_explorer/src/ffconf.h b/examples/host/msc_file_explorer/src/ffconf.h new file mode 100644 index 000000000..5c89136fe --- /dev/null +++ b/examples/host/msc_file_explorer/src/ffconf.h @@ -0,0 +1,313 @@ +/*---------------------------------------------------------------------------/ +/ 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/src/main.c b/examples/host/msc_file_explorer/src/main.c index f6bf9a60a..07515e626 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -23,39 +23,6 @@ * */ -/* Example to show how to navigate mass storage device with built-in command line. - * Type help for list of supported commands and syntax (mostly linux commands) - - > help - * help - Print list of commands - * cat - Usage: cat [FILE]... - Concatenate FILE(s) to standard output.. - * cd - Usage: cd [DIR]... - Change the current directory to DIR. - * cp - Usage: cp SOURCE DEST - Copy SOURCE to DEST. - * ls - Usage: ls [DIR]... - List information about the FILEs (the current directory by default). - * pwd - Usage: pwd - Print the name of the current working directory. - * mkdir - Usage: mkdir DIR... - Create the DIRECTORY(ies), if they do not already exist.. - * mv - Usage: mv SOURCE DEST... - Rename SOURCE to DEST. - * rm - Usage: rm [FILE]... - Remove (unlink) the FILE(s). - */ - -#include <stdlib.h> #include <string.h> #include "bsp/board_api.h" diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c index 238af5431..3f15bb84f 100644 --- a/examples/host/msc_file_explorer/src/msc_app.c +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -46,7 +46,7 @@ #define CLI_RX_BUFFER_SIZE 16 #define CLI_CMD_BUFFER_SIZE 64 #define CLI_HISTORY_SIZE 32 -#define CLI_BINDING_COUNT 8 +#define CLI_BINDING_COUNT 9 static EmbeddedCli *_cli; static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)]; @@ -56,7 +56,11 @@ static CFG_TUH_MEM_SECTION FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity on static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX]; static CFG_TUH_MEM_SECTION FIL file1, file2; -static CFG_TUH_MEM_SECTION uint8_t rw_buf[512]; + +#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 { @@ -114,15 +118,15 @@ static bool inquiry_complete_cb(uint8_t dev_addr, const tuh_msc_complete_data_t } // Print out Vendor ID, Product ID and Rev - printf("%.8s %.16s rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, + 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 " MB\r\n", block_count / ((1024 * 1024) / block_size)); - // printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + 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; @@ -256,7 +260,7 @@ DRESULT disk_ioctl(BYTE pdrv, /* Physical drive nmuber (0..) */ return RES_OK; case GET_SECTOR_COUNT: - *((DWORD *)buff) = (WORD)tuh_msc_get_block_count(dev_addr, lun); + *((DWORD *)buff) = (DWORD)tuh_msc_get_block_count(dev_addr, lun); return RES_OK; case GET_SECTOR_SIZE: @@ -279,6 +283,7 @@ DRESULT disk_ioctl(BYTE pdrv, /* Physical drive nmuber (0..) */ void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context); void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context); void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context); +void cli_cmd_dd(EmbeddedCli *cli, char *args, void *context); void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context); void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context); void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context); @@ -316,6 +321,9 @@ bool cli_init(void) { 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).", @@ -339,6 +347,69 @@ bool cli_init(void) { 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; + + 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); + wait_for_disk_io(pdrv); + } + + 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; |
