diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d00ee78bda..c47f0f0f95 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,86 +1,50 @@ -name: Bug Report -description: Report a problem with TinyUSB -labels: 'Bug 🐞' +name: Bug report +description: Report build and runtime bugs +labels: ["Type: Bug"] body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this bug report! - It's okay to leave some blank if it doesn't apply to your problem. - - - type: dropdown + - type: checkboxes + id: checklist attributes: - label: Operating System + label: Answers checklist. + description: Before submitting a new issue, please follow the checklist and try to find the answer. options: - - Linux - - MacOS - - RaspberryPi OS - - Windows 7 - - Windows 10 - - Windows 11 - - Others - validations: - required: true - + - label: I have read the component documentation [ESP-IDF Components](https://components.espressif.com) and the issue is not addressed there. + required: true + - label: I am using target and esp-idf version as defined in component's idf_component.yml + required: true + - label: I have searched the upstream [issue tracker](https://github.com/hathach/tinyusb/issues?q=is%3Aissue) for a similar issue and not found any related issue. + required: true + - label: I have searched the Espressif esp-usb component [issue tracker](https://github.com/espressif/esp-usb/issues?q=is%3Aissue) for a similar issue and not found any related issue. + required: true - type: input + id: idf_version attributes: - label: Board - placeholder: e.g Feather nRF52840 Express - validations: - required: true - - - type: textarea - attributes: - label: Firmware - placeholder: | - e.g examples/device/cdc_msc. If it is custom firmware, it is preferably compiled like one in example folder and reviewable for people to comment on. The easiest way is - - Fork this repo, checkout a new branch - - Add your-own-example based on stock one - - Push and post it here. + label: ESP-IDF version. + description: Which ESP-IDF version does this issue occur on? Run `git describe --tags` in your esp-idf folder to find it. + placeholder: ex. v5.0-rc1 validations: required: true - - - type: textarea - attributes: - label: What happened ? - placeholder: A clear and concise description of what the bug is. - validations: - required: true - - - type: textarea + - type: input + id: devkit attributes: - label: How to reproduce ? - placeholder: | - Exact steps in chronological order, details should be specific e.g if you use a command/script to test with, please post it as well. - 1. Go to '...' - 2. Click on '....' - 3. See error + label: Development Kit. + description: Which Development Kit does this issue occur on? + placeholder: ex. ESP32-Wrover-Kit v2 | Custom Board validations: required: true - - - type: textarea + - type: input + id: component_version attributes: - label: Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2) - placeholder: | - Attach your debug log txt file here, where the issue occurred, best with comments to explain the actual events. - - Note1: Please DO NOT paste your lengthy log contents here since it hurts the readability. - Note2: To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. - More information can be found at [example's readme](https://github.com/hathach/tinyusb/blob/master/docs/getting_started.md) + label: Used Component version. + description: Which Component version does this issue occur on? Check `dependencies.lock` file in your project root to find it. + placeholder: ex. v1.2.0-rc0 validations: required: true - - type: textarea + id: more-info attributes: - label: Screenshots - description: If applicable, add screenshots to help explain your problem. + label: More Information. + description: Any other information from investigating this? + placeholder: ex. I tried on Windows 10 PC and the issue couldn't be reproduced there. validations: required: false - - - type: checkboxes - attributes: - label: I have checked existing issues, dicussion and documentation - description: You agree to check all the resources above before opening a new issue. - options: - - label: I confirm I have checked existing issues, dicussion and documentation. - required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 28fd274674..0000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: TinyUSB Discussion - url: https://github.com/hathach/tinyusb/discussions - about: If you have other questions or need help, post it here. - - name: TinyUSB Docs - url: https://docs.tinyusb.org/ - about: Online documentation diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index 19f403246e..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Feature Request -description: Suggest an idea for this project -labels: 'Feature 💡' -body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this request! - It's okay to leave some blank if it doesn't apply to your request. - - - type: input - attributes: - label: Related area - description: Please briefly explain the area of your Feature Request. - placeholder: eg. new port support, device stack, class driver ... - validations: - required: true - - - type: input - attributes: - label: Hardware specification - description: Please provide if your proposal depends on specific Hardware. - placeholder: eg. rp2040, samd51 ... - validations: - required: true - - - type: textarea - attributes: - label: Is your feature request related to a problem? - description: Please provide a clear and concise description of what the problem is. Add relevant issue link. - placeholder: ex. I'm facing the issue/missing function... - validations: - required: true - - - type: textarea - attributes: - label: Describe the solution you'd like - description: Please provide a clear and concise description of what you want to happen. - placeholder: ex. When using this function... - validations: - required: true - - - type: checkboxes - attributes: - label: I have checked existing issues, dicussion and documentation - description: You agree to check all the resources above before opening a new issue. - options: - - label: I confirm I have checked existing issues, dicussion and documentation. - required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..22c9febcb0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,17 @@ +## Requirements +_Provide a requirements for requesting changes_ + +## Limitations +_Describe limitations if there are any_ + +## Breaking change +_No breaking changes_ + +## Checklist + +- [ ] Pull Request name has appropriate format (for example: "fix(dcd_dwc2): Resolved address selection when several phy are present") +- [ ] _Optional:_ README.md updated +- [ ] CI passed + +## Related issues +_No related issues_ diff --git a/.github/ci/override_managed_component.py b/.github/ci/override_managed_component.py new file mode 100644 index 0000000000..bae246804a --- /dev/null +++ b/.github/ci/override_managed_component.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import sys +import argparse +from pathlib import Path +from glob import glob +from idf_component_tools.manifest import ManifestManager + + +def override_with_local_component(component, local_path, app): + app_path = Path(app) + + absolute_local_path = Path(local_path).absolute() + if not absolute_local_path.exists(): + print('[Error] {} path does not exist'.format(local_path)) + raise Exception + if not app_path.exists(): + print('[Error] {} path does not exist'.format(app_path)) + raise Exception + + print('[Info] Processing app {}'.format(app)) + manager = ManifestManager(app_path / 'main', 'app') + if '/' not in component: + # Prepend with default namespace + component_with_namespace = 'espressif/' + component + + try: + manager.manifest_tree['dependencies'][component_with_namespace] = { + 'version': '*', + 'override_path': str(absolute_local_path) + } + except KeyError: + print('[Error] {} app does not depend on {}'.format(app, component_with_namespace)) + raise KeyError + + manager.dump() + + +def override_with_local_component_all(component, local_path, apps): + # Process wildcard, e.g. "app_prefix_*" + apps_with_glob = list() + for app in apps: + apps_with_glob += glob(app) + + # Go through all collected apps + for app in apps_with_glob: + try: + override_with_local_component(component, local_path, app) + except: + print("[Error] Could not process app {}".format(app)) + return -1 + return 0 + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('component', help='Existing component that the app depends on') + parser.add_argument('local_path', help='Path to component that will be used instead of the managed version') + parser.add_argument('apps', nargs='*', help='List of apps to process') + args = parser.parse_args() + sys.exit(override_with_local_component_all(args.component, args.local_path, args.apps)) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index aa148eb79f..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,5 +0,0 @@ -**Describe the PR** -A clear and concise description of what this PR solve. - -**Additional context** -If applicable, add any other context about the PR and/or screenshots here. diff --git a/.github/workflows/build_idf_examples.yml b/.github/workflows/build_idf_examples.yml new file mode 100644 index 0000000000..7a0a0bab4b --- /dev/null +++ b/.github/workflows/build_idf_examples.yml @@ -0,0 +1,28 @@ +name: Build ESP-IDF USB examples + +on: + schedule: + - cron: '0 0 * * SAT' # Saturday midnight + pull_request: + types: [opened, reopened, synchronize] + +jobs: + build: + strategy: + matrix: + idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4", "latest"] + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + - name: Build ESP-IDF USB Device examples + shell: bash + run: | + . ${IDF_PATH}/export.sh + pip install idf-component-manager==1.5.2 idf-build-apps --upgrade + python .github/ci/override_managed_component.py tinyusb . ${IDF_PATH}/examples/peripherals/usb/device/tusb_* + cd ${IDF_PATH} + idf-build-apps find --path examples/peripherals/usb/device/ --recursive --target all --manifest-file examples/peripherals/.build-test-rules.yml + idf-build-apps build --path examples/peripherals/usb/device/ --recursive --target all --manifest-file examples/peripherals/.build-test-rules.yml diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml new file mode 100644 index 0000000000..2dde0268ce --- /dev/null +++ b/.github/workflows/upload_component.yml @@ -0,0 +1,25 @@ +name: Push TinyUSB to Espressif Component Service + +# If the commit is tagged, it will be uploaded. Other scenario silently fail. +on: + push: + tags: + - v* + +jobs: + upload_components: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Remove unneeded files + shell: bash + run: rm -rf docs tools lib/embedded-cli lib/fatfs lib/SEGGER_RTT + + - name: Upload components to component service + uses: espressif/upload-components-ci-action@v1 + with: + name: "tinyusb" + version: ${{ github.ref_name }} + namespace: "espressif" + api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..7efbef4851 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,66 @@ +idf_build_get_property(target IDF_TARGET) + +if(target STREQUAL "esp32s3") + set(tusb_mcu "OPT_MCU_ESP32S3") + set(tusb_family "esp32sx") +elseif(target STREQUAL "esp32s2") + set(tusb_mcu "OPT_MCU_ESP32S2") + set(tusb_family "esp32sx") +elseif(target STREQUAL "esp32p4") + set(tusb_mcu "OPT_MCU_ESP32P4") + set(tusb_family "esp32px") +endif() + +set(compile_options + "-DCFG_TUSB_MCU=${tusb_mcu}" + ) + +idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH) + +set(includes_private + "src/" + "src/device" + "lib/networking" # For RNDIS definitions + ) + +set(includes_public + "src/" + # The FreeRTOS API include convention in tinyusb is different from esp-idf + "${freertos_include}" + ) + +set(srcs + "src/class/cdc/cdc_device.c" + "src/class/hid/hid_device.c" + "src/class/midi/midi_device.c" + "src/class/msc/msc_device.c" + "src/class/vendor/vendor_device.c" + "src/class/audio/audio_device.c" + "src/class/video/video_device.c" + "src/class/bth/bth_device.c" + # NET class + "src/class/net/ecm_rndis_device.c" + "lib/networking/rndis_reports.c" + "src/class/net/ncm_device.c" + # DFU + "src/class/dfu/dfu_device.c" + "src/class/dfu/dfu_rt_device.c" + # Common, device-mode related + "src/portable/synopsys/dwc2/dcd_dwc2.c" + "src/portable/synopsys/dwc2/dwc2_common.c" + "src/common/tusb_fifo.c" + "src/device/usbd_control.c" + "src/device/usbd.c" + "src/tusb.c" + ) + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes_public} + PRIV_INCLUDE_DIRS ${includes_private} + PRIV_REQUIRES esp_netif # required by rndis_reports.c: #include "netif/ethernet.h" + ) + +target_compile_options(${COMPONENT_LIB} PUBLIC ${compile_options}) + +# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false +set_source_files_properties("src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits") diff --git a/README.md b/README.md new file mode 100644 index 0000000000..8387bb6ed6 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# Espressif TinyUSB component + +Upstream [TinyUSB](https://github.com/hathach/tinyusb) fork with integration into ESP-IDF build system. + +## How to use + +There are two options of using TinyUSB component with Espressif's SoCs: + +### 1. Use component via [Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb) + +[Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb) provides several preconfigured features to use benefits of TinyUSB stack faster. + +To use [Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb), add ``idf_component.yml`` to your main component with the following content:: + +```yaml +## IDF Component Manager Manifest File +dependencies: + esp_tinyusb: "^1.0.0" # Automatically update minor releases +``` + +Or simply run: +``` +idf.py add-dependency "esp_tinyusb^1.0.0" +``` + +Then, the Espressif TinyUSB component will be added automatically during resolving dependencies by the component manager. + +### 2. Use component directly + +Use this option for custom TinyUSB applications. +In this case you will have to provide configuration header file ``tusb_config.h``. More information about TinyUSB configuration can be found [in official TinyUSB documentation](https://docs.tinyusb.org/en/latest/reference/getting_started.html). + +You will also have to tell TinyUSB where to find the configuration file. This can be achieved by adding following CMake snippet to you main component's ``CMakeLists.txt``: + +```cmake +idf_component_get_property(tusb_lib espressif__tinyusb COMPONENT_LIB) +target_include_directories(${tusb_lib} PRIVATE path_to_your_tusb_config) +``` + +Again, you can add this component to your project by adding ``idf_component.yml`` file: + +```yaml +## IDF Component Manager Manifest File +dependencies: + tinyusb: "~0.15.1" # Automatically update bugfix releases. TinyUSB does not guarantee backward compatibility +``` + +Or simply run: +``` +idf.py add-dependency "tinyusb~0.15.1" +``` + +README from the upstream TinyUSB can be found in [hathach/tinyusb/README](https://github.com/hathach/tinyusb/blob/master/README.rst). diff --git a/idf_component.yml b/idf_component.yml new file mode 100644 index 0000000000..b038f9b71d --- /dev/null +++ b/idf_component.yml @@ -0,0 +1,11 @@ +description: TinyUSB ported to Espressif's SoCs +url: https://docs.tinyusb.org/en/latest/ +documentation: "https://docs.tinyusb.org/en/latest/" +repository: "https://github.com/espressif/tinyusb.git" +issues: "https://github.com/hathach/tinyusb/issues" +dependencies: + idf: '>=5.0' # IDF 4.x contains TinyUSB as submodule +targets: + - esp32s2 + - esp32s3 + - esp32p4 diff --git a/sbom.yml b/sbom.yml new file mode 100644 index 0000000000..91867531ab --- /dev/null +++ b/sbom.yml @@ -0,0 +1,2 @@ +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Person: Ha Thach ' diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 447560b4dd..93852ee24c 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -55,10 +55,6 @@ enum typedef struct { - // TODO optimize alignment - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -75,8 +71,25 @@ typedef struct }mscd_interface_t; CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf; + +// HINT: bypass cache +// All three buffers below should use direct access while read and write +CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static msc_cbw_t _mscd_cbw; +CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static msc_csw_t _mscd_csw; CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; +// TODO: make dependency from SOC_NON_CACHEABLE_OFFSET and change 1 to it +#if (0) +#define _mscd_p_cbw ((msc_cbw_t*)(((uintptr_t)&_mscd_cbw) + 0x40000000)) +#define _mscd_p_csw ((msc_csw_t*)(((uintptr_t)&_mscd_csw) + 0x40000000)) +#define _mscd_p_buf ((uint8_t*) (((uintptr_t)_mscd_buf) + 0x40000000)) +#else +#define _mscd_p_cbw (&_mscd_cbw) +#define _mscd_p_csw (&_mscd_csw) +#define _mscd_p_buf (_mscd_buf) +#endif // SOC_NON_CACHEABLE_OFFSET + + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -93,26 +106,28 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) { + msc_cbw_t const * p_cbw = _mscd_p_cbw; + msc_csw_t * p_csw = _mscd_p_csw; // Data residue is always = host expect - actual transferred - p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len; p_msc->stage = MSC_STAGE_STATUS_SENT; - return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); + return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &_mscd_csw, sizeof(msc_csw_t)); } static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) { p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); + return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &_mscd_cbw, sizeof(msc_cbw_t)); } static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) { - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; + msc_cbw_t const * p_cbw = _mscd_p_cbw; + msc_csw_t * p_csw = _mscd_p_csw; p_csw->status = status; - p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len; p_msc->stage = MSC_STAGE_STATUS; // failed but sense key is not set: default to Illegal Request @@ -395,8 +410,10 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t (void) event; mscd_interface_t* p_msc = &_mscd_itf; - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; + // HINT: get cache-able or noncache-able addresses + msc_cbw_t const * p_cbw = _mscd_p_cbw; + msc_csw_t * p_csw = _mscd_p_csw; + uint8_t * p_buf = _mscd_p_buf; switch (p_msc->stage) { @@ -475,12 +492,12 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t }else { // First process if it is a built-in commands - int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); + int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, p_buf, sizeof(_mscd_buf)); // Invoke user callback if not built-in if ( (resplen < 0) && (p_msc->sense_key == 0) ) { - resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); + resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, p_buf, (uint16_t) p_msc->total_len); } if ( resplen < 0 ) @@ -513,6 +530,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t { // cannot return more than host expect p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); + // HINT: + // DMA use a cache-able addr only, so use _mscd_buf here TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) p_msc->total_len) ); } } @@ -548,7 +567,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // OUT transfer, invoke callback if needed if ( !is_data_in(p_cbw->dir) ) { - int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); + int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, p_buf, (uint16_t) p_msc->total_len); if ( cb_result < 0 ) { @@ -852,7 +871,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { - msc_cbw_t const * p_cbw = &p_msc->cbw; + msc_cbw_t const * p_cbw = _mscd_p_cbw; + uint8_t * p_buf = _mscd_p_buf; // block size already verified not zero uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); @@ -865,7 +885,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) // Application can consume smaller bytes uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); + nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, p_buf, (uint32_t) nbytes); if ( nbytes < 0 ) { @@ -890,7 +910,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { - msc_cbw_t const * p_cbw = &p_msc->cbw; + msc_cbw_t const * p_cbw = _mscd_p_cbw; bool writable = true; if ( tud_msc_is_writable_cb ) @@ -917,7 +937,8 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) // process new data arrived from WRITE10 static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) { - msc_cbw_t const * p_cbw = &p_msc->cbw; + msc_cbw_t const * p_cbw = _mscd_p_cbw; + uint8_t * p_buf = _mscd_p_buf; // block size already verified not zero uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); @@ -927,7 +948,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 // Invoke callback to consume new data uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); + int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, p_buf, xferred_bytes); if ( nbytes < 0 ) { @@ -950,7 +971,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 if ( nbytes > 0 ) { p_msc->xferred_len += (uint16_t) nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, left_over); + memmove(p_buf, p_buf+nbytes, left_over); } // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index b1fd357aa3..75edac8d7a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -66,6 +66,13 @@ tu_static usbd_control_xfer_t _ctrl_xfer; CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +// TODO: make dependency from SOC_NON_CACHEABLE_OFFSET and change 1 to it +#if (0) +#define _usbd_ctrl_p_buf ((uint8_t*) (((uintptr_t)_usbd_ctrl_buf) + 0x40000000)) +#else +#define _usbd_ctrl_p_buf (_usbd_ctrl_buf) +#endif // SOC_NON_CACHEABLE_OFFSET + //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ @@ -99,10 +106,12 @@ static bool _data_stage_xact(uint8_t rhport) { if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { ep_addr = EDPT_CTRL_IN; if (xact_len) { - TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); + TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_p_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); } } - + // HINT: + // DMA doesn't have access to noncache-able memory and will use the cache-able addr + // for preparing transfer, but during transfer will use the direct memory address return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -179,8 +188,8 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) { TU_VERIFY(_ctrl_xfer.buffer); - memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2); + memcpy(_ctrl_xfer.buffer, _usbd_ctrl_p_buf, xferred_bytes); + TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_p_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += (uint16_t) xferred_bytes; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 2b3ef096f9..ac8918c17c 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -49,6 +49,14 @@ static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; +// TODO: make dependency from SOC_NON_CACHEABLE_OFFSET and change 1 to it +#if (0) +#define _setup_pkt_p ((uint8_t *)(((uintptr_t)_setup_packet) + 0x40000000)) +#else +#define _setup_pkt_p ((uint8_t *)_setup_packet) +#endif + + typedef struct { uint8_t* buffer; tu_fifo_t* ff; @@ -91,6 +99,8 @@ static void dma_setup_prepare(uint8_t rhport) { // Receive only 1 packet dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos); + // HINT: + // DMA use a cache-able addr only, so use _setup_packet here dwc2->epout[0].doepdma = (uintptr_t)_setup_packet; dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP; } @@ -180,7 +190,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { // Check if free space is available TU_ASSERT(_dfifo_top >= fifo_size + dwc2->grxfsiz); _dfifo_top -= fifo_size; - TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, _dfifo_top); + // TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, _dfifo_top); // Both TXFD and TXSA are in unit of 32-bit words. if (epnum == 0) { @@ -348,6 +358,8 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin const bool is_dma = dma_device_enabled(dwc2); if(is_dma) { + // HINT: + // DMA use a cache-able addr only, so use xfer->buffer here dep->diepdma = (uintptr_t) xfer->buffer; } @@ -394,8 +406,9 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Force device mode dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; - // Clear A override, force B Valid - dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; + // No overrides + dwc2->gotgctl &= ~(GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL); + // Enable required interrupts dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; @@ -847,7 +860,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi if (doepint_bm.setup_phase_done) { dma_setup_prepare(rhport); - dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + dcd_event_setup_received(rhport, _setup_pkt_p, true); return; }