diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 291b22079..fc41d8ff1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -33,8 +33,10 @@ body: attributes: label: Firmware placeholder: | - e.g examples/device/cdc_msc. - If it is custom firmware, please provide links to your minimal sources or as attached files. + 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. validations: required: true @@ -49,6 +51,7 @@ body: 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 diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml new file mode 100644 index 000000000..0cc7a5de1 --- /dev/null +++ b/.github/workflows/build_aarch64.yml @@ -0,0 +1,67 @@ +name: Build AArch64 + +on: + pull_request: + push: + release: + types: + - created + +jobs: + # --------------------------------------- + # Build AARCH64 family + # --------------------------------------- + build-arm: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + family: + # Alphabetical order + - 'raspberrypi4' + steps: + - name: Setup Python + uses: actions/setup-python@v2 + + - name: Checkout TinyUSB + uses: actions/checkout@v2 + + - name: Checkout common submodules in lib + run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel + + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + + - name: Set Toolchain URL + run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz + + - name: Cache Toolchain + uses: actions/cache@v2 + id: cache-toolchain + with: + path: ~/cache/ + key: ${{ runner.os }}-21-11-02-${{ env.TOOLCHAIN_URL }} + + - name: Install Toolchain + if: steps.cache-toolchain.outputs.cache-hit != 'true' + run: | + mkdir -p ~/cache/toolchain + wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.gz + tar -C ~/cache/toolchain -xaf toolchain.tar.gz + + - name: Set Toolchain Path + run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` + + - name: Build + run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build.yml b/.github/workflows/build_arm.yml similarity index 89% rename from .github/workflows/build.yml rename to .github/workflows/build_arm.yml index 8ef19b0a0..dc4d9fcfb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build_arm.yml @@ -44,6 +44,8 @@ jobs: - 'lpc18' - 'lpc54' - 'lpc55' + - 'mm32' + - 'msp432e4' - 'nrf' - 'rp2040' - 'samd11' @@ -55,6 +57,9 @@ jobs: - 'stm32f4' - 'stm32f7' - 'stm32h7' + - 'stm32l4' + - 'tm4c123' + - 'xmc4000' steps: - name: Setup Python uses: actions/setup-python@v2 @@ -65,6 +70,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Checkout pico-sdk if: matrix.family == 'rp2040' run: | @@ -94,6 +105,14 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done + # --------------------------------------- # Build all no-family (opharned) boards # --------------------------------------- diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 25f4e68f8..57dbf33e3 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -18,8 +18,8 @@ jobs: # ESP32-S2 - 'espressif_saola_1' # ESP32-S3 - # latest IDF does not define USB0 in linker #- 'espressif_addax_1' + # S3 compile error with "dangerous relocation: call8: call target out of range: memcpy" steps: - name: Setup Python @@ -31,5 +31,19 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v2 + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Build run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32sx.py ${{ matrix.board }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -maxdepth 3 -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_msp430.yml b/.github/workflows/build_msp430.yml index ff2ce72c9..98dc36cd9 100644 --- a/.github/workflows/build_msp430.yml +++ b/.github/workflows/build_msp430.yml @@ -26,6 +26,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2 @@ -48,3 +54,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index ee9ba8289..6eb042d72 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -26,6 +26,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run @@ -49,3 +55,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index 78510751c..0c7b2d154 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -27,6 +27,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz @@ -49,3 +55,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.gitmodules b/.gitmodules index e87b8750f..339dfd4ec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -121,12 +121,19 @@ [submodule "hw/mcu/nxp/nxp_sdk"] path = hw/mcu/nxp/nxp_sdk url = https://github.com/hathach/nxp_sdk.git -[submodule "hw/mcu/mindmotion/mm32sdk"] - path = hw/mcu/mindmotion/mm32sdk - url = https://github.com/zhangslice/mm32sdk.git [submodule "hw/mcu/gd/nuclei-sdk"] path = hw/mcu/gd/nuclei-sdk url = https://github.com/Nuclei-Software/nuclei-sdk.git [submodule "hw/mcu/bridgetek/ft9xx/ft90x-sdk"] path = hw/mcu/bridgetek/ft9xx/ft90x-sdk url = https://github.com/BRTSG-FOSS/ft90x-sdk +[submodule "hw/mcu/mindmotion/mm32sdk"] + path = hw/mcu/mindmotion/mm32sdk + url = https://github.com/hathach/mm32sdk.git +[submodule "hw/mcu/broadcom"] + path = hw/mcu/broadcom + url = https://github.com/adafruit/broadcom-peripherals.git + branch = main-build +[submodule "hw/mcu/infineon/mtb-xmclib-cat3"] + path = hw/mcu/infineon/mtb-xmclib-cat3 + url = https://github.com/Infineon/mtb-xmclib-cat3.git diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 040f40166..e3186f086 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -31,6 +31,12 @@ Notable contributors - Improve ESP32s2 DCD +`Jacob Berg Potter `__ +------------------------------------------------ + +- Add new class driver for network CDC-NCM + + `Jan Dümpelmann `__ ----------------------------------------------- @@ -76,7 +82,8 @@ Notable contributors ----------------------------------------------- - Add new DCD port for NXP Kinetis KL25 -- Add new DCD port for Renesas RX63n with GR-CITRUS board +- Add new DCD port for Renesas RX family (RX600, RX700 ..) with GR-CITRUS, RX65n target board +- Add new class driver for USB Video Class (UVC 1.5) `Nathan Conrad `__ @@ -93,9 +100,9 @@ Notable contributors ------------------------------------------------ - Add new DCD port for Nuvoton NUC 120, 121, 125, 126, 505 -- Add new class driver for USBNET RNDIS, CDC-ECM -- Add *net\_lwip\_webserver* example for demonstration of usbnet with - lwip +- Add new class driver for network RNDIS, CDC-ECM +- Enhance CDC-NCM network driver to compatible with RNDIS/ECM +- Add *net\_lwip\_webserver* example for demonstration of usbnet with lwip - Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 - Improve multiple cdc interfaces API & add cdc\_dual\_ports example @@ -103,7 +110,7 @@ Notable contributors `Rafael Silva `__ ---------------------------------------------- -- Add new DCD port for Silabs EFM32GG12 with SLTB009A board +- Port DCD Synopsys to support Silabs EFM32GG12 with SLTB009A board - Rewrite documentation in rst and setup for readthedocs @@ -118,10 +125,8 @@ Notable contributors ------------------------------------------------ - Add new class driver for USB Audio Class 2.0 (UAC2) -- Rework tu\_fifo with unmasked pointer, add DMA support, and constant - address support -- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint - transfer +- Rework tu\_fifo with unmasked pointer, add DMA support, and constant address support +- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint transfer - Add and greatly improve Isochronous transfer - Add new audio examples: audio\_test and audio\_4\_channel\_mic @@ -130,8 +135,7 @@ Notable contributors ------------------------------------------------ - Add new DCD port for SAMD21 and SAMD51 -- Add new class driver for Musical Instrument Digital Interface - (MIDI) +- Add new class driver for Musical Instrument Digital Interface (MIDI) - Improve USBD control transfer, MSC, CDC class driver - Board support for Metro M0 & M4 express - Write the excellent porting.md documentation @@ -173,12 +177,11 @@ Notable contributors - Add new DCD port for Synopsys DesignWare for STM32 L4, F2, F4, F7, H7 etc ... - Add new DCD port for TI MSP430 -- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard - v1.1, msp\_exp430f5529lp etc ... +- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp\_exp430f5529lp etc ... `Zixun Li `__ ------------------------------------------------ +------------------------------------------- - Add new DCD port for Microchip SAMx7x - Add IAR compiler support diff --git a/README.rst b/README.rst index 52738da32..a8ce9399c 100644 --- a/README.rst +++ b/README.rst @@ -32,23 +32,26 @@ Supported MCUs The stack supports the following MCUs: +- **Broadcom:** BCM2837, BCM2711 - **Dialog:** DA1469x - **Espressif:** ESP32-S2, ESP32-S3 +- **GigaDevice:** GD32VF103 +- **Infineon:** XMC4500 - **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x -- **NordicSemi:** nRF52833, nRF52840 +- **NordicSemi:** nRF52833, nRF52840, nRF5340 - **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 - **NXP:** - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 - - Kinetis: KL25, K32L2Bxx + - Kinetis: KL25, K32L2 - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 - **Raspberry Pi:** RP2040 -- **Renesas:** RX63N, RX65N -- **Silabs:** EFM32GG12 +- **Renesas:** RX63N, RX65N, RX72N +- **Silabs:** EFM32GG - **Sony:** CXD56 -- **ST:** STM32 series: L0, L1, F0, F1, F2, F3, F4, F7, H7 both FullSpeed and HighSpeed -- **TI:** MSP430 +- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, L0, L1, L4, L4+ +- **TI:** MSP430, MSP432E4, TM4C123 - **ValentyUSB:** eptri Here is the list of `Supported Devices`_ that can be used with provided examples. @@ -65,8 +68,9 @@ Supports multiple device configurations by dynamically changing USB descriptors, - Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... - Mass Storage Class (MSC): with multiple LUNs - Musical Instrument Digital Interface (MIDI) -- Network with RNDIS, CDC-ECM (work in progress) -- USB Test and Measurement Class (USBTMC) +- Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM) +- Test and Measurement Class (USBTMC) +- Video class 1.5 (UVC): work in progress - Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file. - `WebUSB `__ with vendor-specific class diff --git a/docs/conf.py b/docs/conf.py index c7a17478f..878b29645 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,7 +21,6 @@ extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx_autodoc_typehints', - 'sphinxemoji.sphinxemoji', ] templates_path = ['_templates'] diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst index 4325ff2ca..8eec729d6 100644 --- a/docs/info/changelog.rst +++ b/docs/info/changelog.rst @@ -2,6 +2,37 @@ Changelog ********* +0.12.0 +====== + +- add CFG_TUSB_OS_INC_PATH for os include path + +Device Controller Driver (DCD) +------------------------------ + +- Getting device stack to pass USB Compliance Verification test (chapter9, HID, MSC). Ports are tested: + nRF, SAMD 21/51, rp2040, stm32f4, Renesas RX, iMXRT, ESP32-S2/3, Kinetic KL25/32, DA146xx +- Added dcd_edpt_close_all() for switching configuration +- [Transdimension] Support dcd_edpt_xfer_fifo() with auto wrap over if fifo buffer is 4K aligned and size is multiple of 4K. +- [DA146xx] Improve vbus, reset, suspend, resume detection, and remote wakeup. + +Device Stack +------------ + +- Add new network driver Network Control Model (CDC-NCM), update net_lwip_webserver to work with NCM (need re-configure example) +- Add new USB Video Class UVC 1.5 driver and video_capture example ((work in progress) +- Fix potential buffer overflow for HID, bluetooth drivers + +Host Controller Driver (HCD) +---------------------------- + +No notable changes + +Host Stack +---------- + +No notable changes + 0.11.0 (2021-08-29) =================== @@ -26,7 +57,7 @@ Synopsys ^^^^^^^^ - Fix Synopsys set address bug which could cause re-enumeration failed -- Fix for dcd_synopsys driver integer overflow in HS mode (issue #968) +- Fix dcd_synopsys driver integer overflow in HS mode (issue #968) nRF5x ^^^^^ diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index 5f3227927..875372c81 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -89,6 +89,15 @@ A MCU can support multiple operational speed. By default, the example build syst $ make BOARD=stm32f746disco SPEED=full all +Size Analysis +~~~~~~~~~~~~~ + +First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since -flto merges code across .o files and make it difficult to analyze. + +.. code-block:: + + $ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap + Debug ^^^^^ @@ -113,7 +122,7 @@ Logger By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols: -* `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) +* `LOGGER=rtt`: use `Segger RTT protocol `_ * Cons: requires jlink as the debugger. * Pros: work with most if not all MCUs @@ -151,3 +160,39 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can .. code-block:: $ make BOARD=feather_nrf52840_express all uf2 + +IAR Support +^^^^^^^^^^^ + +IAR Project Connection files are provided to import TinyUSB stack into your project. + +* A buldable project of your MCU need to be created in advance. + + + * Take example of STM32F0: + + - You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`. + + - `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs. + +* Open `Tools -> Configure Custom Argument Variables` (Switch to `Global` tab if you want to do it for all your projects) + Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack, + for example `C:\\tinyusb` + +Import stack only +~~~~~~~~~~~~~~~~~ + +1. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`. + +Run examples +~~~~~~~~~~~~ + +1. (Python3 is needed) Run `iar_gen.py` to generate .ipcf files of examples: + + .. code-block:: + + cd C:\tinyusb\tools + python iar_gen.py + +2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`. + For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf` diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index 4c7d753c2..e3cb8c679 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -2,126 +2,114 @@ Supported Devices ***************** - Supported MCUs ============== -.. admonition:: Warning - :class: warning ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | ++==============+=======================+========+======+===========+===================+==============+ +| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Espressif | ESP32 S2, S3 | ✔ | | ✖ | dwc2 or esp32sx | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Infineon | XMC4500 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| MicroChip | SAM D11, D21 | ✔ | | ✖ | samd | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | SAM D51, E5x | ✔ | | ✖ | samd | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | SAM G55 | ✔ | | ✖ | samg | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | SAM L21, L22 | ✔ | | ✖ | samd | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | SAM E70,S70,V70,V71 | ✔ | | ✔ | samx7x | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| NordicSemi | nRF52833, nRF52840 | ✔ | ✖ | ✖ | nrf5x | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | nRF5340 | ✔ | ✖ | ✖ | nrf5x | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Nuvoton | NUC120 | ✔ | ✖ | ✖ | | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | NUC121/NUC125 | ✔ | ✖ | ✖ | | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | NUC126 | ✔ | ✖ | ✖ | | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | NUC505 | ✔ | | ✔ | | | ++--------------+---------+-------------+--------+------+-----------+-------------------+--------------+ +| NXP | iMXRT | RT10xx | ✔ | ✔ | ✔ | ci_hs | | +| +---------+-------------+--------+------+-----------+-------------------+--------------+ +| | Kinetis | KL25 | ✔ | | ✖ | | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | K32L2 | ✔ | | ✖ | | | +| +---------+-------------+--------+------+-----------+-------------------+--------------+ +| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40 | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | 54 | ✔ | | ✔ | lpc_ip3511 | | +| | +-------------+--------+------+-----------+-------------------+--------------+ +| | | 55 | ✔ | | ✔ | lpc_ip3511 | | ++--------------+---------+-------------+--------+------+-----------+-------------------+--------------+ +| Raspberry Pi | RP2040 | ✔ | ✔ | ✖ | rp2040 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Renesas | RX 63N, 65N, 72N | ✔ | ✖ | ✖ | usba | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| ST STM32 | F0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------+--------+------+-----------+-------------------+--------------+ +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | +------------------+--------+------+-----------+-------------------+--------------+ +| | | 105, 107 | ✔ | | ✖ | dwc2 | | +| +----+------------------+--------+------+-----------+-------------------+--------------+ +| | F2 | ✔ | | ✔ | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | F3 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | F4 | ✔ | | ✔ | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | F7 | ✔ | | ✔ | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | H7 | ✔ | | ✔ | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | L0, L1 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------+--------+------+-----------+-------------------+--------------+ +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | +------------------+--------+------+-----------+-------------------+--------------+ +| | | 4x5, 4x6 | ✔ | | | dwc2 | | +| +----+------------------+--------+------+-----------+-------------------+--------------+ +| | L4+ | ✔ | | | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | U5 | ⚠ | | | dwc2 | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | MSP432E4 | ✔ | | ✖ | musb | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | TM4C123 | ✔ | | ✖ | musb | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ +| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | ++--------------+-----------------------+--------+------+-----------+-------------------+--------------+ - This table is a WIP! the data is not correct, tho if a device is listed, it likely works as a usb full speed device at the least. - -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Manufacturer | Family | Device | Host | FS | HS | Known Issues | -+==============+====================+===================+====================+===================+===================+==============+ -| Dialog | DA1469x | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Espressif | ESP32-S2 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | ESP32-S3 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| MicroChip | SAMD11 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAMD21 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAMD51 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAME5x | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAMG55 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAML21 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAML22 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | SAME70,S70,V70,V71 | |:green_square:| | |:red_square:| | |:green_square:| | |:green_square:| | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| NordicSemi | nRF52833 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | nRF52840 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Nuvoton | NUC120 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | NUC121/NUC125 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | NUC126 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | NUC505 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| NXP | iMX | RT1011 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | RT1015 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | RT1021 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | RT1052 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | RT1062 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | RT1064 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | Kinetis KL25 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | LPC | 11u | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 13 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 15 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 17 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 18 | | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 40 | | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 43 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 51u | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 54 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | 55 | |:green_square:| | |:x:| | |:green_square:| | | | -+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Raspberry Pi | RP2040 | |:green_square:| | |:x:| | |:green_square:| | | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Renesas | RX63N | | | | | | -| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | RX65N | | | | | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Silabs | EFM32GG12 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | #750 | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| Sony | CXD56 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | | -+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| ST | STM32 | L0 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F0 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F1 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F2 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F3 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F4 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | F7 | |:green_square:| | | |:green_square:| | | | -| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| | | H7 | |:green_square:| | | |:green_square:| | |:green_square:| | | -+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| TI | MSP430 | |:green_square:| | | |:green_square:| | | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ -| ValentyUSB | eptri | |:green_square:| | | |:green_square:| | | | -+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+ Table Legend ------------ -================= =================== -|:x:| Not available -|:red_square:| Not supported -|:yellow_square:| WIP/partial support -|:green_square:| Supported -================= =================== += =================== +✔ Supported +⚠ WIP/partial support +✖ Not supported += =================== Supported Boards ================ @@ -134,6 +122,11 @@ The board support code is only used for self-contained examples and testing. It The following boards are supported (sorted alphabetically): +Broadcom +-------- + +- `Raspberry Pi CM4 `__ + Dialog DA146xx -------------- @@ -143,12 +136,25 @@ Dialog DA146xx Espressif ESP32-S2 ------------------ -- Adafruit Feather ESP32-S2 +- `Adafruit Feather ESP32-S2 `__ - `Adafruit Magtag 2.9" E-Ink WiFi Display `__ - `Adafruit Metro ESP32-S2 `__ - `ESP32-S2-Kaluga-1 `__ - `ESP32-S2-Saola-1 `__ +GigaDevice +---------- + +- `Sipeed Longan Nano `__ + +Infineon +--------- + +XMC4000 +^^^^^^^ + +- `XMC4500 Relax (Lite) Kit `__ + MicroChip --------- @@ -175,6 +181,12 @@ SAMD51 & SAME54 - `D5035-01 `__ - `Microchip SAME54 Xplained Pro `__ +SAME7x +^^^^^^ + +- `Microchip SAME70 Xplained `_ +- `QMTECH ATSAME70N19 `_ + SAMG ^^^^ @@ -229,7 +241,8 @@ iMX RT Kinetis ^^^^^^^ -- `FRDM-KL25Z `__ +- `Freedom FRDM-KL25Z `__ +- `Freedom FRDM-K32L2B3 `__ LPC 11-13-15 ^^^^^^^^^^^^ @@ -299,28 +312,58 @@ Sony ST STM32 -------- -- `Adafruit Feather STM32F405 `__ -- `Micro Python PyBoard v1.1 `__ -- `STLink-V3 Mini `__ -- `STM32 L035c8 Discovery `__ -- `STM32 L4R5zi Nucleo `__ +F0 +^^ - `STM32 F070rb Nucleo `__ - `STM32 F072 Evaluation `__ - `STM32 F072rb Discovery `__ + +F1 +^^ - `STM32 F103c8 Blue Pill `__ - `STM32 F103rc Mini v2.0 `__ + +F2 +^^ - `STM32 F207zg Nucleo `__ + +F3 +^^ - `STM32 F303vc Discovery `__ + +F4 +^^ +- `Adafruit Feather STM32F405 `__ +- `Micro Python PyBoard v1.1 `__ - `STM32 F401cc Black Pill `__ - `STM32 F407vg Discovery `__ - `STM32 F411ce Black Pill `__ - `STM32 F411ve Discovery `__ - `STM32 F412zg Discovery `__ +- `STM32 F412zg Nucleo `__ + +F7 +^^ + +- `STLink-V3 Mini `__ - `STM32 F723e Discovery `__ - `STM32 F746zg Nucleo `__ - `STM32 F746g Discovery `__ - `STM32 F767zi Nucleo `__ - `STM32 F769i Discovery `__ + +L0 +^^ +- `STM32 L035c8 Discovery `__ + +L4 +^^ +- `STM32 L476vg Discovery `__ +- `STM32 L4P5zg Nucleo `__ +- `STM32 L4R5zi Nucleo `__ + +H7 +^^ - `STM32 H743zi Nucleo `__ - `STM32 H743i Evaluation `__ - `STM32 H745i Discovery `__ @@ -330,6 +373,8 @@ TI -- - `MSP430F5529 USB LaunchPad Evaluation Kit `__ +- `MSP-EXP432E401Y LaunchPad Evaluation Kit `__ +- `TM4C123GXL LaunchPad Evaluation Kit `__ Tomu ---- diff --git a/docs/requirements.txt b/docs/requirements.txt index e415ae03e..8ae9ae73b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,3 @@ sphinx~=3.0 furo>=2020.12.30.b24 -sphinxemoji>=0.1.8 sphinx-autodoc-typehints>=1.10 diff --git a/examples/device/99-tinyusb.rules b/examples/device/99-tinyusb.rules index e6372ed58..d306bada5 100644 --- a/examples/device/99-tinyusb.rules +++ b/examples/device/99-tinyusb.rules @@ -12,3 +12,10 @@ ATTRS{idVendor}=="cafe", MODE="0666", GROUP="dialout" # Rule to blacklist TinyUSB example from being manipulated by ModemManager. SUBSYSTEMS=="usb", ATTRS{idVendor}=="cafe", ENV{ID_MM_DEVICE_IGNORE}="1" + +# Xplained Pro SamG55 Device +SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2111", MODE="0666", GROUP="users", ENV{ID_MM_DEVICE_IGNORE}="1" +SUBSYSTEMS=="tty", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2111", MODE="0666", GROUP="users", ENV{ID_MM_DEVICE_IGNORE}="1" + +# TI Stellaris/Tiva-C Launchpad ICDI +SUBSYSTEM=="usb", ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0666" diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index a0e4600f6..edf5ab805 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -24,4 +24,5 @@ family_add_subdirectory(msc_dual_lun) family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(usbtmc) +family_add_subdirectory(video_capture) family_add_subdirectory(webusb_serial) diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 983b87e5b..d085dd43a 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -141,7 +141,7 @@ void tud_resume_cb(void) void audio_task(void) { // Yet to be filled - e.g. put meas data into TX FIFOs etc. - asm("nop"); + // asm("nop"); } //--------------------------------------------------------------------+ diff --git a/examples/device/audio_4_channel_mic/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c index 93ec6e9f7..93ae2ea47 100644 --- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c @@ -81,21 +81,26 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_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 +#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 + #else -#define EPNUM_AUDIO 0x01 + #define EPNUM_AUDIO 0x01 #endif uint8_t const desc_configuration[] = { - // 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 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_AUDIO_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) + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_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 diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 9a2fdd3a1..ed13ce993 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -142,7 +142,7 @@ void tud_resume_cb(void) void audio_task(void) { // Yet to be filled - e.g. put meas data into TX FIFOs etc. - asm("nop"); + // asm("nop"); } //--------------------------------------------------------------------+ diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 67dd34d2a..09b2a2d45 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -82,17 +82,22 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_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 + // 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 + #else -#define EPNUM_AUDIO 0x01 + #define EPNUM_AUDIO 0x01 #endif uint8_t const desc_configuration[] = { // 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), + 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_AUDIO_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) diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index c77dd5647..5e28cbb27 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -47,6 +47,7 @@ enum { int main(void) { board_init(); + board_led_write(true); uint32_t start_ms = 0; bool led_state = false; diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index b935b672f..aa400d486 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -35,6 +35,9 @@ #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 //--------------------------------------------------------------------+ @@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .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) @@ -51,7 +54,7 @@ tusb_desc_device_t const desc_device = .bDeviceProtocol = MISC_PROTOCOL_IAD, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, + .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, @@ -118,7 +121,7 @@ enum 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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), @@ -128,10 +131,12 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), @@ -139,7 +144,44 @@ uint8_t const desc_hs_configuration[] = // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), }; -#endif + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .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 + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; +} + +#endif // highspeed // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 503baace9..134bda392 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -188,10 +188,24 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); - return bufsize; + return (int32_t) bufsize; +} + +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. @@ -200,6 +214,9 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); @@ -207,7 +224,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* (void) lba; (void) offset; (void) buffer; #endif - return bufsize; + return (int32_t) bufsize; } // Callback invoked when received an SCSI command not in built-in list below @@ -218,7 +235,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // read10 & write10 has their own callback and MUST not be handled here void const* response = NULL; - uint16_t resplen = 0; + int32_t resplen = 0; // most scsi handled is input bool in_xfer = true; @@ -246,14 +263,14 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, { if(in_xfer) { - memcpy(buffer, response, resplen); + memcpy(buffer, response, (size_t) resplen); }else { // SCSI output } } - return resplen; + return (int32_t) resplen; } #endif diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 2bf5248bf..e74e80541 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -47,9 +47,9 @@ // RHPort max operational speed can defined by board.mk // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X || \ - CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X ) + #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\ + TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\ + TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 565a5d60c..3c3e9c891 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -35,32 +35,35 @@ #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 //--------------------------------------------------------------------+ tusb_desc_device_t const desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .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, + // 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, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR @@ -82,8 +85,6 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_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, 5 Bulk etc ... @@ -136,10 +137,13 @@ enum #endif +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) + +// full speed configuration uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), @@ -149,10 +153,13 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// high speed configuration uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), @@ -160,7 +167,54 @@ uint8_t const desc_hs_configuration[] = // 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), }; -#endif + +// other speed configuration +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 +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 OHER_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 @@ -188,7 +242,7 @@ char const* string_desc_arr [] = (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID + "123456789012", // 3: Serials, should use chip ID "TinyUSB CDC", // 4: CDC Interface "TinyUSB MSC", // 5: MSC Interface }; @@ -217,7 +271,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) const char* str = string_desc_arr[index]; // Cap at max char - chr_count = strlen(str); + chr_count = (uint8_t) strlen(str); if ( chr_count > 31 ) chr_count = 31; // Convert ASCII string into UTF-16 diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_EFM32GG12 b/examples/device/cdc_msc_freertos/.skip.MCU_BCM2711 similarity index 100% rename from examples/device/cdc_msc_freertos/.skip.MCU_EFM32GG12 rename to examples/device/cdc_msc_freertos/.skip.MCU_BCM2711 diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 86bacd2d4..a155d6cb7 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -7,12 +7,18 @@ FREERTOS_SRC = lib/FreeRTOS-Kernel INC += \ src \ + src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/msc_disk.c \ + src/usb_descriptors.c + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # FreeRTOS source, all files in port folder @@ -23,6 +29,9 @@ SRC_C += \ $(FREERTOS_SRC)/timers.c \ $(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c)) +# Suppress FreeRTOS warnings +CFLAGS += -Wno-error=cast-qual + # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext diff --git a/examples/device/cdc_msc_freertos/src/CMakeLists.txt b/examples/device/cdc_msc_freertos/src/CMakeLists.txt index 6b188fd30..93ae0686a 100644 --- a/examples/device/cdc_msc_freertos/src/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/src/CMakeLists.txt @@ -8,9 +8,7 @@ if(EXISTS ${board_cmake}) include(${board_cmake}) endif() -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" "${TOP}/hw" "${TOP}/src" ) @@ -25,8 +23,9 @@ target_sources(${COMPONENT_TARGET} PUBLIC "${TOP}/src/class/hid/hid_device.c" "${TOP}/src/class/midi/midi_device.c" "${TOP}/src/class/msc/msc_device.c" - "${TOP}/src/class/net/net_device.c" + "${TOP}/src/class/net/ecm_rndis_device.c" + "${TOP}/src/class/net/ncm_device.c" "${TOP}/src/class/usbtmc/usbtmc_device.c" "${TOP}/src/class/vendor/vendor_device.c" - "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" + "${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c" ) diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h similarity index 96% rename from examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h rename to examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index 568b27a18..ccb620720 100644 --- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h +++ b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -45,7 +45,16 @@ // Include MCU header #include "bsp/board_mcu.h" -extern uint32_t SystemCoreClock; +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" +#endif + +// TODO fix later +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + extern uint32_t SystemCoreClock; +#endif /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index c27b7feda..0a1c964ae 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -27,15 +27,30 @@ #include #include -#include "FreeRTOS.h" -#include "task.h" -#include "timers.h" -#include "queue.h" -#include "semphr.h" - #include "bsp/board.h" #include "tusb.h" +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // 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 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -55,14 +70,7 @@ enum { StaticTimer_t blinky_tmdef; TimerHandle_t blinky_tm; -// static task for usbd -// Increase stack size when debug log is enabled -#if CFG_TUSB_DEBUG - #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE) -#else - #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) -#endif - +// static task StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; @@ -95,14 +103,14 @@ int main(void) (void) xTaskCreateStatic( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_ESP32S3 +#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) vTaskStartScheduler(); #endif return 0; } -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) void app_main(void) { main(); diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 5aa7befc9..b9205f0c2 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -178,6 +178,9 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); @@ -190,6 +193,9 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); @@ -208,7 +214,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // read10 & write10 has their own callback and MUST not be handled here void const* response = NULL; - uint16_t resplen = 0; + int32_t resplen = 0; // most scsi handled is input bool in_xfer = true; diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index ff5438349..55e84c62d 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -67,6 +67,11 @@ // This examples use FreeRTOS #define CFG_TUSB_OS OPT_OS_FREERTOS +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #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 diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 75b5ce7bb..9585822a3 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -35,6 +35,9 @@ #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 //--------------------------------------------------------------------+ @@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .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) @@ -52,7 +55,7 @@ tusb_desc_device_t const desc_device = .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, + .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, @@ -82,8 +85,6 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_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, 5 Bulk etc ... @@ -114,10 +115,12 @@ enum #endif +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) + 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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), @@ -127,10 +130,13 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// high speed configuration uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), @@ -138,7 +144,54 @@ uint8_t const desc_hs_configuration[] = // 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), }; -#endif + +// other speed configuration +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 +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 OHER_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 @@ -165,7 +218,7 @@ char const* string_desc_arr [] = (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID + "123456789012", // 3: Serials, should use chip ID "TinyUSB CDC", // 4: CDC Interface "TinyUSB MSC", // 5: MSC Interface }; diff --git a/examples/device/dfu/.skip.MCU_TM4C123 b/examples/device/dfu/.skip.MCU_TM4C123 new file mode 100644 index 000000000..6260e6e25 --- /dev/null +++ b/examples/device/dfu/.skip.MCU_TM4C123 @@ -0,0 +1,4 @@ +LINK _build/ek-tm4c123gxl/dfu.elf +/home/runner/cache/toolchain/xpack-arm-none-eabi-gcc-10.2.1-1.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: section .ARM.exidx.text._close LMA [0000000000002980,0000000000002987] overlaps section .data LMA [0000000000002980,0000000000002a03] +collect2: error: ld returned 1 exit status +make: *** [../../rules.mk:94: _build/ek-tm4c123gxl/dfu.elf] Error 1 \ No newline at end of file diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 66e357021..012d50019 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -80,7 +80,7 @@ #define CFG_TUD_DFU 1 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR -#define CFG_TUD_DFU_XFER_BUFSIZE 512 +#define CFG_TUD_DFU_XFER_BUFSIZE ( OPT_MODE_HIGH_SPEED ? 512 : 64 ) #ifdef __cplusplus } diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 1cfe29c53..350334aa5 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -97,7 +97,7 @@ enum 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), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), diff --git a/examples/device/dfu_runtime/src/usb_descriptors.c b/examples/device/dfu_runtime/src/usb_descriptors.c index 8b2bd265d..060943289 100644 --- a/examples/device/dfu_runtime/src/usb_descriptors.c +++ b/examples/device/dfu_runtime/src/usb_descriptors.c @@ -92,7 +92,7 @@ enum 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), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, attributes, detach timeout, transfer size */ TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), diff --git a/examples/device/dynamic_configuration/src/msc_disk.c b/examples/device/dynamic_configuration/src/msc_disk.c index 5aa7befc9..b9205f0c2 100644 --- a/examples/device/dynamic_configuration/src/msc_disk.c +++ b/examples/device/dynamic_configuration/src/msc_disk.c @@ -178,6 +178,9 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); @@ -190,6 +193,9 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* { (void) lun; + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); @@ -208,7 +214,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // read10 & write10 has their own callback and MUST not be handled here void const* response = NULL; - uint16_t resplen = 0; + int32_t resplen = 0; // most scsi handled is input bool in_xfer = true; diff --git a/examples/device/dynamic_configuration/src/usb_descriptors.c b/examples/device/dynamic_configuration/src/usb_descriptors.c index 9ccb37654..3352972a5 100644 --- a/examples/device/dynamic_configuration/src/usb_descriptors.c +++ b/examples/device/dynamic_configuration/src/usb_descriptors.c @@ -160,7 +160,7 @@ enum uint8_t const desc_configuration_0[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_0_NUM_TOTAL, 0, CONFIG_0_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_0_NUM_TOTAL, 0, CONFIG_0_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_0_NUM_CDC, 0, EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC_OUT, EPNUM_0_CDC_IN, 64), @@ -173,7 +173,7 @@ uint8_t const desc_configuration_0[] = uint8_t const desc_configuraiton_1[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_1_NUM_MSC, 0, EPNUM_1_MSC_OUT, EPNUM_1_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), diff --git a/examples/device/hid_boot_interface/Makefile b/examples/device/hid_boot_interface/Makefile index 138c27846..c6a9c5b21 100644 --- a/examples/device/hid_boot_interface/Makefile +++ b/examples/device/hid_boot_interface/Makefile @@ -6,7 +6,7 @@ INC += \ $(TOP)/hw \ # Example source -EXAMPLE_SOURCE += \ +EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 868424e6d..8fa5e5cd4 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -47,8 +47,8 @@ // RHPort max operational speed can defined by board.mk // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) + #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\ + TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index b9a6e7292..e760b20ba 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -36,6 +36,9 @@ #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 //--------------------------------------------------------------------+ @@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .bcdUSB = USB_BCD, .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, + .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, @@ -111,12 +114,62 @@ uint8_t const desc_configuration[] = 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 +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 +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 = OHER_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 + + // This example use the same configuration for both high and full speed mode return desc_configuration; } diff --git a/examples/device/hid_composite_freertos/.skip.MCU_EFM32GG12 b/examples/device/hid_composite_freertos/.skip.MCU_BCM2711 similarity index 100% rename from examples/device/hid_composite_freertos/.skip.MCU_EFM32GG12 rename to examples/device/hid_composite_freertos/.skip.MCU_BCM2711 diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile index 1c1959590..c9b7abdf5 100644 --- a/examples/device/hid_composite_freertos/Makefile +++ b/examples/device/hid_composite_freertos/Makefile @@ -7,12 +7,17 @@ FREERTOS_SRC = lib/FreeRTOS-Kernel INC += \ src \ + src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/usb_descriptors.c + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # FreeRTOS source, all files in port folder @@ -23,6 +28,9 @@ SRC_C += \ $(FREERTOS_SRC)/timers.c \ $(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c)) +# Suppress FreeRTOS warnings +CFLAGS += -Wno-error=cast-qual + # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext diff --git a/examples/device/hid_composite_freertos/src/CMakeLists.txt b/examples/device/hid_composite_freertos/src/CMakeLists.txt index 6d4a3c1e2..6f156379f 100644 --- a/examples/device/hid_composite_freertos/src/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/src/CMakeLists.txt @@ -8,9 +8,7 @@ if(EXISTS ${board_cmake}) include(${board_cmake}) endif() -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" "${TOP}/hw" "${TOP}/src" ) @@ -25,7 +23,8 @@ target_sources(${COMPONENT_TARGET} PUBLIC "${TOP}/src/class/hid/hid_device.c" "${TOP}/src/class/midi/midi_device.c" "${TOP}/src/class/msc/msc_device.c" - "${TOP}/src/class/net/net_device.c" + "${TOP}/src/class/net/ecm_rndis_device.c" + "${TOP}/src/class/net/ncm_device.c" "${TOP}/src/class/usbtmc/usbtmc_device.c" "${TOP}/src/class/vendor/vendor_device.c" "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" diff --git a/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h similarity index 96% rename from examples/device/hid_composite_freertos/src/FreeRTOSConfig.h rename to examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index 568b27a18..bfdf1e926 100644 --- a/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h +++ b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -45,7 +45,16 @@ // Include MCU header #include "bsp/board_mcu.h" -extern uint32_t SystemCoreClock; +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 +#error "ESP32-Sx should use IDF's FreeRTOSConfig.h" +#endif + +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + // TODO fix/remove later + extern u32 SystemCoreClock; +#else + extern uint32_t SystemCoreClock; +#endif /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 9c9830e34..1695f968c 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -27,17 +27,32 @@ #include #include -#include "FreeRTOS.h" -#include "task.h" -#include "timers.h" -#include "queue.h" -#include "semphr.h" - #include "bsp/board.h" #include "tusb.h" - #include "usb_descriptors.h" +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // 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 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -57,13 +72,7 @@ enum { StaticTimer_t blinky_tmdef; TimerHandle_t blinky_tm; -// static task for usbd -#if CFG_TUSB_DEBUG - #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE) -#else - #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) -#endif - +// static task StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; @@ -96,14 +105,14 @@ int main(void) (void) xTaskCreateStatic( hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, hid_stack, &hid_taskdef); // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_ESP32S3 +#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) vTaskStartScheduler(); #endif return 0; } -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) void app_main(void) { main(); diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 4b0458ef0..062f32ac3 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -67,8 +67,15 @@ // This examples use FreeRTOS #define CFG_TUSB_OS OPT_OS_FREERTOS -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #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 diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index b9a6e7292..791813fdf 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -36,6 +36,9 @@ #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 //--------------------------------------------------------------------+ @@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .bcdUSB = USB_BCD, .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, + .idVendor = USB_VID, .idProduct = USB_PID, .bcdDevice = 0x0100, @@ -111,6 +114,54 @@ uint8_t const desc_configuration[] = 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 +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 +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 = OHER_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 diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 5a2f5ffdc..5dabf42a3 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -101,7 +101,7 @@ enum 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), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 9d92a7753..bd5a0eeab 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -91,7 +91,7 @@ enum 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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 0x80 | EPNUM_MIDI, 64) @@ -101,7 +101,7 @@ uint8_t const desc_fs_configuration[] = uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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, 0x80 | EPNUM_MIDI, 512) diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 2ab050da8..18d3ca0d7 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -268,16 +268,33 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // 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) { + // out of ramdisk + if ( lba >= DISK_BLOCK_NUM ) return -1; + uint8_t const* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; memcpy(buffer, addr, bufsize); return bufsize; } +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 -1; + #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; memcpy(addr, buffer, bufsize); @@ -296,7 +313,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // read10 & write10 has their own callback and MUST not be handled here void const* response = NULL; - uint16_t resplen = 0; + int32_t resplen = 0; // most scsi handled is input bool in_xfer = true; diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 138de62a3..2afd391af 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -99,7 +99,7 @@ enum 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, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), @@ -109,7 +109,7 @@ uint8_t const desc_fs_configuration[] = uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + 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_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), @@ -141,7 +141,7 @@ char const* string_desc_arr [] = (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID + "123456789012", // 3: Serials, should use chip ID }; static uint16_t _desc_str[32]; diff --git a/examples/device/net_lwip_webserver/.skip.MCU_BCM2711 b/examples/device/net_lwip_webserver/.skip.MCU_BCM2711 new file mode 100644 index 000000000..bdc68f5db --- /dev/null +++ b/examples/device/net_lwip_webserver/.skip.MCU_BCM2711 @@ -0,0 +1 @@ +tinyusb/lib/lwip/src/include/lwip/arch.h:202:13: error: conflicting types for 'ssize_t' \ No newline at end of file diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index c3e0d8899..881866a56 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -3,10 +3,11 @@ DEPS_SUBMODULES += lib/lwip include ../../../tools/top.mk include ../../make.mk +# suppress warning caused by lwip CFLAGS += \ - -DPBUF_POOL_SIZE=2 \ - -DTCP_WND=2*TCP_MSS \ - -DHTTPD_USE_CUSTOM_FSDATA=0 + -Wno-error=null-dereference \ + -Wno-error=unused-parameter \ + -Wno-error=unused-variable INC += \ src \ @@ -50,6 +51,15 @@ SRC_C += \ lib/lwip/src/core/ipv4/ip4.c \ lib/lwip/src/core/ipv4/ip4_addr.c \ lib/lwip/src/core/ipv4/ip4_frag.c \ + lib/lwip/src/core/ipv6/dhcp6.c \ + lib/lwip/src/core/ipv6/ethip6.c \ + lib/lwip/src/core/ipv6/icmp6.c \ + lib/lwip/src/core/ipv6/inet6.c \ + lib/lwip/src/core/ipv6/ip6.c \ + lib/lwip/src/core/ipv6/ip6_addr.c \ + lib/lwip/src/core/ipv6/ip6_frag.c \ + lib/lwip/src/core/ipv6/mld6.c \ + lib/lwip/src/core/ipv6/nd6.c \ lib/lwip/src/netif/ethernet.c \ lib/lwip/src/netif/slipif.c \ lib/lwip/src/apps/http/httpd.c \ diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 5a8096f50..a215017c7 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -42,11 +42,14 @@ #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 +#define LWIP_IPV4 1 +#define LWIP_IPV6 0 #define ETH_PAD_SIZE 0 #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) #define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_WND (TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 @@ -56,4 +59,13 @@ #define LWIP_SINGLE_NETIF 1 +#define PBUF_POOL_SIZE 2 + +#define HTTPD_USE_CUSTOM_FSDATA 0 + +#define LWIP_MULTICAST_PING 1 +#define LWIP_BROADCAST_PING 1 +#define LWIP_IPV6_MLD 0 +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 + #endif /* __LWIPOPTS_H__ */ diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 80831921a..30bb3577b 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -50,8 +50,11 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 #include "dnserver.h" #include "lwip/init.h" #include "lwip/timeouts.h" +#include "lwip/ethip6.h" #include "httpd.h" +#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } + /* lwip context */ static struct netif netif_data; @@ -64,24 +67,24 @@ static struct pbuf *received_frame; const uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; /* network parameters of this MCU */ -static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); -static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); -static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); +static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); +static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); /* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ static dhcp_entry_t entries[] = { /* mac ip address lease time */ - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 4), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 }, }; static const dhcp_config_t dhcp_config = { - .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ + .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ .port = 67, /* listen port */ - .dns = IPADDR4_INIT_BYTES(192, 168, 7, 1), /* dns server (if any) */ + .dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */ "usb", /* dns suffix */ TU_ARRAY_SIZE(entries), /* num entry */ entries /* entries */ @@ -97,7 +100,7 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (tud_network_can_xmit()) + if (tud_network_can_xmit(p->tot_len)) { tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; @@ -108,11 +111,18 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) } } -static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { return etharp_output(netif, p, addr); } +#if LWIP_IPV6 +static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) +{ + return ethip6_output(netif, p, addr); +} +#endif + static err_t netif_init_cb(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); @@ -122,7 +132,10 @@ static err_t netif_init_cb(struct netif *netif) netif->name[0] = 'E'; netif->name[1] = 'X'; netif->linkoutput = linkoutput_fn; - netif->output = output_fn; + netif->output = ip4_output_fn; +#if LWIP_IPV6 + netif->output_ip6 = ip6_output_fn; +#endif return ERR_OK; } @@ -138,11 +151,14 @@ static void init_lwip(void) netif->hwaddr[5] ^= 0x01; netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(netif, 1); +#endif netif_set_default(netif); } /* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip_addr_t *addr) +bool dns_query_proc(const char *name, ip4_addr_t *addr) { if (0 == strcmp(name, "tiny.usb")) { @@ -218,7 +234,7 @@ int main(void) init_lwip(); while (!netif_is_up(&netif_data)); while (dhserv_init(&dhcp_config) != ERR_OK); - while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK); httpd_init(); while (1) diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 262d4ebce..114961cb7 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -95,12 +95,11 @@ #endif //------------- CLASS -------------// -#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 -#define CFG_TUD_NET 1 + +// Network class has 2 drivers: ECM/RNDIS and NCM. +// Only one of the drivers can be enabled +#define CFG_TUD_ECM_RNDIS 1 +#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) #ifdef __cplusplus } diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 71e6c4582..2b4b2a0c3 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -33,7 +33,7 @@ */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5) ) + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) ) // String Descriptor Index enum @@ -55,8 +55,12 @@ enum enum { +#if CFG_TUD_ECM_RNDIS CONFIG_ID_RNDIS = 0, CONFIG_ID_ECM = 1, +#else + CONFIG_ID_NCM = 0, +#endif CONFIG_ID_COUNT }; @@ -99,6 +103,7 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) +#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_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 @@ -120,6 +125,8 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_NET_IN 0x82 #endif +#if CFG_TUD_ECM_RNDIS + static uint8_t const rndis_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA @@ -138,14 +145,31 @@ static uint8_t const ecm_configuration[] = TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; +#else + +static uint8_t const ncm_configuration[] = +{ + // Config number (index+1), interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100), + + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +}; + +#endif + // Configuration array: RNDIS and CDC-ECM // - Windows only works with RNDIS // - MacOS only works with CDC-ECM // - Linux will work on both static uint8_t const * const configuration_arr[2] = { +#if CFG_TUD_ECM_RNDIS [CONFIG_ID_RNDIS] = rndis_configuration, [CONFIG_ID_ECM ] = ecm_configuration +#else + [CONFIG_ID_NCM ] = ncm_configuration +#endif }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 790af088f..67e287d3e 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -36,11 +36,12 @@ // List of supported sample rates #if defined(__RX__) -const uint32_t sample_rates[] = {44100, 48000}; + const uint32_t sample_rates[] = {44100, 48000}; #else -const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; + const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; #endif -uint32_t current_sample_rate = 44100; + +uint32_t current_sample_rate = 44100; #define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) @@ -202,7 +203,7 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t { TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); - current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur; + current_sample_rate = ((audio_control_cur_4_t const *)buf)->bCur; TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate); @@ -264,7 +265,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req { TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur; + mute[request->bChannelNumber] = ((audio_control_cur_1_t const *)buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); @@ -295,7 +296,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req // 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) { - audio_control_request_t *request = (audio_control_request_t *)p_request; + audio_control_request_t const *request = (audio_control_request_t const *)p_request; if (request->bEntityID == UAC2_ENTITY_CLOCK) return tud_audio_clock_get_request(rhport, request); diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 4a26b0b1e..9e97845b8 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -77,28 +77,31 @@ uint8_t const * tud_descriptor_device_cb(void) #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_HEADSET_STEREO_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_IN 0x03 -#define EPNUM_AUDIO_OUT 0x03 + // 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_IN 0x03 + #define EPNUM_AUDIO_OUT 0x03 + #elif CFG_TUSB_MCU == OPT_MCU_NRF5X -// ISO endpoints for NRF5x are fixed to 0x08 (0x88) -#define EPNUM_AUDIO_IN 0x08 -#define EPNUM_AUDIO_OUT 0x08 + // ISO endpoints for NRF5x are fixed to 0x08 (0x88) + #define EPNUM_AUDIO_IN 0x08 + #define EPNUM_AUDIO_OUT 0x08 + #elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X -// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT -// e.g EP1 OUT & EP1 IN cannot exist together -#define EPNUM_AUDIO_IN 0x01 -#define EPNUM_AUDIO_OUT 0x02 + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_AUDIO_IN 0x01 + #define EPNUM_AUDIO_OUT 0x02 + #else -#define EPNUM_AUDIO_IN 0x01 -#define EPNUM_AUDIO_OUT 0x01 + #define EPNUM_AUDIO_IN 0x01 + #define EPNUM_AUDIO_OUT 0x01 #endif uint8_t const desc_configuration[] = { // 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), + 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_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 2336266b8..423482634 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -122,7 +122,7 @@ enum 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), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), TUD_USBTMC_DESC(ITF_NUM_USBTMC), }; diff --git a/examples/device/video_capture/.skip.MCU_MSP430x5xx b/examples/device/video_capture/.skip.MCU_MSP430x5xx new file mode 100644 index 000000000..17600f062 --- /dev/null +++ b/examples/device/video_capture/.skip.MCU_MSP430x5xx @@ -0,0 +1 @@ +too many warnings for 16-bit integer overflow diff --git a/examples/device/video_capture/.skip.MCU_SAMD11 b/examples/device/video_capture/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/video_capture/CMakeLists.txt b/examples/device/video_capture/CMakeLists.txt new file mode 100644 index 000000000..cb321f9a8 --- /dev/null +++ b/examples/device/video_capture/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c +) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT}) \ No newline at end of file diff --git a/examples/device/video_capture/Makefile b/examples/device/video_capture/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/video_capture/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/video_capture/src/images.h b/examples/device/video_capture/src/images.h new file mode 100644 index 000000000..1b13cfe81 --- /dev/null +++ b/examples/device/video_capture/src/images.h @@ -0,0 +1,1651 @@ +static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { + /* 0 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 1 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 2 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 3 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 4 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 5 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 6 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 7 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 8 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 9 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 10 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 11 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 12 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 13 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 14 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 15 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 16 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 17 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 18 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 19 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 20 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 21 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 22 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 23 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 24 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 25 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 26 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 27 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 28 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 29 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 30 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 31 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 32 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 33 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 34 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 35 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 36 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 37 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 38 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 39 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 40 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 41 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 42 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 43 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 44 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 45 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 46 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 47 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 48 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 49 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 50 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 51 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 52 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 53 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 54 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 55 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 56 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 57 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 58 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 59 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 60 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 61 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 62 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 63 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 64 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 65 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 66 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 67 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 68 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 69 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 70 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 71 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 72 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 73 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 74 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 75 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 76 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 77 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 78 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 79 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 80 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 81 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 82 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 83 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 84 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 85 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 86 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 87 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 88 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 89 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 90 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 91 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 92 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 93 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 94 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 95 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 96 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, +}; diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c new file mode 100644 index 000000000..f1d48385f --- /dev/null +++ b/examples/device/video_capture/src/main.c @@ -0,0 +1,222 @@ +/* + * 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.h" +#include "tusb.h" +#include "usb_descriptors.h" + +//--------------------------------------------------------------------+ +// 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 uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); +void video_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + + video_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// 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 = BLINK_MOUNTED; +} + + +//--------------------------------------------------------------------+ +// USB Video +//--------------------------------------------------------------------+ +static unsigned frame_num = 0; +static unsigned tx_busy = 0; +static unsigned interval_ms = 1000 / FRAME_RATE; + +/* YUY2 frame buffer */ +#ifdef CFG_EXAMPLE_VIDEO_READONLY +#include "images.h" +#else +static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; +static void fill_color_bar(uint8_t *buffer, unsigned start_position) +{ + /* EBU color bars + * See also https://stackoverflow.com/questions/6939422 */ + static uint8_t const bar_color[8][4] = { + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ + }; + uint8_t *p; + + /* Generate the 1st line */ + uint8_t *end = &buffer[FRAME_WIDTH * 2]; + unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); + p = &buffer[idx * 4]; + for (unsigned i = 0; i < 8; ++i) { + for (int j = 0; j < FRAME_WIDTH / (2 * 8); ++j) { + memcpy(p, &bar_color[i], 4); + p += 4; + if (end <= p) { + p = buffer; + } + } + } + /* Duplicate the 1st line to the others */ + p = &buffer[FRAME_WIDTH * 2]; + for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { + memcpy(p, buffer, FRAME_WIDTH * 2); + p += FRAME_WIDTH * 2; + } +} +#endif + +void video_task(void) +{ + static unsigned start_ms = 0; + static unsigned already_sent = 0; + + if (!tud_video_n_streaming(0, 0)) { + already_sent = 0; + frame_num = 0; + return; + } + + if (!already_sent) { + already_sent = 1; + start_ms = board_millis(); +#ifdef CFG_EXAMPLE_VIDEO_READONLY + tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t) &frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], + FRAME_WIDTH * FRAME_HEIGHT * 16/8); +#else + fill_color_bar(frame_buffer, frame_num); + tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); +#endif + } + + unsigned cur = board_millis(); + if (cur - start_ms < interval_ms) return; // not enough time + if (tx_busy) return; + start_ms += interval_ms; + +#ifdef CFG_EXAMPLE_VIDEO_READONLY + tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t) &frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], + FRAME_WIDTH * FRAME_HEIGHT * 16/8); +#else + fill_color_bar(frame_buffer, frame_num); + tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); +#endif +} + +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) +{ + (void)ctl_idx; (void)stm_idx; + tx_busy = 0; + /* flip buffer */ + ++frame_num; +} + +int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const *parameters) +{ + (void)ctl_idx; (void)stm_idx; + /* convert unit to ms from 100 ns */ + interval_ms = parameters->dwFrameInterval / 10000; + return VIDEO_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h new file mode 100644 index 000000000..4feb6a48a --- /dev/null +++ b/examples/device/video_capture/src/tusb_config.h @@ -0,0 +1,107 @@ +/* + * 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 +//-------------------------------------------------------------------- + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +// RHPort max operational speed can defined by board.mk +// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed +#ifndef BOARD_DEVICE_RHPORT_SPEED + #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED + #else + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED + #endif +#endif + +// Device mode with rhport and speed defined by board.mk +#if BOARD_DEVICE_RHPORT_NUM == 0 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#elif BOARD_DEVICE_RHPORT_NUM == 1 + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#else + #error "Incorrect RHPort configuration" +#endif + +// This example doesn't use an RTOS +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// 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 -------------// +// The number of video control interfaces +#define CFG_TUD_VIDEO 1 + +// The number of video streaming interfaces +#define CFG_TUD_VIDEO_STREAMING 1 + +// video streaming endpoint size +#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c new file mode 100644 index 000000000..da8ec8e89 --- /dev/null +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -0,0 +1,166 @@ +/* + * 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 "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] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +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 Video + // 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 +//--------------------------------------------------------------------+ + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_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, 5 Bulk etc ... + #define EPNUM_VIDEO_IN 0x83 + +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_VIDEO_IN 0x88 + +#else + #define EPNUM_VIDEO_IN 0x81 + +#endif + +uint8_t const desc_fs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), + // IAD for Video Control + TUD_VIDEO_CAPTURE_DESCRIPTOR(4, EPNUM_VIDEO_IN, + FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, + CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) +}; + +// 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_fs_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "TinyUSB UVC", // 4: UVC Interface +}; + +static uint16_t _desc_str[32]; + +// 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; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // 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); + if ( chr_count > 31 ) chr_count = 31; + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; iwIndex == 7 ) @@ -188,7 +188,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ uint16_t total_len; memcpy(&total_len, desc_ms_os_20+8, 2); - return tud_control_xfer(rhport, request, (void*) desc_ms_os_20, total_len); + return tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_ms_os_20, total_len); }else { return false; diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index d1539488f..93e802a90 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -107,7 +107,7 @@ enum 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), + 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, 0x81, 8, EPNUM_CDC_OUT, 0x80 | EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index f185ac4f8..5c63ec0c0 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -7,3 +7,4 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(cdc_msc_hid) +family_add_subdirectory(hid_controller) diff --git a/examples/host/cdc_msc_hid/.only.MCU_MSP432E4 b/examples/host/cdc_msc_hid/.only.MCU_MSP432E4 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 6a2b4d902..ce0dd1a40 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -9,7 +9,8 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -CFLAGS += -Wno-error=cast-align +# TODO: suppress warning caused by host stack +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference # TinyUSB Host Stack source SRC_C += \ @@ -19,9 +20,7 @@ SRC_C += \ src/host/hub.c \ src/host/usbh.c \ src/host/usbh_control.c \ - src/portable/ehci/ehci.c \ src/portable/ohci/ohci.c \ - src/portable/nxp/transdimension/hcd_transdimension.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c include ../../rules.mk diff --git a/examples/host/hid_controller/.only.MCU_MSP432E4 b/examples/host/hid_controller/.only.MCU_MSP432E4 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile index 6f59faeee..c58df562b 100644 --- a/examples/host/hid_controller/Makefile +++ b/examples/host/hid_controller/Makefile @@ -9,10 +9,11 @@ INC += \ EXAMPLE_SOURCE += \ src/hid_app.c \ src/main.c - + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -CFLAGS += -Wno-error=cast-align +# TODO: suppress warning caused by host stack +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference # TinyUSB Host Stack source SRC_C += \ @@ -22,9 +23,7 @@ SRC_C += \ src/host/hub.c \ src/host/usbh.c \ src/host/usbh_control.c \ - src/portable/ehci/ehci.c \ src/portable/ohci/ohci.c \ - src/portable/nxp/transdimension/hcd_transdimension.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c include ../../rules.mk diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index c61ce70f3..582e01959 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -111,7 +111,11 @@ static inline bool is_sony_ds4(uint8_t dev_addr) uint16_t vid, pid; tuh_vid_pid_get(dev_addr, &vid, &pid); - return (vid == 0x054c && pid == 0x09cc); + return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4 + || (vid == 0x0f0d && pid == 0x005e) // Hori FC4 + || (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U) + || (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller + ); } //--------------------------------------------------------------------+ @@ -134,6 +138,8 @@ void hid_app_task(void) // 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) { + (void)desc_report; + (void)desc_len; uint16_t vid, pid; tuh_vid_pid_get(dev_addr, &vid, &pid); diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c index e13fa818a..b9b37a4d2 100644 --- a/examples/host/hid_controller/src/main.c +++ b/examples/host/hid_controller/src/main.c @@ -49,6 +49,7 @@ int main(void) board_init(); printf("TinyUSB Host HID Controller Example\r\n"); + printf("Note: Events only displayed for explictly supported controllers\r\n"); tusb_init(); diff --git a/examples/make.mk b/examples/make.mk index 9daf60e35..793c40aa2 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -65,10 +65,12 @@ MKDIR = mkdir ifeq ($(CMDEXE),1) CP = copy RM = del + PYTHON = python else SED = sed CP = cp RM = rm + PYTHON = python3 endif #-------------- Source files and compiler flags -------------- @@ -102,7 +104,9 @@ CFLAGS += \ -Wmissing-format-attribute \ -Wunreachable-code \ -Wcast-align \ - -Wcast-function-type + -Wcast-function-type \ + -Wcast-qual \ + -Wnull-dereference # Debugging/Optimization ifeq ($(DEBUG), 1) diff --git a/examples/rules.mk b/examples/rules.mk index 861973284..4cc35cb22 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -5,12 +5,11 @@ # Set all as default goal .DEFAULT_GOAL := all -# ESP32-SX and RP2040 has its own CMake build system -ifneq ($(FAMILY),esp32s2) -ifneq ($(FAMILY),esp32s3) -ifneq ($(FAMILY),rp2040) +# ESP32-Sx and RP2040 has its own CMake build system +ifeq (,$(findstring $(FAMILY),esp32s2 esp32s3 rp2040)) + # --------------------------------------- -# GNU Make build system +# Compiler Flags # --------------------------------------- # libc @@ -33,8 +32,10 @@ SRC_C += \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ src/class/msc/msc_device.c \ - src/class/net/net_device.c \ + src/class/net/ecm_rndis_device.c \ + src/class/net/ncm_device.c \ src/class/usbtmc/usbtmc_device.c \ + src/class/video/video_device.c \ src/class/vendor/vendor_device.c # TinyUSB stack include @@ -42,6 +43,12 @@ INC += $(TOP)/src CFLAGS += $(addprefix -I,$(INC)) +# LTO makes it difficult to analyze map file for optimizing size purpose +# We will run this option in ci +ifeq ($(NO_LTO),1) +CFLAGS := $(filter-out -flto,$(CFLAGS)) +endif + LDFLAGS += $(CFLAGS) -Wl,-T,$(TOP)/$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections ifneq ($(SKIP_NANOLIB), 1) LDFLAGS += -specs=nosys.specs -specs=nano.specs @@ -65,6 +72,10 @@ $(info LDFLAGS $(LDFLAGS)) $(info ) $(info ASFLAGS $(ASFLAGS)) $(info ) endif +# --------------------------------------- +# Rules +# --------------------------------------- + all: $(BUILD)/$(PROJECT).bin $(BUILD)/$(PROJECT).hex size uf2: $(BUILD)/$(PROJECT).uf2 @@ -124,11 +135,17 @@ $(BUILD)/obj/%_asm.o: %.S @echo AS $(notdir $@) @$(CC) -x assembler-with-cpp $(ASFLAGS) -c -o $@ $< +endif # GNU Make + size: $(BUILD)/$(PROJECT).elf -@echo '' @$(SIZE) $< -@echo '' +# linkermap must be install previously at https://github.com/hathach/linkermap +linkermap: $(BUILD)/$(PROJECT).elf + @linkermap -v $<.map + .PHONY: clean clean: ifeq ($(CMDEXE),1) @@ -137,21 +154,18 @@ else $(RM) -rf $(BUILD) endif -endif -endif -endif # GNU Make - # --------------------------------------- # Flash Targets # --------------------------------------- -# Flash binary using Jlink +# Jlink binary ifeq ($(OS),Windows_NT) JLINKEXE = JLink.exe else JLINKEXE = JLinkExe endif +# Jlink Interface JLINK_IF ?= swd # Flash using jlink @@ -164,18 +178,22 @@ flash-jlink: $(BUILD)/$(PROJECT).hex @echo exit >> $(BUILD)/$(BOARD).jlink $(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink -# flash STM32 MCU using stlink with STM32 Cube Programmer CLI +# Flash STM32 MCU using stlink with STM32 Cube Programmer CLI flash-stlink: $(BUILD)/$(PROJECT).elf STM32_Programmer_CLI --connect port=swd --write $< --go -# flash with pyocd +# Flash using pyocd PYOCD_OPTION ?= flash-pyocd: $(BUILD)/$(PROJECT).hex pyocd flash -t $(PYOCD_TARGET) $(PYOCD_OPTION) $< pyocd reset -t $(PYOCD_TARGET) -# flash with Black Magic Probe +# Flash using openocd +OPENOCD_OPTION ?= +flash-openocd: $(BUILD)/$(PROJECT).elf + openocd $(OPENOCD_OPTION) -c "program $< verify reset exit" +# flash with Black Magic Probe # This symlink is created by https://github.com/blacksphere/blackmagic/blob/master/driver/99-blackmagic.rules BMP ?= /dev/ttyBmpGdb @@ -202,4 +220,4 @@ copy-artifact: $(BIN) # Print out the value of a make variable. # https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile print-%: - @echo $* = $($*) + @echo $* = $($*) \ No newline at end of file diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 6a26f55b7..e208624ba 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -96,7 +96,7 @@ void board_led_task(void) TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) { (void) fhdl; - SEGGER_RTT_Write(0, (char*) buf, (int) count); + SEGGER_RTT_Write(0, (const char*) buf, (int) count); return count; } @@ -126,6 +126,8 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; + (void) buf; + (void) count; return 0; } @@ -135,13 +137,13 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) { (void) fhdl; - return board_uart_write(buf, count); + return board_uart_write(buf, (int) count); } TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; - return board_uart_read((uint8_t*) buf, count); + return board_uart_read((uint8_t*) buf, (int) count); } #endif diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 8cc50c808..f8b5c061c 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -98,6 +98,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx #include "msp430.h" +#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 + #include "msp.h" + #elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI // no header needed @@ -125,7 +128,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_RP2040 #include "pico.h" -#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG || CFG_TUSB_MCU == OPT_MCU_EFM32GG11 || CFG_TUSB_MCU == OPT_MCU_EFM32GG12 +#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG #include "em_device.h" #elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X @@ -134,6 +137,15 @@ #elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 #include "gd32vf103.h" +#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X + #include "mm32_device.h" + +#elif CFG_TUSB_MCU == OPT_MCU_XMC4000 + #include "xmc_device.h" + +#elif CFG_TUSB_MCU == OPT_MCU_TM4C123 + #include "TM4C123.h" + #else #error "Missing MCU header" #endif diff --git a/hw/bsp/d5035_01/board.mk b/hw/bsp/d5035_01/board.mk index 1d09bd3d4..b7796b9d8 100644 --- a/hw/bsp/d5035_01/board.mk +++ b/hw/bsp/d5035_01/board.mk @@ -18,6 +18,9 @@ CFLAGS += \ -DSVC_Handler=SVCall_Handler \ -DHWREV=$(HWREV) +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual + # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld diff --git a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c index e7c7ae364..95fe70d01 100644 --- a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c +++ b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c @@ -53,6 +53,9 @@ void UnhandledIRQ(void) while(1); } +// DA146xx driver function that must be called whenever VBUS changes. +extern void tusb_vbus_changed(bool present); + void board_init(void) { // LED @@ -65,12 +68,15 @@ void board_init(void) hal_gpio_init_out(5, 0); // Button - hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_NONE); + hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_DOWN); // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); - NVIC_SetPriority(USB_IRQn, 2); +#if TUSB_OPT_DEVICE_ENABLED + // This board is USB powered there is no need to monitor + // VBUS line. Notify driver that VBUS is present. + tusb_vbus_changed(true); /* Setup USB IRQ */ NVIC_SetPriority(USB_IRQn, 2); @@ -81,6 +87,7 @@ void board_init(void) mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB); mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB); +#endif } //--------------------------------------------------------------------+ @@ -94,8 +101,8 @@ void board_led_write(bool state) uint32_t board_button_read(void) { - // button is active LOW - return hal_gpio_read(BUTTON_PIN) ^ 1; + // button is active HIGH + return hal_gpio_read(BUTTON_PIN); } int board_uart_read(uint8_t* buf, int len) diff --git a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c index 85fa17152..0441c000c 100644 --- a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c +++ b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c @@ -36,6 +36,21 @@ void USB_IRQHandler(void) tud_int_handler(0); } +#if TUSB_OPT_DEVICE_ENABLED +// DA146xx driver function that must be called whenever VBUS changes +extern void tusb_vbus_changed(bool present); + +// VBUS change interrupt handler +void VBUS_IRQHandler(void) +{ + bool present = (CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0; + // Clear VBUS interrupt + CRG_TOP->VBUS_IRQ_CLEAR_REG = 1; + + tusb_vbus_changed(present); +} +#endif + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -65,12 +80,20 @@ void board_init(void) hal_gpio_init_out(5, 0); // Button - hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_NONE); + hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_UP); // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); - NVIC_SetPriority(USB_IRQn, 2); +#if TUSB_OPT_DEVICE_ENABLED + // Setup interrupt for both connect and disconnect + CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk | + CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk; + NVIC_SetPriority(VBUS_IRQn, 2); + // Trigger interrupt at the start to inform driver about VBUS state at start + // otherwise it could go unnoticed. + NVIC_SetPendingIRQ(VBUS_IRQn); + NVIC_EnableIRQ(VBUS_IRQn); /* Setup USB IRQ */ NVIC_SetPriority(USB_IRQn, 2); @@ -81,6 +104,7 @@ void board_init(void) mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB); mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB); +#endif } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/board.mk b/hw/bsp/ea4088qs/board.mk index c624a5cf2..b325dfeb4 100644 --- a/hw/bsp/ea4088qs/board.mk +++ b/hw/bsp/ea4088qs/board.mk @@ -14,7 +14,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC40XX # mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter +CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc40xx/lpc_chip_40xx diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index 86391ab5d..6f243c6a2 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -13,7 +13,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes +CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx @@ -21,7 +21,9 @@ MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx LD_FILE = hw/bsp/$(BOARD)/lpc4357.ld SRC_C += \ - src/portable/nxp/transdimension/dcd_transdimension.c \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \ $(MCU_DIR)/src/chip_18xx_43xx.c \ $(MCU_DIR)/src/clock_18xx_43xx.c \ diff --git a/hw/bsp/esp32s2/boards/CMakeLists.txt b/hw/bsp/esp32s2/boards/CMakeLists.txt index 71753012b..c3c687a70 100644 --- a/hw/bsp/esp32s2/boards/CMakeLists.txt +++ b/hw/bsp/esp32s2/boards/CMakeLists.txt @@ -6,9 +6,7 @@ idf_component_register(SRCS esp32s2.c # Apply board specific content include("${BOARD}/board.cmake") -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" "${TOP}/hw" "${TOP}/src" ) diff --git a/hw/bsp/esp32s2/family.mk b/hw/bsp/esp32s2/family.mk index fb9b21641..4b9000a6a 100644 --- a/hw/bsp/esp32s2/family.mk +++ b/hw/bsp/esp32s2/family.mk @@ -7,14 +7,11 @@ all: build: all -clean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean - fullclean: if test -f sdkconfig; then $(RM) -f sdkconfig ; fi if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi -flash bootloader-flash app-flash erase monitor dfu-flash dfu: +clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ uf2: $(BUILD)/$(PROJECT).uf2 diff --git a/hw/bsp/fomu/fomu.c b/hw/bsp/fomu/fomu.c index 25e5e9613..12b7bfd18 100644 --- a/hw/bsp/fomu/fomu.c +++ b/hw/bsp/fomu/fomu.c @@ -101,9 +101,14 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { int32_t offset = 0; + uint8_t const* buf8 = (uint8_t const*) buf; for (offset = 0; offset < len; offset++) - if (! (messible_status_read() & CSR_MESSIBLE_STATUS_FULL_OFFSET)) - messible_in_write(((uint8_t *)buf)[offset]); + { + if (!(messible_status_read() & CSR_MESSIBLE_STATUS_FULL_OFFSET)) + { + messible_in_write(buf8[offset]); + } + } return len; } diff --git a/hw/bsp/frdm_k32l2b/frdm_k32l2b.c b/hw/bsp/frdm_k32l2b/frdm_k32l2b.c index c45095caa..924bb18e9 100644 --- a/hw/bsp/frdm_k32l2b/frdm_k32l2b.c +++ b/hw/bsp/frdm_k32l2b/frdm_k32l2b.c @@ -122,7 +122,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - LPUART_WriteBlocking(UART_PORT, (uint8_t*)buf, len); + LPUART_WriteBlocking(UART_PORT, (uint8_t const*) buf, len); return len; } diff --git a/hw/bsp/frdm_kl25z/board.mk b/hw/bsp/frdm_kl25z/board.mk index 451bc37c2..15bd50eda 100644 --- a/hw/bsp/frdm_kl25z/board.mk +++ b/hw/bsp/frdm_kl25z/board.mk @@ -6,10 +6,15 @@ CFLAGS += \ -mabi=aapcs \ -mcpu=cortex-m0plus \ -DCPU_MKL25Z128VLK4 \ - -DCFG_TUSB_MCU=OPT_MCU_MKL25ZXX + -DCFG_TUSB_MCU=OPT_MCU_MKL25ZXX \ + -DCFG_EXAMPLE_VIDEO_READONLY + +LDFLAGS += \ + -Wl,--defsym,__stack_size__=0x400 \ + -Wl,--defsym,__heap_size__=0 # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter +CFLAGS += -Wno-error=unused-parameter -Wno-error=format MCU_DIR = $(SDK_DIR)/devices/MKL25Z4 diff --git a/hw/bsp/frdm_kl25z/frdm_kl25z.c b/hw/bsp/frdm_kl25z/frdm_kl25z.c index 7d3a173ed..72982ed8a 100644 --- a/hw/bsp/frdm_kl25z/frdm_kl25z.c +++ b/hw/bsp/frdm_kl25z/frdm_kl25z.c @@ -54,6 +54,14 @@ void USB0_IRQHandler(void) #define LED_PIN_FUNCTION kPORT_MuxAsGpio #define LED_STATE_ON 0 +// Button +#define BUTTON_PORT GPIOC +#define BUTTON_PIN_CLOCK kCLOCK_PortC +#define BUTTON_PIN_PORT PORTC +#define BUTTON_PIN 9U +#define BUTTON_PIN_FUNCTION kPORT_MuxAsGpio +#define BUTTON_STATE_ACTIVE 0 + // UART #define UART_PORT UART0 #define UART_PIN_CLOCK kCLOCK_PortA @@ -84,7 +92,19 @@ void board_init(void) PORT_SetPinMux(LED_PIN_PORT, LED_PIN, LED_PIN_FUNCTION); gpio_pin_config_t led_config = { kGPIO_DigitalOutput, 0 }; GPIO_PinInit(LED_PORT, LED_PIN, &led_config); - board_led_write(true); + board_led_write(false); + +#if defined(BUTTON_PORT) && defined(BUTTON_PIN) + // Button + CLOCK_EnableClock(BUTTON_PIN_CLOCK); + port_pin_config_t button_port = { + .pullSelect = kPORT_PullUp, + .mux = BUTTON_PIN_FUNCTION, + }; + PORT_SetPinConfig(BUTTON_PIN_PORT, BUTTON_PIN, &button_port); + gpio_pin_config_t button_config = { kGPIO_DigitalInput, 0 }; + GPIO_PinInit(BUTTON_PORT, BUTTON_PIN, &button_config); +#endif // UART CLOCK_EnableClock(UART_PIN_CLOCK); @@ -119,6 +139,9 @@ void board_led_write(bool state) uint32_t board_button_read(void) { +#if defined(BUTTON_PORT) && defined(BUTTON_PIN) + return BUTTON_STATE_ACTIVE == GPIO_ReadPinInput(BUTTON_PORT, BUTTON_PIN); +#endif return 0; } @@ -130,7 +153,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - LPSCI_WriteBlocking(UART_PORT, (uint8_t*)buf, len); + LPSCI_WriteBlocking(UART_PORT, (uint8_t const*) buf, len); return len; } diff --git a/hw/bsp/gd32vf103/family.c b/hw/bsp/gd32vf103/family.c index d76fb9a2a..c20732302 100644 --- a/hw/bsp/gd32vf103/family.c +++ b/hw/bsp/gd32vf103/family.c @@ -158,7 +158,7 @@ int board_uart_write(void const* buf, int len) { #if defined(UART_DEV) int txsize = len; while (txsize--) { - usart_write(UART_DEV, *(uint8_t*)buf); + usart_write(UART_DEV, *(uint8_t const*)buf); buf++; } return len; diff --git a/hw/bsp/gd32vf103/family.mk b/hw/bsp/gd32vf103/family.mk index 9148e7f8b..49bacdf1b 100644 --- a/hw/bsp/gd32vf103/family.mk +++ b/hw/bsp/gd32vf103/family.mk @@ -28,14 +28,13 @@ CFLAGS += \ -mstrict-align \ -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_GD32VF103 \ - -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP \ - -DGD32VF103 + -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(GD32VF103_SDK_DRIVER)/gd32vf103_rcu.c \ $(GD32VF103_SDK_DRIVER)/gd32vf103_gpio.c \ $(GD32VF103_SDK_DRIVER)/Usb/gd32vf103_usb_hw.c \ diff --git a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.mk b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.mk index 507db7f00..17dc01cd9 100644 --- a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.mk +++ b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DCPU_MIMXRT1011DAE5A +CFLAGS += -DCPU_MIMXRT1011DAE5A -DCFG_EXAMPLE_VIDEO_READONLY MCU_VARIANT = MIMXRT1011 # For flash-jlink target diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board.mk b/hw/bsp/imxrt/boards/mimxrt1015_evk/board.mk index 17fd25dfe..20c697ea1 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board.mk +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DCPU_MIMXRT1015DAF5A +CFLAGS += -DCPU_MIMXRT1015DAF5A -DCFG_EXAMPLE_VIDEO_READONLY MCU_VARIANT = MIMXRT1015 # For flash-jlink target diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 77a224a5e..716681ca9 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -172,7 +172,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - LPUART_WriteBlocking(UART_PORT, (uint8_t*)buf, len); + LPUART_WriteBlocking(UART_PORT, (uint8_t const*)buf, len); return len; } diff --git a/hw/bsp/imxrt/family.mk b/hw/bsp/imxrt/family.mk index a919d3698..d086d503f 100644 --- a/hw/bsp/imxrt/family.mk +++ b/hw/bsp/imxrt/family.mk @@ -28,7 +28,9 @@ LDFLAGS += \ -Wl,--defsym,__stack_size__=0x800 \ SRC_C += \ - src/portable/nxp/transdimension/dcd_transdimension.c \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ $(MCU_DIR)/system_$(MCU_VARIANT).c \ $(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \ $(MCU_DIR)/project_template/clock_config.c \ diff --git a/hw/bsp/lpc15/boards/lpcxpresso1549/board.mk b/hw/bsp/lpc15/boards/lpcxpresso1549/board.mk index a3e04cfa1..b00fc71b0 100644 --- a/hw/bsp/lpc15/boards/lpcxpresso1549/board.mk +++ b/hw/bsp/lpc15/boards/lpcxpresso1549/board.mk @@ -1,3 +1,4 @@ +CFLAGS += -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/lpc1549.ld JLINK_DEVICE = LPC1549 diff --git a/hw/bsp/lpc15/family.mk b/hw/bsp/lpc15/family.mk index e80a3bc51..c7dd3f8be 100644 --- a/hw/bsp/lpc15/family.mk +++ b/hw/bsp/lpc15/family.mk @@ -15,7 +15,7 @@ CFLAGS += \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' # mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable +CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc15xx/lpc_chip_15xx diff --git a/hw/bsp/lpc18/family.mk b/hw/bsp/lpc18/family.mk index 3fed0b45a..7aa36abc4 100644 --- a/hw/bsp/lpc18/family.mk +++ b/hw/bsp/lpc18/family.mk @@ -13,12 +13,14 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes +CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx SRC_C += \ - src/portable/nxp/transdimension/dcd_transdimension.c \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc18xx.c \ $(MCU_DIR)/src/chip_18xx_43xx.c \ $(MCU_DIR)/src/clock_18xx_43xx.c \ diff --git a/hw/bsp/lpc54/family.c b/hw/bsp/lpc54/family.c index 4789425a3..4f1199c3a 100644 --- a/hw/bsp/lpc54/family.c +++ b/hw/bsp/lpc54/family.c @@ -210,7 +210,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - USART_WriteBlocking(UART_DEV, (uint8_t *)buf, len); + USART_WriteBlocking(UART_DEV, (uint8_t const *) buf, len); return 0; } diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index 4fc1f6222..f037a9f5b 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -265,7 +265,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - USART_WriteBlocking(UART_DEV, (uint8_t *)buf, len); + USART_WriteBlocking(UART_DEV, (uint8_t const *) buf, len); return len; } diff --git a/hw/bsp/lpcxpresso11u37/board.mk b/hw/bsp/lpcxpresso11u37/board.mk index 8fcda51ee..b736eebe1 100644 --- a/hw/bsp/lpcxpresso11u37/board.mk +++ b/hw/bsp/lpcxpresso11u37/board.mk @@ -9,6 +9,7 @@ CFLAGS += \ -DCORE_M0 \ -D__USE_LPCOPEN \ -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_LPC11UXX \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' diff --git a/hw/bsp/lpcxpresso1347/board.mk b/hw/bsp/lpcxpresso1347/board.mk index 0d56a33a6..62135c274 100644 --- a/hw/bsp/lpcxpresso1347/board.mk +++ b/hw/bsp/lpcxpresso1347/board.mk @@ -9,6 +9,7 @@ CFLAGS += \ -DCORE_M3 \ -D__USE_LPCOPEN \ -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_LPC13XX \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' diff --git a/hw/bsp/lpcxpresso1769/board.mk b/hw/bsp/lpcxpresso1769/board.mk index b69be39bd..34b4d6dc0 100644 --- a/hw/bsp/lpcxpresso1769/board.mk +++ b/hw/bsp/lpcxpresso1769/board.mk @@ -12,7 +12,7 @@ CFLAGS += \ -DRTC_EV_SUPPORT=0 # lpc_types.h cause following errors -CFLAGS += -Wno-error=strict-prototypes +CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc175x_6x/lpc_chip_175x_6x diff --git a/hw/bsp/mbed1768/board.mk b/hw/bsp/mbed1768/board.mk index e99df9f08..b0d885866 100644 --- a/hw/bsp/mbed1768/board.mk +++ b/hw/bsp/mbed1768/board.mk @@ -12,7 +12,7 @@ CFLAGS += \ -DRTC_EV_SUPPORT=0 # startup.c and lpc_types.h cause following errors -CFLAGS += -Wno-error=strict-prototypes +CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc175x_6x/lpc_chip_175x_6x diff --git a/hw/bsp/mm32/boards/mm32f327x_mb39/board.mk b/hw/bsp/mm32/boards/mm32f327x_mb39/board.mk new file mode 100644 index 000000000..b7663926f --- /dev/null +++ b/hw/bsp/mm32/boards/mm32f327x_mb39/board.mk @@ -0,0 +1,8 @@ +LD_FILE = $(BOARD_PATH)/flash.ld +SRC_S += $(SDK_DIR)/mm32f327x/MM32F327x/Source/GCC_StartAsm/startup_mm32m3ux_u_gcc.S + +# For flash-jlink target +#JLINK_DEVICE = stm32f411ve + +# flash target using on-board stlink +#flash: flash-jlink diff --git a/hw/bsp/mm32/boards/mm32f327x_mb39/flash.ld b/hw/bsp/mm32/boards/mm32f327x_mb39/flash.ld new file mode 100644 index 000000000..d96d6e43d --- /dev/null +++ b/hw/bsp/mm32/boards/mm32f327x_mb39/flash.ld @@ -0,0 +1,163 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 MM32 SE TEAM + * + * 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. + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x2001FFFF; /* end of RAM */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/mm32/boards/mm32f327x_mb39/mm32f327x_mb39.c b/hw/bsp/mm32/boards/mm32f327x_mb39/mm32f327x_mb39.c new file mode 100644 index 000000000..cff7bc15e --- /dev/null +++ b/hw/bsp/mm32/boards/mm32f327x_mb39/mm32f327x_mb39.c @@ -0,0 +1,172 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 MM32 SE TEAM + * + * 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 "mm32_device.h" +#include "hal_conf.h" +#include "tusb.h" +#include "../board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler (void) +{ + tud_int_handler(0); + +} +void USB_DeviceClockInit (void) +{ + /* Select USBCLK source */ + // RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); + RCC->CFGR &= ~(0x3 << 22); + RCC->CFGR |= (0x1 << 22); + + /* Enable USB clock */ + RCC->AHB2ENR |= 0x1 << 7; +} +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +// LED + +void board_led_write (bool state); +extern u32 SystemCoreClock; +const int baudrate = 115200; + +void board_init (void) +{ +// usb clock + USB_DeviceClockInit(); + + if ( SysTick_Config(SystemCoreClock / 1000) ) + { + while ( 1 ) + ; + } + NVIC_SetPriority(SysTick_IRQn, 0x0); + + // LED + GPIO_InitTypeDef GPIO_InitStruct; + RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_15); //Disable JTDI AF to AF15 + + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + board_led_write(true); + + // UART + UART_InitTypeDef UART_InitStruct; + + RCC_APB2PeriphClockCmd(RCC_APB2ENR_UART1, ENABLE); //enableUART1,GPIOAclock + RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE); // + //UART initialset + + GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7); + + UART_StructInit(&UART_InitStruct); + UART_InitStruct.UART_BaudRate = baudrate; + UART_InitStruct.UART_WordLength = UART_WordLength_8b; + UART_InitStruct.UART_StopBits = UART_StopBits_1; //one stopbit + UART_InitStruct.UART_Parity = UART_Parity_No; //none odd-even verify bit + UART_InitStruct.UART_HardwareFlowControl = UART_HardwareFlowControl_None; //No hardware flow control + UART_InitStruct.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; // receive and sent mode + + UART_Init(UART1, &UART_InitStruct); //initial uart 1 + UART_Cmd(UART1, ENABLE); //enable uart 1 + + //UART1_TX GPIOA.9 + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + //UART1_RX GPIOA.10 + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(GPIOA, &GPIO_InitStruct); + +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write (bool state) +{ + state ? (GPIO_ResetBits(GPIOA, GPIO_Pin_15)) : (GPIO_SetBits(GPIOA, GPIO_Pin_15)); +} + +uint32_t board_button_read (void) +{ + return 0; +} + +int board_uart_read (uint8_t *buf, int len) +{ + (void) buf; + (void) len; + return 0; +} + +int board_uart_write (void const *buf, int len) +{ + const char *buff = buf; + while ( len ) + { + while ( (UART1->CSR & UART_IT_TXIEN) == 0 ) + ; //The loop is sent until it is finished + UART1->TDR = (*buff & 0xFF); + buff++; + len--; + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis (void) +{ + return system_ticks; +} +#endif + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/mm32/family.mk b/hw/bsp/mm32/family.mk new file mode 100644 index 000000000..1a9f51191 --- /dev/null +++ b/hw/bsp/mm32/family.mk @@ -0,0 +1,36 @@ +UF2_FAMILY_ID = 0x0 +SDK_DIR = hw/mcu/mindmotion/mm32sdk +DEPS_SUBMODULES += lib/CMSIS_5 $(SDK_DIR) + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m3 \ + -mfloat-abi=soft \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_MM32F327X + +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=unused-parameter -Wno-error=maybe-uninitialized -Wno-error=cast-qual + +SRC_C += \ + src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c \ + $(SDK_DIR)/mm32f327x/MM32F327x/Source/system_mm32f327x.c \ + $(SDK_DIR)/mm32f327x/MM32F327x/HAL_Lib/Src/hal_gpio.c \ + $(SDK_DIR)/mm32f327x/MM32F327x/HAL_Lib/Src/hal_rcc.c \ + $(SDK_DIR)/mm32f327x/MM32F327x/HAL_Lib/Src/hal_uart.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(SDK_DIR)/mm32f327x/MM32F327x/Include \ + $(TOP)/$(SDK_DIR)/mm32f327x/MM32F327x/HAL_Lib/Inc + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM3 + +# flash target using on-board +flash: flash-jlink diff --git a/hw/bsp/msp432e4/boards/msp_exp432e401y/board.h b/hw/bsp/msp432e4/boards/msp_exp432e401y/board.h new file mode 100644 index 000000000..3130d663b --- /dev/null +++ b/hw/bsp/msp432e4/boards/msp_exp432e401y/board.h @@ -0,0 +1,46 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#define CLK_LED 12u +#define GPIO_LED GPION +#define GPIO_LED_PIN 1u + +#define CLK_BUTTON 8u +#define GPIO_BUTTON GPIOJ +#define GPIO_BUTTON_PIN 0u + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/msp432e4/family.c b/hw/bsp/msp432e4/family.c new file mode 100644 index 000000000..262dc1d30 --- /dev/null +++ b/hw/bsp/msp432e4/family.c @@ -0,0 +1,203 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "bsp/board.h" +#include "board.h" +#include "msp.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ +#if TUSB_OPT_HOST_ENABLED + tuh_int_handler(0); +#endif +#if TUSB_OPT_DEVICE_ENABLED + tud_int_handler(0); +#endif +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +void board_init(void) +{ + unsigned bits; + /* Turn off power domains that unused peripherals belong to */ + SYSCTL->PCCAN = 0u; +#ifdef __MCU_HAS_LCD0__ + SYSCTL->PCLCD = 0u; +#endif + SYSCTL->PCEMAC = 0u; + SYSCTL->PCEPHY = 0u; + SYSCTL->PCCCM = 0u; + + /* --- Setup system clock --- */ + /* Start power-up process of the main oscillator */ + SYSCTL->MOSCCTL = SYSCTL_MOSCCTL_OSCRNG; + while (!(SYSCTL->RIS & SYSCTL_RIS_MOSCPUPRIS)) ; /* Wait for completion */ + SYSCTL->MISC = SYSCTL_MISC_MOSCPUPMIS; /* Clear the completion interrupt status */ + /* Set the main oscillator to PLL reference clock */ + SYSCTL->RSCLKCFG = SYSCTL_RSCLKCFG_PLLSRC_MOSC; + /* PLL freq. = (MOSC freq. / 10) * 96 = 240MHz */ + SYSCTL->PLLFREQ1 = (4 << SYSCTL_PLLFREQ1_N_S) | (1 << SYSCTL_PLLFREQ1_Q_S); + SYSCTL->PLLFREQ0 = (96 << SYSCTL_PLLFREQ0_MINT_S) | SYSCTL_PLLFREQ0_PLLPWR; + /* Set BCHT=6, BCE=0, WS=5 for 120MHz system clock */ + SYSCTL->MEMTIM0 = SYSCTL_MEMTIM0_EBCHT_3_5 | (5 << SYSCTL_MEMTIM0_EWS_S) | + SYSCTL_MEMTIM0_FBCHT_3_5 | (5 << SYSCTL_MEMTIM0_FWS_S) | SYSCTL_MEMTIM0_MB1; + /* Wait for completion of PLL power-up process */ + while (!(SYSCTL->RIS & SYSCTL_RIS_PLLLRIS)) ; + SYSCTL->MISC = SYSCTL_MISC_PLLLMIS; /* Clear the completion interrupt status */ + /* Switch the system clock to PLL/4 */ + SYSCTL->RSCLKCFG = SYSCTL_RSCLKCFG_MEMTIMU | SYSCTL_RSCLKCFG_ACG | + SYSCTL_RSCLKCFG_USEPLL | SYSCTL_RSCLKCFG_PLLSRC_MOSC | (1 << SYSCTL_RSCLKCFG_PSYSDIV_S); + + SystemCoreClockUpdate(); +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + /* USR_LED1 ON1 */ + bits = TU_BIT(CLK_LED); + SYSCTL->RCGCGPIO |= bits; + while (bits != (SYSCTL->RCGCGPIO & bits)) ; + GPIO_LED->DIR = TU_BIT(GPIO_LED_PIN); + GPIO_LED->DEN = TU_BIT(GPIO_LED_PIN); + + /* USR_SW1 PJ0 */ + bits = TU_BIT(CLK_BUTTON); + SYSCTL->RCGCGPIO |= bits; + while (bits != (SYSCTL->RCGCGPIO & bits)) ; + GPIO_BUTTON->PUR = TU_BIT(GPIO_BUTTON_PIN); + GPIO_BUTTON->DEN = TU_BIT(GPIO_BUTTON_PIN); + + /* UART PA0,1 */ + bits = TU_BIT(0); + SYSCTL->RCGCGPIO |= bits; + while (bits != (SYSCTL->RCGCGPIO & bits)) ; + GPIOA->AFSEL = 3u; + GPIOA->PCTL = 0x11u; + GPIOA->DEN = 3u; + + SYSCTL->RCGCUART |= 1u << 0; + while (!(SYSCTL->PRUART & (1u << 0))) ; + UART0->CTL = 0; + UART0->IBRD = 8; /* 8.68056 = 16MHz / (16 * 115200) */ + UART0->FBRD = 44; /* 0.6875 = 44/64 -> 115108bps (0.08%) */ + UART0->LCRH = UART_LCRH_WLEN_8 | UART_LCRH_FEN; + UART0->CC = UART_CC_CS_PIOSC; /* Set the baud clock to PIOSC */ + UART0->CTL = UART_CTL_RXE | UART_CTL_TXE | UART_CTL_UARTEN; + + /* USB PB0(ID) PB1(VBUS) PL6,7(DP,DM) */ + bits = TU_BIT(1) | TU_BIT(10); + SYSCTL->RCGCGPIO |= bits; + while (bits != (SYSCTL->RCGCGPIO & bits)) ; + GPIOB->AMSEL = TU_BIT(0) | TU_BIT(1); + GPIOL->AMSEL = TU_BIT(6) | TU_BIT(7); + +#if TUSB_OPT_HOST_ENABLED + /* USB PD6(EPEN) */ + bits = TU_BIT(3); + SYSCTL->RCGCGPIO |= bits; + while (bits != (SYSCTL->RCGCGPIO & bits)) ; + GPIOD->AFSEL = TU_BIT(6); + GPIOD->PCTL = 0x05000000u; + GPIOD->DEN = TU_BIT(6); +#endif + + SYSCTL->RCGCUSB = 1u; /* Open the clock gate for SYSCLK */ + while (!(SYSCTL->PRUSB & (1u << 0))) ; + USB0->CC = USB_CC_CLKEN | (3u << USB_CC_CLKDIV_S); /* 60MHz = 240MHz / 4 */ + __DMB(); /* Wait for completion of opening of the clock gate */ + + SYSCTL->SRUSB = 1u; + for (int i = 0; i < 16; ++i) __NOP(); + SYSCTL->SRUSB = 0u; + + USB0->CC = USB_CC_CLKEN | (3u << USB_CC_CLKDIV_S); /* 60MHz = 240MHz / 4 */ + __DMB(); /* Wait for completion of opening of the clock gate */ +#if TUSB_OPT_HOST_ENABLED + USB0->GPCS = USB_GPCS_DEVMOD_OTG; + USB0->EPC = USB_EPC_EPENDE | USB_EPC_EPEN_HIGH; +#endif +#if TUSB_OPT_DEVICE_ENABLED + USB0->GPCS = USB_GPCS_DEVMOD_DEVVBUS; +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + if (state) + GPIO_LED->DATA |= TU_BIT(GPIO_LED_PIN); + else + GPIO_LED->DATA &= ~TU_BIT(GPIO_LED_PIN); +} + +uint32_t board_button_read(void) +{ + return (GPIO_BUTTON->DATA & TU_BIT(GPIO_BUTTON_PIN)) ? 0u : 1u; +} + +int board_uart_read(uint8_t * buf, int len) +{ + for (int i = 0; i < len; ++i) { + while (UART0->FR & UART_FR_RXFE) ; + *buf++ = UART0->DR; + } + return len; +} + +int board_uart_write(void const * buf, int len) +{ + uint8_t const *p = (uint8_t const *)buf; + for (int i = 0; i < len; ++i) { + while (UART0->FR & UART_FR_TXFF) ; + UART0->DR = *p++; + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0u; +void SysTick_Handler(void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif diff --git a/hw/bsp/msp432e4/family.mk b/hw/bsp/msp432e4/family.mk new file mode 100644 index 000000000..e3cb90abc --- /dev/null +++ b/hw/bsp/msp432e4/family.mk @@ -0,0 +1,41 @@ +DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/ti + +CFLAGS += \ + -flto \ + -mthumb \ + -mslow-flash-data \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -D__MSP432E401Y__ \ + -DCFG_TUSB_MCU=OPT_MCU_MSP432E4 + +# mcu driver cause following warnings +CFLAGS += -Wno-error=cast-qual -Wno-error=format= + +# All source paths should be relative to the top level. +LD_FILE = hw/mcu/ti/msp432e4/Source/msp432e401y.ld +LDINC += $(TOP)/hw/mcu/ti/msp432e4/Include +LDFLAGS += $(addprefix -L,$(LDINC)) + +MCU_DIR = hw/mcu/ti/msp432e4 + +SRC_C += \ + src/portable/mentor/musb/dcd_musb.c \ + src/portable/mentor/musb/hcd_musb.c \ + $(MCU_DIR)/Source/system_msp432e401y.c + +INC += \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(MCU_DIR)/Include \ + $(TOP)/$(BOARD_PATH) + +SRC_S += $(MCU_DIR)/Source/startup_msp432e411y_gcc.S + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = MSP432E401Y +JLINK_IF = SWD diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index 04c37feeb..3e901567c 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -13,7 +13,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter +CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx @@ -21,7 +21,9 @@ MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx LD_FILE = hw/bsp/$(BOARD)/ngx4330.ld SRC_C += \ - src/portable/nxp/transdimension/dcd_transdimension.c \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \ $(MCU_DIR)/src/chip_18xx_43xx.c \ $(MCU_DIR)/src/clock_18xx_43xx.c \ diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index d1afd2587..d8283a9e6 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -14,19 +14,7 @@ CFLAGS += \ -DCONFIG_GPIO_AS_PINRESET # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align - -# due to tusb_hal_nrf_power_event -GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) -ifeq ($(CMDEXE),1) - ifeq ($(shell if $(GCCVERSION) geq 8 echo 1), 1) - CFLAGS += -Wno-error=cast-function-type - endif -else - ifeq ($(shell expr $(GCCVERSION) \>= 8), 1) - CFLAGS += -Wno-error=cast-function-type - endif -endif +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual # All source paths should be relative to the top level. LD_FILE ?= hw/bsp/nrf/boards/$(BOARD)/nrf52840_s140_v6.ld diff --git a/hw/bsp/nutiny_nuc121s/board.mk b/hw/bsp/nutiny_nuc121s/board.mk index a0a208ca7..ff1d5aa3a 100644 --- a/hw/bsp/nutiny_nuc121s/board.mk +++ b/hw/bsp/nutiny_nuc121s/board.mk @@ -16,24 +16,12 @@ LD_FILE = hw/bsp/$(BOARD)/nuc121_flash.ld SRC_C += \ src/portable/nuvoton/nuc121/dcd_nuc121.c \ hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/system_NUC121.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/adc.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/bpwm.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/clk.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/fmc.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/i2c.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/pdma.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/pwm.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/spi_i2s.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/sys.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/uart.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/usbd.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/usci_i2c.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/usci_spi.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/usci_uart.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/wdt.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/wwdt.c + hw/mcu/nuvoton/nuc121_125/StdDriver/src/uart.c SRC_S += \ hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/GCC/startup_NUC121.S diff --git a/hw/bsp/nutiny_nuc126v/board.mk b/hw/bsp/nutiny_nuc126v/board.mk index 848b19f95..4f0ebf201 100644 --- a/hw/bsp/nutiny_nuc126v/board.mk +++ b/hw/bsp/nutiny_nuc126v/board.mk @@ -7,6 +7,7 @@ CFLAGS += \ -mcpu=cortex-m0 \ -D__ARM_FEATURE_DSP=0 \ -DUSE_ASSERT=0 \ + -DCFG_EXAMPLE_VIDEO_READONLY \ -D__CORTEX_SC=0 \ -DCFG_TUSB_MCU=OPT_MCU_NUC126 @@ -16,28 +17,13 @@ LD_FILE = hw/bsp/$(BOARD)/nuc126_flash.ld SRC_C += \ src/portable/nuvoton/nuc121/dcd_nuc121.c \ hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/system_NUC126.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/acmp.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/adc.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/clk.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/crc.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/ebi.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/fmc.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/pdma.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/pwm.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/rtc.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/sc.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/scuart.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/spi.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/sys.c \ hw/mcu/nuvoton/nuc126/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/timer_pwm.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/uart.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/usbd.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/usci_spi.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/usci_uart.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/wdt.c \ - hw/mcu/nuvoton/nuc126/StdDriver/src/wwdt.c + hw/mcu/nuvoton/nuc126/StdDriver/src/uart.c SRC_S += \ hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Source/GCC/startup_NUC126.S diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nutiny_sdk_nuc120/board.mk index 90b3e91fb..4d7aac7f5 100644 --- a/hw/bsp/nutiny_sdk_nuc120/board.mk +++ b/hw/bsp/nutiny_sdk_nuc120/board.mk @@ -6,6 +6,7 @@ CFLAGS += \ -mabi=aapcs-linux \ -mcpu=cortex-m0 \ -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_NUC120 # All source paths should be relative to the top level. @@ -14,26 +15,11 @@ LD_FILE = hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld SRC_C += \ src/portable/nuvoton/nuc120/dcd_nuc120.c \ hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/acmp.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/adc.c \ hw/mcu/nuvoton/nuc100_120/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/crc.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/fmc.c \ hw/mcu/nuvoton/nuc100_120/StdDriver/src/gpio.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/i2c.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/i2s.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/pdma.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/ps2.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/pwm.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/rtc.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/sc.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/spi.c \ hw/mcu/nuvoton/nuc100_120/StdDriver/src/sys.c \ hw/mcu/nuvoton/nuc100_120/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/uart.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/usbd.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/wdt.c \ - hw/mcu/nuvoton/nuc100_120/StdDriver/src/wwdt.c + hw/mcu/nuvoton/nuc100_120/StdDriver/src/uart.c SRC_S += \ hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S diff --git a/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.h b/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.h new file mode 100644 index 000000000..1d3565d5c --- /dev/null +++ b/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.h @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.mk b/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.mk new file mode 100644 index 000000000..897342479 --- /dev/null +++ b/hw/bsp/raspberrypi4/boards/raspberrypi_cm4/board.mk @@ -0,0 +1 @@ +CFLAGS += -DBCM_VERSION=2711 diff --git a/hw/bsp/raspberrypi4/family.c b/hw/bsp/raspberrypi4/family.c new file mode 100644 index 000000000..ba0b2700a --- /dev/null +++ b/hw/bsp/raspberrypi4/family.c @@ -0,0 +1,144 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "bsp/board.h" +#include "board.h" + +#include "broadcom/interrupts.h" +#include "broadcom/io.h" +#include "broadcom/mmu.h" +#include "broadcom/caches.h" +#include "broadcom/vcmailbox.h" + +// LED +#define LED_PIN 18 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN 16 +#define BUTTON_STATE_ACTIVE 0 + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ +void board_init(void) +{ + setup_mmu_flat_map(); + init_caches(); + + // LED + gpio_initOutputPinWithPullNone(LED_PIN); + board_led_write(true); + + // Button + // TODO + + // Uart + uart_init(); + + // Turn on USB peripheral. + vcmailbox_set_power_state(VCMAILBOX_DEVICE_USB_HCD, true); + + // Timer 1/1024 second tick + SYSTMR->CS_b.M1 = 1; + SYSTMR->C1 = SYSTMR->CLO + 977; + BP_EnableIRQ(TIMER_1_IRQn); + + BP_SetPriority(USB_IRQn, 0x00); + BP_ClearPendingIRQ(USB_IRQn); + BP_EnableIRQ(USB_IRQn); + BP_EnableIRQs(); +} + +void board_led_write(bool state) +{ + gpio_setPinOutputBool(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + for (int i = 0; i < len; i++) { + const char* cbuf = buf; + while (!UART1->STAT_b.TX_READY) {} + if (cbuf[i] == '\n') { + UART1->IO = '\r'; + while (!UART1->STAT_b.TX_READY) {} + } + UART1->IO = cbuf[i]; + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void TIMER_1_IRQHandler(void) +{ + system_ticks++; + SYSTMR->C1 += 977; + SYSTMR->CS_b.M1 = 1; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + // asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/raspberrypi4/family.mk b/hw/bsp/raspberrypi4/family.mk new file mode 100644 index 000000000..c65070a71 --- /dev/null +++ b/hw/bsp/raspberrypi4/family.mk @@ -0,0 +1,51 @@ +MCU_DIR = hw/mcu/broadcom +DEPS_SUBMODULES += $(MCU_DIR) + +include $(TOP)/$(BOARD_PATH)/board.mk + +CC = clang + +CFLAGS += \ + -mcpu=cortex-a72 \ + -Wall \ + -O0 \ + -ffreestanding \ + -nostdlib \ + -nostartfiles \ + -std=c17 \ + -mgeneral-regs-only \ + -DCFG_TUSB_MCU=OPT_MCU_BCM2711 + +# mcu driver cause following warnings +CFLAGS += -Wno-error=cast-qual + +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + $(MCU_DIR)/broadcom/gen/interrupt_handlers.c \ + $(MCU_DIR)/broadcom/interrupts.c \ + $(MCU_DIR)/broadcom/io.c \ + $(MCU_DIR)/broadcom/mmu.c \ + $(MCU_DIR)/broadcom/caches.c \ + $(MCU_DIR)/broadcom/vcmailbox.c + + +CROSS_COMPILE = aarch64-none-elf- + +SKIP_NANOLIB = 1 + +LD_FILE = $(MCU_DIR)/broadcom/link.ld + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(MCU_DIR) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core_A/Include + +SRC_S += $(MCU_DIR)/broadcom/boot.S + +$(BUILD)/kernel8.img: $(BUILD)/$(PROJECT).elf + $(OBJCOPY) -O binary $^ $@ + +# Copy to kernel to netboot drive or SD card +# Change destinaation to fit your need +flash: $(BUILD)/kernel8.img + $(CP) $< /home/$(USER)/Documents/code/pi4_tinyusb/boot_cpy diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 41960b6cd..1aa180ef8 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -70,12 +70,13 @@ if (NOT TARGET _rp2040_family_inclusion_marker) ${TOP}/src/class/hid/hid_device.c ${TOP}/src/class/midi/midi_device.c ${TOP}/src/class/msc/msc_device.c - ${TOP}/src/class/net/net_device.c + ${TOP}/src/class/net/ecm_rndis_device.c + ${TOP}/src/class/net/ncm_device.c ${TOP}/src/class/usbtmc/usbtmc_device.c ${TOP}/src/class/vendor/vendor_device.c + ${TOP}/src/class/video/video_device.c ) - # Base config for host mode; wrapped by SDK's tinyusb_host add_library(tinyusb_host_base INTERFACE) target_sources(tinyusb_host_base INTERFACE @@ -151,4 +152,28 @@ if (NOT TARGET _rp2040_family_inclusion_marker) enable_language(C CXX ASM) pico_sdk_init() endfunction() + + # This method must be called from the project scope to suppress known warnings in TinyUSB source files + function(suppress_tinyusb_warnings) + set_source_files_properties( + ${PICO_TINYUSB_PATH}/src/tusb.c + PROPERTIES + COMPILE_FLAGS "-Wno-conversion") + set_source_files_properties( + ${PICO_TINYUSB_PATH}/src/common/tusb_fifo.c + PROPERTIES + COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual") + set_source_files_properties( + ${PICO_TINYUSB_PATH}/src/device/usbd.c + PROPERTIES + COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual -Wno-null-dereference") + set_source_files_properties( + ${PICO_TINYUSB_PATH}/src/device/usbd_control.c + PROPERTIES + COMPILE_FLAGS "-Wno-conversion") + set_source_files_properties( + ${PICO_TINYUSB_PATH}/src/class/cdc/cdc_device.c + PROPERTIES + COMPILE_FLAGS "-Wno-conversion") + endfunction() endif() diff --git a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c index caf5fd6fa..633ddad16 100644 --- a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c +++ b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c @@ -228,7 +228,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const *buf, int len) { - sci0_buf[0].buf = (uint8_t*)buf; + sci0_buf[0].buf = (uint8_t*)(uintptr_t) buf; sci0_buf[0].cnt = len; SCI0.SCR.BYTE |= SCI_SCR_TE | SCI_SCR_TIE; while (SCI0.SCR.BIT.TE) ; diff --git a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c index 20867455e..ab86bc419 100644 --- a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c +++ b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c @@ -273,7 +273,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const *buf, int len) { - sci_buf[0].buf = (uint8_t*)buf; + sci_buf[0].buf = (uint8_t*)(uintptr_t) buf; sci_buf[0].cnt = len; SCI5.SCR.BYTE |= SCI_SCR_TE | SCI_SCR_TIE; while (SCI5.SCR.BIT.TE) ; diff --git a/hw/bsp/samd11/family.mk b/hw/bsp/samd11/family.mk index 032d11b98..ae55be75b 100644 --- a/hw/bsp/samd11/family.mk +++ b/hw/bsp/samd11/family.mk @@ -11,6 +11,9 @@ CFLAGS += \ -DOSC32K_OVERWRITE_CALIBRATION=0 \ -DCFG_TUSB_MCU=OPT_MCU_SAMD11 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual + SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ hw/mcu/microchip/samd11/gcc/gcc/startup_samd11.c \ diff --git a/hw/bsp/samd21/boards/atsamd21_xpro/board.mk b/hw/bsp/samd21/boards/atsamd21_xpro/board.mk index 5cd82735c..4be547a1b 100644 --- a/hw/bsp/samd21/boards/atsamd21_xpro/board.mk +++ b/hw/bsp/samd21/boards/atsamd21_xpro/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21J18A__ +CFLAGS += -D__SAMD21J18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/samd21j18a_flash.ld diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.mk b/hw/bsp/samd21/boards/circuitplayground_express/board.mk index bb426cdaa..d6c9150b3 100644 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.mk +++ b/hw/bsp/samd21/boards/circuitplayground_express/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.mk b/hw/bsp/samd21/boards/curiosity_nano/board.mk index ec3217f89..112fb6946 100644 --- a/hw/bsp/samd21/boards/curiosity_nano/board.mk +++ b/hw/bsp/samd21/boards/curiosity_nano/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G17A__ -DCFG_EXAMPLE_MSC_READONLY +CFLAGS += -D__SAMD21G17A__ -DCFG_EXAMPLE_MSC_READONLY -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/samd21g17a_flash.ld diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.mk b/hw/bsp/samd21/boards/feather_m0_express/board.mk index bb426cdaa..d6c9150b3 100644 --- a/hw/bsp/samd21/boards/feather_m0_express/board.mk +++ b/hw/bsp/samd21/boards/feather_m0_express/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk b/hw/bsp/samd21/boards/itsybitsy_m0/board.mk index bb426cdaa..d6c9150b3 100644 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk +++ b/hw/bsp/samd21/boards/itsybitsy_m0/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/luna_d21/board.mk b/hw/bsp/samd21/boards/luna_d21/board.mk index 5beb5e02d..27a634e3a 100644 --- a/hw/bsp/samd21/boards/luna_d21/board.mk +++ b/hw/bsp/samd21/boards/luna_d21/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/samd21g18a_flash.ld diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.h b/hw/bsp/samd21/boards/metro_m0_express/board.h index b9292b9af..13b7556b0 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.h +++ b/hw/bsp/samd21/boards/metro_m0_express/board.h @@ -35,7 +35,7 @@ #define LED_PIN 17 #define LED_STATE_ON 1 -// Button +// Button: D5 #define BUTTON_PIN 15 #define BUTTON_STATE_ACTIVE 0 diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.mk b/hw/bsp/samd21/boards/metro_m0_express/board.mk index bb426cdaa..d6c9150b3 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.mk +++ b/hw/bsp/samd21/boards/metro_m0_express/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/qtpy/board.h b/hw/bsp/samd21/boards/qtpy/board.h new file mode 100644 index 000000000..6f8325e49 --- /dev/null +++ b/hw/bsp/samd21/boards/qtpy/board.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED is neopixel, leave unset for now + +// Button is wired to reset + +// UART +#define UART_RX_PIN 8 +#define UART_TX_PIN 7 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/qtpy/board.mk b/hw/bsp/samd21/boards/qtpy/board.mk new file mode 100644 index 000000000..6cefa84c3 --- /dev/null +++ b/hw/bsp/samd21/boards/qtpy/board.mk @@ -0,0 +1,11 @@ +# For Adafruit QT Py board + +CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21E18 + +flash: flash-bossac diff --git a/hw/bsp/samd21/boards/qtpy/qtpy.ld b/hw/bsp/samd21/boards/qtpy/qtpy.ld new file mode 100644 index 000000000..f0c93340c --- /dev/null +++ b/hw/bsp/samd21/boards/qtpy/qtpy.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the Licence at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk b/hw/bsp/samd21/boards/seeeduino_xiao/board.mk index 54591b3a5..1c888da3a 100644 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk +++ b/hw/bsp/samd21/boards/seeeduino_xiao/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAMD21G18A__ +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/trinket_m0/board.h b/hw/bsp/samd21/boards/trinket_m0/board.h new file mode 100644 index 000000000..c8692e6bd --- /dev/null +++ b/hw/bsp/samd21/boards/trinket_m0/board.h @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Jean Gressmann + * + * 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. + * + */ + +#pragma once + +// LED +#define LED_PIN 10 // PA10 +#define LED_STATE_ON 1 + +// UART +#define UART_SERCOM 0 + diff --git a/hw/bsp/samd21/boards/trinket_m0/board.mk b/hw/bsp/samd21/boards/trinket_m0/board.mk new file mode 100644 index 000000000..803ffe892 --- /dev/null +++ b/hw/bsp/samd21/boards/trinket_m0/board.mk @@ -0,0 +1,5 @@ +CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/trinket_m0.ld + diff --git a/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld b/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld new file mode 100644 index 000000000..f0c93340c --- /dev/null +++ b/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the Licence at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index eb5b55863..cead582e9 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -44,6 +44,11 @@ void USB_Handler(void) tud_int_handler(0); } +//--------------------------------------------------------------------+ +// UART support +//--------------------------------------------------------------------+ +void uart_init(void); + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -70,15 +75,23 @@ void board_init(void) // Update SystemCoreClock since it is hard coded with asf4 and not correct // Init 1ms tick timer (samd SystemCoreClock may not correct) SystemCoreClock = CONF_CPU_FREQUENCY; +#if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif // Led init +#ifdef LED_PIN gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); board_led_write(false); +#endif // Button init +#ifdef BUTTON_PIN gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); +#endif + + uart_init(); #if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) @@ -119,12 +132,94 @@ void board_init(void) void board_led_write(bool state) { + (void)state; +#ifdef LED_PIN gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +#endif } uint32_t board_button_read(void) { +#ifdef BUTTON_PIN return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); +#else + return 0; +#endif +} + +#if defined(UART_SERCOM) + +#define BOARD_SERCOM2(n) SERCOM ## n +#define BOARD_SERCOM(n) BOARD_SERCOM2(n) + +void uart_init(void) +{ +#if UART_SERCOM == 0 + gpio_set_pin_function(PIN_PA06, PINMUX_PA06D_SERCOM0_PAD2); + gpio_set_pin_function(PIN_PA07, PINMUX_PA07D_SERCOM0_PAD3); + + // setup clock (48MHz) + _pm_enable_bus_clock(PM_BUS_APBC, SERCOM0); + _gclk_enable_channel(SERCOM0_GCLK_ID_CORE, GCLK_CLKCTRL_GEN_GCLK0_Val); + + SERCOM0->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ + while(SERCOM0->USART.SYNCBUSY.bit.SWRST); + + SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ +// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(3) | /* pad 3 */ + SERCOM_USART_CTRLA_TXPO(1); /* pad 2 */ + + SERCOM0->USART.CTRLB.reg = + SERCOM_USART_CTRLB_TXEN | /* tx enabled */ + SERCOM_USART_CTRLB_RXEN; /* rx enabled */ + + SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); + + SERCOM0->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ +#endif +} + +static inline void uart_send_buffer(uint8_t const *text, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = text[i]; + while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + +static inline void uart_send_str(const char* text) +{ + while (*text) { + BOARD_SERCOM(UART_SERCOM)->USART.DATA.reg = *text++; + while((BOARD_SERCOM(UART_SERCOM)->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + if (len < 0) { + uart_send_str(buf); + } else { + uart_send_buffer(buf, len); + } + return len; +} + +#else // ! defined(UART_SERCOM) +void uart_init(void) +{ + } int board_uart_read(uint8_t* buf, int len) @@ -138,6 +233,7 @@ int board_uart_write(void const * buf, int len) (void) buf; (void) len; return 0; } +#endif #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index f1b063f2c..208f23789 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -12,6 +12,9 @@ CFLAGS += \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ -DCFG_TUSB_MCU=OPT_MCU_SAMD21 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual + SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ hw/mcu/microchip/samd21/gcc/gcc/startup_samd21.c \ diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index 9bb5f815e..ab10ae4f8 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -35,8 +35,8 @@ #define LED_PIN 16 #define LED_STATE_ON 1 -// Button -#define BUTTON_PIN (32+14) // D5 +// Button: D5 +#define BUTTON_PIN (32+14) #define BUTTON_STATE_ACTIVE 0 // UART diff --git a/hw/bsp/samd51/family.mk b/hw/bsp/samd51/family.mk index f4e260fb1..783bed82a 100644 --- a/hw/bsp/samd51/family.mk +++ b/hw/bsp/samd51/family.mk @@ -13,7 +13,8 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -CFLAGS += -Wno-error=undef +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ diff --git a/hw/bsp/same54xplainedpro/board.mk b/hw/bsp/same54xplainedpro/board.mk index 16ac786d5..2d0d928ff 100644 --- a/hw/bsp/same54xplainedpro/board.mk +++ b/hw/bsp/same54xplainedpro/board.mk @@ -15,6 +15,8 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_SAME5X \ -DBOARD_NAME="\"Microchip SAM E54 Xplained Pro\"" +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same54p20a_flash.ld diff --git a/hw/bsp/same70_qmtech/board.mk b/hw/bsp/same70_qmtech/board.mk new file mode 100644 index 000000000..ba7088e44 --- /dev/null +++ b/hw/bsp/same70_qmtech/board.mk @@ -0,0 +1,56 @@ +DEPS_SUBMODULES += hw/mcu/microchip + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m7 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -D__SAME70N19B__ \ + -DCFG_TUSB_MCU=OPT_MCU_SAMX7X + +# suppress following warnings from mcu driver +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual + +ASF_DIR = hw/mcu/microchip/same70 + +# All source paths should be relative to the top level. +LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld + +SRC_C += \ + src/portable/microchip/samx7x/dcd_samx7x.c \ + $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ + $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ + $(ASF_DIR)/hpl/core/hpl_init.c \ + $(ASF_DIR)/hpl/usart/hpl_usart.c \ + $(ASF_DIR)/hpl/pmc/hpl_pmc.c \ + $(ASF_DIR)/hal/src/hal_usart_async.c \ + $(ASF_DIR)/hal/src/hal_io.c \ + $(ASF_DIR)/hal/src/hal_atomic.c \ + $(ASF_DIR)/hal/utils/src/utils_ringbuffer.c + +INC += \ + $(TOP)/hw/bsp/$(BOARD) \ + $(TOP)/$(ASF_DIR) \ + $(TOP)/$(ASF_DIR)/config \ + $(TOP)/$(ASF_DIR)/same70b/include \ + $(TOP)/$(ASF_DIR)/hal/include \ + $(TOP)/$(ASF_DIR)/hal/utils/include \ + $(TOP)/$(ASF_DIR)/hpl/core \ + $(TOP)/$(ASF_DIR)/hpl/pio \ + $(TOP)/$(ASF_DIR)/hpl/pmc \ + $(TOP)/$(ASF_DIR)/hri \ + $(TOP)/$(ASF_DIR)/CMSIS/Core/Include + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM7 + +# For flash-jlink target +JLINK_DEVICE = SAME70N19B + +# flash using edbg from https://github.com/ataradov/edbg +# Note: SAME70's GPNVM1 must be set to 1 to boot from flash with +# edbg -t same70 -F w0,1,1 +flash: $(BUILD)/$(PROJECT).bin + edbg --verbose -t same70 -pv -f $< diff --git a/hw/bsp/same70_qmtech/hpl_pmc_config.h b/hw/bsp/same70_qmtech/hpl_pmc_config.h new file mode 100644 index 000000000..387aaa5df --- /dev/null +++ b/hw/bsp/same70_qmtech/hpl_pmc_config.h @@ -0,0 +1,1053 @@ +/* Auto-generated config file hpl_pmc_config.h */ +#ifndef HPL_PMC_CONFIG_H +#define HPL_PMC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include + +#define CLK_SRC_OPTION_OSC32K 0 +#define CLK_SRC_OPTION_XOSC32K 1 +#define CLK_SRC_OPTION_OSC12M 2 +#define CLK_SRC_OPTION_XOSC20M 3 + +#define CLK_SRC_OPTION_SLCK 0 +#define CLK_SRC_OPTION_MAINCK 1 +#define CLK_SRC_OPTION_PLLACK 2 +#define CLK_SRC_OPTION_UPLLCKDIV 3 +#define CLK_SRC_OPTION_MCK 4 + +#define CLK_SRC_OPTION_UPLLCK 3 + +#define CONF_RC_4M 0 +#define CONF_RC_8M 1 +#define CONF_RC_12M 2 + +#define CONF_XOSC32K_NO_BYPASS 0 +#define CONF_XOSC32K_BYPASS 1 + +#define CONF_XOSC20M_NO_BYPASS 0 +#define CONF_XOSC20M_BYPASS 1 + +// Clock_SLCK configuration +// Indicates whether SLCK configuration is enabled or not +// enable_clk_gen_slck +#ifndef CONF_CLK_SLCK_CONFIG +#define CONF_CLK_SLCK_CONFIG 1 +#endif + +// Clock Generator +// clock generator SLCK source + +// 32kHz High Accuracy Internal Oscillator (OSC32K) + +// 32kHz External Crystal Oscillator (XOSC32K) + +// This defines the clock source for SLCK +// clk_gen_slck_oscillator +#ifndef CONF_CLK_GEN_SLCK_SRC +#define CONF_CLK_GEN_SLCK_SRC CLK_SRC_OPTION_OSC32K +#endif + +// Enable Clock_SLCK +// Indicates whether SLCK is enabled or disable +// clk_gen_slck_arch_enable +#ifndef CONF_CLK_SLCK_ENABLE +#define CONF_CLK_SLCK_ENABLE 1 +#endif + +// + +// + +// +// // Clock_MAINCK configuration +// Indicates whether MAINCK configuration is enabled or not +// enable_clk_gen_mainck +#ifndef CONF_CLK_MAINCK_CONFIG +#define CONF_CLK_MAINCK_CONFIG 1 +#endif + +// Clock Generator +// clock generator MAINCK source + +// Embedded 4/8/12MHz RC Oscillator (OSC12M) + +// External 3-20MHz Oscillator (XOSC20M) + +// This defines the clock source for MAINCK +// clk_gen_mainck_oscillator +#ifndef CONF_CLK_GEN_MAINCK_SRC +#define CONF_CLK_GEN_MAINCK_SRC CLK_SRC_OPTION_XOSC20M +#endif + +// Enable Clock_MAINCK +// Indicates whether MAINCK is enabled or disable +// clk_gen_mainck_arch_enable +#ifndef CONF_CLK_MAINCK_ENABLE +#define CONF_CLK_MAINCK_ENABLE 1 +#endif + +// Enable Main Clock Failure Detection +// Indicates whether Main Clock Failure Detection is enabled or disable. +// The 4/8/12 MHz RC oscillator must be selected as the source of MAINCK. +// clk_gen_cfden_enable +#ifndef CONF_CLK_CFDEN_ENABLE +#define CONF_CLK_CFDEN_ENABLE 0 +#endif + +// + +// + +// +// // Clock_MCKR configuration +// Indicates whether MCKR configuration is enabled or not +// enable_clk_gen_mckr +#ifndef CONF_CLK_MCKR_CONFIG +#define CONF_CLK_MCKR_CONFIG 1 +#endif + +// Clock Generator +// clock generator MCKR source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// PLLA Clock (PLLACK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// This defines the clock source for MCKR +// clk_gen_mckr_oscillator +#ifndef CONF_CLK_GEN_MCKR_SRC +#define CONF_CLK_GEN_MCKR_SRC CLK_SRC_OPTION_PLLACK +#endif + +// Enable Clock_MCKR +// Indicates whether MCKR is enabled or disable +// clk_gen_mckr_arch_enable +#ifndef CONF_CLK_MCKR_ENABLE +#define CONF_CLK_MCKR_ENABLE 1 +#endif + +// + +// + +// Master Clock Prescaler +// <0=> 1 +// <1=> 2 +// <2=> 4 +// <3=> 8 +// <4=> 16 +// <5=> 32 +// <6=> 64 +// <7=> 3 +// Select the clock prescaler. +// mckr_presc +#ifndef CONF_MCKR_PRESC +#define CONF_MCKR_PRESC 0 +#endif + +// +// // Clock_MCK configuration +// Indicates whether MCK configuration is enabled or not +// enable_clk_gen_mck +#ifndef CONF_CLK_MCK_CONFIG +#define CONF_CLK_MCK_CONFIG 1 +#endif + +// Clock Generator +// clock generator MCK source + +// Master Clock Controller (PMC_MCKR) + +// This defines the clock source for MCK +// clk_gen_mck_oscillator +#ifndef CONF_CLK_GEN_MCK_SRC +#define CONF_CLK_GEN_MCK_SRC CLK_SRC_OPTION_MCKR +#endif + +// + +// + +// Master Clock Controller Divider MCK divider +// <0=> 1 +// <1=> 2 +// <3=> 3 +// <2=> 4 +// Select the master clock divider. +// mck_div +#ifndef CONF_MCK_DIV +#define CONF_MCK_DIV 1 +#endif + +// +// // Clock_SYSTICK configuration +// Indicates whether SYSTICK configuration is enabled or not +// enable_clk_gen_systick +#ifndef CONF_CLK_SYSTICK_CONFIG +#define CONF_CLK_SYSTICK_CONFIG 1 +#endif + +// Clock Generator +// clock generator SYSTICK source + +// Master Clock Controller (PMC_MCKR) + +// This defines the clock source for SYSTICK +// clk_gen_systick_oscillator +#ifndef CONF_CLK_GEN_SYSTICK_SRC +#define CONF_CLK_GEN_SYSTICK_SRC CLK_SRC_OPTION_MCKR +#endif + +// + +// + +// Systick clock divider +// <8=> 8 +// Select systick clock divider +// systick_clock_div +#ifndef CONF_SYSTICK_DIV +#define CONF_SYSTICK_DIV 8 +#endif + +// +// // Clock_FCLK configuration +// Indicates whether FCLK configuration is enabled or not +// enable_clk_gen_fclk +#ifndef CONF_CLK_FCLK_CONFIG +#define CONF_CLK_FCLK_CONFIG 1 +#endif + +// Clock Generator +// clock generator FCLK source + +// Master Clock Controller (PMC_MCKR) + +// This defines the clock source for FCLK +// clk_gen_fclk_oscillator +#ifndef CONF_CLK_GEN_FCLK_SRC +#define CONF_CLK_GEN_FCLK_SRC CLK_SRC_OPTION_MCKR +#endif + +// + +// + +// +// // Clock_GCLK0 configuration +// Indicates whether GCLK0 configuration is enabled or not +// enable_clk_gen_gclk0 +#ifndef CONF_CLK_GCLK0_CONFIG +#define CONF_CLK_GCLK0_CONFIG 1 +#endif + +// Clock Generator +// clock generator GCLK0 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// USB 480M Clock (UPLLCK) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for GCLK0 +// clk_gen_gclk0_oscillator +#ifndef CONF_CLK_GEN_GCLK0_SRC +#define CONF_CLK_GEN_GCLK0_SRC CLK_SRC_OPTION_MCK +#endif + +// Enable Clock_GCLK0 +// Indicates whether GCLK0 is enabled or disable +// clk_gen_gclk0_arch_enable +#ifndef CONF_CLK_GCLK0_ENABLE +#define CONF_CLK_GCLK0_ENABLE 1 +#endif + +// + +// +// Enable GCLK0 GCLKEN +// Indicates whether GCLK0 GCLKEN is enabled or disable +// gclk0_gclken_enable +#ifndef CONF_GCLK0_GCLKEN_ENABLE +#define CONF_GCLK0_GCLKEN_ENABLE 0 +#endif + +// Generic Clock GCLK0 divider <1-256> +// Select the clock divider (divider = GCLKDIV + 1). +// gclk0_div +#ifndef CONF_GCLK0_DIV +#define CONF_GCLK0_DIV 2 +#endif + +// +// // Clock_GCLK1 configuration +// Indicates whether GCLK1 configuration is enabled or not +// enable_clk_gen_gclk1 +#ifndef CONF_CLK_GCLK1_CONFIG +#define CONF_CLK_GCLK1_CONFIG 1 +#endif + +// Clock Generator +// clock generator GCLK1 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// USB 480M Clock (UPLLCK) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for GCLK1 +// clk_gen_gclk1_oscillator +#ifndef CONF_CLK_GEN_GCLK1_SRC +#define CONF_CLK_GEN_GCLK1_SRC CLK_SRC_OPTION_PLLACK +#endif + +// Enable Clock_GCLK1 +// Indicates whether GCLK1 is enabled or disable +// clk_gen_gclk1_arch_enable +#ifndef CONF_CLK_GCLK1_ENABLE +#define CONF_CLK_GCLK1_ENABLE 1 +#endif + +// + +// +// Enable GCLK1 GCLKEN +// Indicates whether GCLK1 GCLKEN is enabled or disable +// gclk1_gclken_enable +#ifndef CONF_GCLK1_GCLKEN_ENABLE +#define CONF_GCLK1_GCLKEN_ENABLE 0 +#endif + +// Generic Clock GCLK1 divider <1-256> +// Select the clock divider (divider = GCLKDIV + 1). +// gclk1_div +#ifndef CONF_GCLK1_DIV +#define CONF_GCLK1_DIV 3 +#endif + +// +// // Clock_PCK0 configuration +// Indicates whether PCK0 configuration is enabled or not +// enable_clk_gen_pck0 +#ifndef CONF_CLK_PCK0_CONFIG +#define CONF_CLK_PCK0_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK0 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK0 +// clk_gen_pck0_oscillator +#ifndef CONF_CLK_GEN_PCK0_SRC +#define CONF_CLK_GEN_PCK0_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK0 +// Indicates whether PCK0 is enabled or disable +// clk_gen_pck0_arch_enable +#ifndef CONF_CLK_PCK0_ENABLE +#define CONF_CLK_PCK0_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck0_presc +#ifndef CONF_PCK0_PRESC +#define CONF_PCK0_PRESC 1 +#endif + +// +// // Clock_PCK1 configuration +// Indicates whether PCK1 configuration is enabled or not +// enable_clk_gen_pck1 +#ifndef CONF_CLK_PCK1_CONFIG +#define CONF_CLK_PCK1_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK1 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK1 +// clk_gen_pck1_oscillator +#ifndef CONF_CLK_GEN_PCK1_SRC +#define CONF_CLK_GEN_PCK1_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK1 +// Indicates whether PCK1 is enabled or disable +// clk_gen_pck1_arch_enable +#ifndef CONF_CLK_PCK1_ENABLE +#define CONF_CLK_PCK1_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck1_presc +#ifndef CONF_PCK1_PRESC +#define CONF_PCK1_PRESC 2 +#endif + +// +// // Clock_PCK2 configuration +// Indicates whether PCK2 configuration is enabled or not +// enable_clk_gen_pck2 +#ifndef CONF_CLK_PCK2_CONFIG +#define CONF_CLK_PCK2_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK2 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK2 +// clk_gen_pck2_oscillator +#ifndef CONF_CLK_GEN_PCK2_SRC +#define CONF_CLK_GEN_PCK2_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK2 +// Indicates whether PCK2 is enabled or disable +// clk_gen_pck2_arch_enable +#ifndef CONF_CLK_PCK2_ENABLE +#define CONF_CLK_PCK2_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck2_presc +#ifndef CONF_PCK2_PRESC +#define CONF_PCK2_PRESC 3 +#endif + +// +// // Clock_PCK3 configuration +// Indicates whether PCK3 configuration is enabled or not +// enable_clk_gen_pck3 +#ifndef CONF_CLK_PCK3_CONFIG +#define CONF_CLK_PCK3_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK3 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK3 +// clk_gen_pck3_oscillator +#ifndef CONF_CLK_GEN_PCK3_SRC +#define CONF_CLK_GEN_PCK3_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK3 +// Indicates whether PCK3 is enabled or disable +// clk_gen_pck3_arch_enable +#ifndef CONF_CLK_PCK3_ENABLE +#define CONF_CLK_PCK3_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck3_presc +#ifndef CONF_PCK3_PRESC +#define CONF_PCK3_PRESC 4 +#endif + +// +// // Clock_PCK4 configuration +// Indicates whether PCK4 configuration is enabled or not +// enable_clk_gen_pck4 +#ifndef CONF_CLK_PCK4_CONFIG +#define CONF_CLK_PCK4_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK4 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK4 +// clk_gen_pck4_oscillator +#ifndef CONF_CLK_GEN_PCK4_SRC +#define CONF_CLK_GEN_PCK4_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK4 +// Indicates whether PCK4 is enabled or disable +// clk_gen_pck4_arch_enable +#ifndef CONF_CLK_PCK4_ENABLE +#define CONF_CLK_PCK4_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck4_presc +#ifndef CONF_PCK4_PRESC +#define CONF_PCK4_PRESC 5 +#endif + +// +// // Clock_PCK5 configuration +// Indicates whether PCK5 configuration is enabled or not +// enable_clk_gen_pck5 +#ifndef CONF_CLK_PCK5_CONFIG +#define CONF_CLK_PCK5_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK5 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK5 +// clk_gen_pck5_oscillator +#ifndef CONF_CLK_GEN_PCK5_SRC +#define CONF_CLK_GEN_PCK5_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK5 +// Indicates whether PCK5 is enabled or disable +// clk_gen_pck5_arch_enable +#ifndef CONF_CLK_PCK5_ENABLE +#define CONF_CLK_PCK5_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck5_presc +#ifndef CONF_PCK5_PRESC +#define CONF_PCK5_PRESC 6 +#endif + +// +// // Clock_PCK6 configuration +// Indicates whether PCK6 configuration is enabled or not +// enable_clk_gen_pck6 +#ifndef CONF_CLK_PCK6_CONFIG +#define CONF_CLK_PCK6_CONFIG 1 +#endif + +// Clock Generator +// clock generator PCK6 source + +// Slow Clock (SLCK) + +// Main Clock (MAINCK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// PLLA Clock (PLLACK) + +// Master Clock (MCK) + +// This defines the clock source for PCK6 +// clk_gen_pck6_oscillator +#ifndef CONF_CLK_GEN_PCK6_SRC +#define CONF_CLK_GEN_PCK6_SRC CLK_SRC_OPTION_MAINCK +#endif + +// Enable Clock_PCK6 +// Indicates whether PCK6 is enabled or disable +// clk_gen_pck6_arch_enable +#ifndef CONF_CLK_PCK6_ENABLE +#define CONF_CLK_PCK6_ENABLE 0 +#endif + +// + +// + +// Programmable Clock Controller Prescaler <1-256> +// Select the clock prescaler (prescaler = PRESC + 1). +// pck6_presc +#ifndef CONF_PCK6_PRESC +#define CONF_PCK6_PRESC 7 +#endif + +// +// // Clock_USB_480M configuration +// Indicates whether USB_480M configuration is enabled or not +// enable_clk_gen_usb_480m +#ifndef CONF_CLK_USB_480M_CONFIG +#define CONF_CLK_USB_480M_CONFIG 1 +#endif + +// Clock Generator +// clock generator USB_480M source + +// USB 480M Clock (UPLLCK) + +// This defines the clock source for USB_480M +// clk_gen_usb_480m_oscillator +#ifndef CONF_CLK_GEN_USB_480M_SRC +#define CONF_CLK_GEN_USB_480M_SRC CLK_SRC_OPTION_UPLLCK +#endif + +// + +// + +// +// // Clock_USB_48M configuration +// Indicates whether USB_48M configuration is enabled or not +// enable_clk_gen_usb_48m +#ifndef CONF_CLK_USB_48M_CONFIG +#define CONF_CLK_USB_48M_CONFIG 1 +#endif + +// Clock Generator +// clock generator USB_48M source + +// PLLA Clock (PLLACK) + +// UDPLL with Divider (MCKR UPLLDIV2) + +// This defines the clock source for USB_48M +// clk_gen_usb_48m_oscillator +#ifndef CONF_CLK_GEN_USB_48M_SRC +#define CONF_CLK_GEN_USB_48M_SRC CLK_SRC_OPTION_UPLLCKDIV +#endif + +// Enable Clock_USB_48M +// Indicates whether USB_48M is enabled or disable +// clk_gen_usb_48m_arch_enable +#ifndef CONF_CLK_USB_48M_ENABLE +#define CONF_CLK_USB_48M_ENABLE 1 +#endif + +// + +// + +// USB Clock Controller Divider <1-16> +// Select the USB clock divider (divider = USBDIV + 1). +// usb_48m_div +#ifndef CONF_USB_48M_DIV +#define CONF_USB_48M_DIV 5 +#endif + +// +// // Clock_SLCK2 configuration +// Indicates whether SLCK2 configuration is enabled or not +// enable_clk_gen_slck2 +#ifndef CONF_CLK_SLCK2_CONFIG +#define CONF_CLK_SLCK2_CONFIG 1 +#endif + +// Clock Generator +// clock generator SLCK2 source + +// Slow Clock (SLCK) + +// This defines the clock source for SLCK2 +// clk_gen_slck2_oscillator +#ifndef CONF_CLK_GEN_SLCK2_SRC +#define CONF_CLK_GEN_SLCK2_SRC CLK_SRC_OPTION_SLCK +#endif + +// + +// + +// +// + +// System Configuration +// Indicates whether configuration for system is enabled or not +// enable_hclk_clock +#ifndef CONF_SYSTEM_CONFIG +#define CONF_SYSTEM_CONFIG 1 +#endif + +// Processor Clock Settings +// Processor Clock source +// Master Clock Controller (PMC_MCKR) +// This defines the clock source for the HCLK (Processor clock) +// hclk_clock_source +#ifndef CONF_HCLK_SRC +#define CONF_HCLK_SRC MCKR +#endif + +// Flash Wait State +// <0=> 1 cycle +// <1=> 2 cycles +// <2=> 3 cycles +// <3=> 4 cycles +// <4=> 5 cycles +// <5=> 6 cycles +// <6=> 7 cycles +// This field defines the number of wait states for read and write operations. +// efc_fws +#ifndef CONF_EFC_WAIT_STATE +#define CONF_EFC_WAIT_STATE 5 +#endif + +// +// + +// SysTick Clock +// enable_systick_clk_clock +#ifndef CONF_SYSTICK_CLK_CONFIG +#define CONF_SYSTICK_CLK_CONFIG 1 +#endif + +// SysTick Clock source +// Master Clock Controller (PMC_MCKR) +// This defines the clock source for the SysTick Clock +// systick_clk_clock_source +#ifndef CONF_SYSTICK_CLK_SRC +#define CONF_SYSTICK_CLK_SRC MCKR +#endif + +// SysTick Clock Divider +// <8=> 8 +// Fixed to 8 if Systick is not using Processor clock +// systick_clk_clock_div +#ifndef CONF_SYSTICK_CLK_DIV +#define CONF_SYSTICK_CLK_DIV 8 +#endif + +// + +// OSC32K Oscillator Configuration +// Indicates whether configuration for OSC32K is enabled or not +// enable_osc32k +#ifndef CONF_OSC32K_CONFIG +#define CONF_OSC32K_CONFIG 1 +#endif + +// OSC32K Oscillator Control +// OSC32K Oscillator Enable +// Indicates whether OSC32K Oscillator is enabled or not +// osc32k_arch_enable +#ifndef CONF_OSC32K_ENABLE +#define CONF_OSC32K_ENABLE 0 +#endif +// +// + +// XOSC32K Oscillator Configuration +// Indicates whether configuration for XOSC32K is enabled or not +// enable_xosc32k +#ifndef CONF_XOSC32K_CONFIG +#define CONF_XOSC32K_CONFIG 0 +#endif + +// XOSC32K Oscillator Control +// Oscillator Bypass Select +// The 32kHz crystal oscillator is not bypassed. +// The 32kHz crystal oscillator is bypassed. +// Indicates whether XOSC32K is bypassed. +// xosc32k_bypass +#ifndef CONF_XOSC32K +#define CONF_XOSC32K CONF_XOSC32K_NO_BYPASS +#endif + +// XOSC32K Oscillator Enable +// Indicates whether XOSC32K Oscillator is enabled or not +// xosc32k_arch_enable +#ifndef CONF_XOSC32K_ENABLE +#define CONF_XOSC32K_ENABLE 0 +#endif +// +// + +// OSC12M Oscillator Configuration +// Indicates whether configuration for OSC12M is enabled or not +// enable_osc12m +#ifndef CONF_OSC12M_CONFIG +#define CONF_OSC12M_CONFIG 0 +#endif + +// OSC12M Oscillator Control +// OSC12M Oscillator Enable +// Indicates whether OSC12M Oscillator is enabled or not. +// osc12m_arch_enable +#ifndef CONF_OSC12M_ENABLE +#define CONF_OSC12M_ENABLE 0 +#endif + +// OSC12M selector +// <0=> 4000000 +// <1=> 8000000 +// <2=> 12000000 +// Select the frequency of embedded fast RC oscillator. +// osc12m_selector +#ifndef CONF_OSC12M_SELECTOR +#define CONF_OSC12M_SELECTOR 2 +#endif +// +// + +// XOSC20M Oscillator Configuration +// Indicates whether configuration for XOSC20M is enabled or not. +// enable_xosc20m +#ifndef CONF_XOSC20M_CONFIG +#define CONF_XOSC20M_CONFIG 1 +#endif + +// XOSC20M Oscillator Control +// XOSC20M selector <3000000-20000000> +// Select the frequency of crystal or ceramic resonator oscillator. +// xosc20m_selector +#ifndef CONF_XOSC20M_SELECTOR +#define CONF_XOSC20M_SELECTOR 12000000 +#endif + +// Start up time for the external oscillator (ms): <0-256> +// Select start-up time. +// xosc20m_startup_time +#ifndef CONF_XOSC20M_STARTUP_TIME +#define CONF_XOSC20M_STARTUP_TIME 62 +#endif + +// Oscillator Bypass Select +// The external crystal oscillator is not bypassed. +// The external crystal oscillator is bypassed. +// Indicates whether XOSC20M is bypassed. +// xosc20m_bypass +#ifndef CONF_XOSC20M +#define CONF_XOSC20M CONF_XOSC20M_NO_BYPASS +#endif + +// XOSC20M Oscillator Enable +// Indicates whether XOSC20M Oscillator is enabled or not +// xosc20m_arch_enable +#ifndef CONF_XOSC20M_ENABLE +#define CONF_XOSC20M_ENABLE 1 +#endif +// +// + +// PLLACK Oscillator Configuration +// Indicates whether configuration for PLLACK is enabled or not +// enable_pllack +#ifndef CONF_PLLACK_CONFIG +#define CONF_PLLACK_CONFIG 1 +#endif + +// PLLACK Reference Clock Source +// Main Clock (MAINCK) +// Select the clock source. +// pllack_ref_clock +#ifndef CONF_PLLACK_CLK +#define CONF_PLLACK_CLK MAINCK +#endif + +// PLLACK Oscillator Control +// PLLACK Oscillator Enable +// Indicates whether PLLACK Oscillator is enabled or not +// pllack_arch_enable +#ifndef CONF_PLLACK_ENABLE +#define CONF_PLLACK_ENABLE 1 +#endif + +// PLLA Frontend Divider (DIVA) <1-255> +// Select the clock divider +// pllack_div +#ifndef CONF_PLLACK_DIV +#define CONF_PLLACK_DIV 1 +#endif + +// PLLACK Muliplier <1-62> +// Indicates PLLA multiplier (multiplier = MULA + 1). +// pllack_mul +#ifndef CONF_PLLACK_MUL +#define CONF_PLLACK_MUL 25 +#endif +// +// + +// UPLLCK Oscillator Configuration +// Indicates whether configuration for UPLLCK is enabled or not +// enable_upllck +#ifndef CONF_UPLLCK_CONFIG +#define CONF_UPLLCK_CONFIG 1 +#endif + +// UPLLCK Reference Clock Source +// External 3-20MHz Oscillator (XOSC20M) +// Select the clock source,only when the input frequency is 12M or 16M, the upllck output is 480M. +// upllck_ref_clock +#ifndef CONF_UPLLCK_CLK +#define CONF_UPLLCK_CLK XOSC20M +#endif + +// UPLLCK Oscillator Control +// UPLLCK Oscillator Enable +// Indicates whether UPLLCK Oscillator is enabled or not +// upllck_arch_enable +#ifndef CONF_UPLLCK_ENABLE +#define CONF_UPLLCK_ENABLE 1 +#endif +// +// + +// UPLLCKDIV Oscillator Configuration +// Indicates whether configuration for UPLLCKDIV is enabled or not +// enable_upllckdiv +#ifndef CONF_UPLLCKDIV_CONFIG +#define CONF_UPLLCKDIV_CONFIG 1 +#endif + +// UPLLCKDIV Reference Clock Source +// USB 480M Clock (UPLLCK) +// Select the clock source. +// upllckdiv_ref_clock +#ifndef CONF_UPLLCKDIV_CLK +#define CONF_UPLLCKDIV_CLK UPLLCK +#endif + +// UPLLCKDIV Oscillator Control +// UPLLCKDIV Clock Divider +// <0=> 1 +// <1=> 2 +// Select the clock divider. +// upllckdiv_div +#ifndef CONF_UPLLCKDIV_DIV +#define CONF_UPLLCKDIV_DIV 1 +#endif +// +// + +// MCK/8 +// enable_mck_div_8 +#ifndef CONF_MCK_DIV_8_CONFIG +#define CONF_MCK_DIV_8_CONFIG 0 +#endif + +// MCK/8 Source +// <0=> Master Clock (MCK) +// mck_div_8_src +#ifndef CONF_MCK_DIV_8_SRC +#define CONF_MCK_DIV_8_SRC 0 +#endif +// + +// External Clock Input Configuration +// enable_dummy_ext +#ifndef CONF_DUMMY_EXT_CONFIG +#define CONF_DUMMY_EXT_CONFIG 1 +#endif + +// External Clock Input Source +// All here are dummy values +// Refer to the peripherals settings for actual input information +// <0=> Specific clock input from specific pin +// dummy_ext_src +#ifndef CONF_DUMMY_EXT_SRC +#define CONF_DUMMY_EXT_SRC 0 +#endif +// + +// External Clock Configuration +// enable_dummy_ext_clk +#ifndef CONF_DUMMY_EXT_CLK_CONFIG +#define CONF_DUMMY_EXT_CLK_CONFIG 1 +#endif + +// External Clock Source +// All here are dummy values +// Refer to the peripherals settings for actual input information +// <0=> External Clock Input +// dummy_ext_clk_src +#ifndef CONF_DUMMY_EXT_CLK_SRC +#define CONF_DUMMY_EXT_CLK_SRC 0 +#endif +// + +// <<< end of configuration section >>> + +#endif // HPL_PMC_CONFIG_H diff --git a/hw/bsp/same70_qmtech/hpl_usart_config.h b/hw/bsp/same70_qmtech/hpl_usart_config.h new file mode 100644 index 000000000..50ca3f15c --- /dev/null +++ b/hw/bsp/same70_qmtech/hpl_usart_config.h @@ -0,0 +1,215 @@ +/* Auto-generated config file hpl_usart_config.h */ +#ifndef HPL_USART_CONFIG_H +#define HPL_USART_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include + +#ifndef CONF_USART_1_ENABLE +#define CONF_USART_1_ENABLE 1 +#endif + +// Basic Configuration + +// Frame parity +// <0x0=>Even parity +// <0x1=>Odd parity +// <0x2=>Parity forced to 0 +// <0x3=>Parity forced to 1 +// <0x4=>No parity +// Parity bit mode for USART frame +// usart_parity +#ifndef CONF_USART_1_PARITY +#define CONF_USART_1_PARITY 0x4 +#endif + +// Character Size +// <0x0=>5 bits +// <0x1=>6 bits +// <0x2=>7 bits +// <0x3=>8 bits +// Data character size in USART frame +// usart_character_size +#ifndef CONF_USART_1_CHSIZE +#define CONF_USART_1_CHSIZE 0x3 +#endif + +// Stop Bit +// <0=>1 stop bit +// <1=>1.5 stop bits +// <2=>2 stop bits +// Number of stop bits in USART frame +// usart_stop_bit +#ifndef CONF_USART_1_SBMODE +#define CONF_USART_1_SBMODE 0 +#endif + +// Clock Output Select +// <0=>The USART does not drive the SCK pin +// <1=>The USART drives the SCK pin if USCLKS does not select the external clock SCK +// Clock Output Select in USART sck, if in usrt master mode, please drive SCK. +// usart_clock_output_select +#ifndef CONF_USART_1_CLKO +#define CONF_USART_1_CLKO 0 +#endif + +// Baud rate <1-3000000> +// USART baud rate setting +// usart_baud_rate +#ifndef CONF_USART_1_BAUD +#define CONF_USART_1_BAUD 9600 +#endif + +// + +// Advanced configuration +// usart_advanced +#ifndef CONF_USART_1_ADVANCED_CONFIG +#define CONF_USART_1_ADVANCED_CONFIG 0 +#endif + +// Channel Mode +// <0=>Normal Mode +// <1=>Automatic Echo +// <2=>Local Loopback +// <3=>Remote Loopback +// Channel mode in USART frame +// usart_channel_mode +#ifndef CONF_USART_1_CHMODE +#define CONF_USART_1_CHMODE 0 +#endif + +// 9 bits character enable +// Enable 9 bits character, this has high priority than 5/6/7/8 bits. +// usart_9bits_enable +#ifndef CONF_USART_1_MODE9 +#define CONF_USART_1_MODE9 0 +#endif + +// Variable Sync +// <0=>User defined configuration +// <1=>sync field is updated when a character is written into US_THR +// Variable Synchronization of Command/Data Sync Start Frarm Delimiter +// variable_sync +#ifndef CONF_USART_1_VAR_SYNC +#define CONF_USART_1_VAR_SYNC 0 +#endif + +// Oversampling Mode +// <0=>16 Oversampling +// <1=>8 Oversampling +// Oversampling Mode in UART mode +// usart__oversampling_mode +#ifndef CONF_USART_1_OVER +#define CONF_USART_1_OVER 0 +#endif + +// Inhibit Non Ack +// <0=>The NACK is generated +// <1=>The NACK is not generated +// Inhibit Non Acknowledge +// usart__inack +#ifndef CONF_USART_1_INACK +#define CONF_USART_1_INACK 1 +#endif + +// Disable Successive NACK +// <0=>NACK is sent on the ISO line as soon as a parity error occurs +// <1=>Many parity errors generate a NACK on the ISO line +// Disable Successive NACK +// usart_dsnack +#ifndef CONF_USART_1_DSNACK +#define CONF_USART_1_DSNACK 0 +#endif + +// Inverted Data +// <0=>Data isn't inverted, nomal mode +// <1=>Data is inverted +// Inverted Data +// usart_invdata +#ifndef CONF_USART_1_INVDATA +#define CONF_USART_1_INVDATA 0 +#endif + +// Maximum Number of Automatic Iteration <0-7> +// Defines the maximum number of iterations in mode ISO7816, protocol T = 0. +// usart_max_iteration +#ifndef CONF_USART_1_MAX_ITERATION +#define CONF_USART_1_MAX_ITERATION 0 +#endif + +// Receive Line Filter enable +// whether the USART filters the receive line using a three-sample filter +// usart_receive_filter_enable +#ifndef CONF_USART_1_FILTER +#define CONF_USART_1_FILTER 0 +#endif + +// Manchester Encoder/Decoder Enable +// whether the USART Manchester Encoder/Decoder +// usart_manchester_filter_enable +#ifndef CONF_USART_1_MAN +#define CONF_USART_1_MAN 0 +#endif + +// Manchester Synchronization Mode +// <0=>The Manchester start bit is a 0 to 1 transition +// <1=>The Manchester start bit is a 1 to 0 transition +// Manchester Synchronization Mode +// usart_manchester_synchronization_mode +#ifndef CONF_USART_1_MODSYNC +#define CONF_USART_1_MODSYNC 0 +#endif + +// Start Frame Delimiter Selector +// <0=>Start frame delimiter is COMMAND or DATA SYNC +// <1=>Start frame delimiter is one bit +// Start Frame Delimiter Selector +// usart_start_frame_delimiter +#ifndef CONF_USART_1_ONEBIT +#define CONF_USART_1_ONEBIT 0 +#endif + +// Fractional Part <0-7> +// Fractional part of the baud rate if baud rate generator is in fractional mode +// usart_arch_fractional +#ifndef CONF_USART_1_FRACTIONAL +#define CONF_USART_1_FRACTIONAL 0x0 +#endif + +// Data Order +// <0=>LSB is transmitted first +// <1=>MSB is transmitted first +// Data order of the data bits in the frame +// usart_arch_msbf +#ifndef CONF_USART_1_MSBF +#define CONF_USART_1_MSBF 0 +#endif + +// + +#define CONF_USART_1_MODE 0x0 + +// Calculate BAUD register value in UART mode +#if CONF_USART1_CK_SRC < 3 +#ifndef CONF_USART_1_BAUD_CD +#define CONF_USART_1_BAUD_CD ((CONF_USART1_FREQUENCY) / CONF_USART_1_BAUD / 8 / (2 - CONF_USART_1_OVER)) +#endif +#ifndef CONF_USART_1_BAUD_FP +#define CONF_USART_1_BAUD_FP \ + ((CONF_USART1_FREQUENCY) / CONF_USART_1_BAUD / (2 - CONF_USART_1_OVER) - 8 * CONF_USART_1_BAUD_CD) +#endif +#elif CONF_USART1_CK_SRC == 3 +// No division is active. The value written in US_BRGR has no effect. +#ifndef CONF_USART_1_BAUD_CD +#define CONF_USART_1_BAUD_CD 1 +#endif +#ifndef CONF_USART_1_BAUD_FP +#define CONF_USART_1_BAUD_FP 1 +#endif +#endif + +// <<< end of configuration section >>> + +#endif // HPL_USART_CONFIG_H diff --git a/hw/bsp/same70_qmtech/hpl_xdmac_config.h b/hw/bsp/same70_qmtech/hpl_xdmac_config.h new file mode 100644 index 000000000..a3d62c6fc --- /dev/null +++ b/hw/bsp/same70_qmtech/hpl_xdmac_config.h @@ -0,0 +1,4400 @@ +/* Auto-generated config file hpl_xdmac_config.h */ +#ifndef HPL_XDMAC_CONFIG_H +#define HPL_XDMAC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +// XDMAC enable +// Indicates whether xdmac is enabled or not +// xdmac_enable +#ifndef CONF_DMA_ENABLE +#define CONF_DMA_ENABLE 0 +#endif + +// Channel 0 settings +// dmac_channel_0_settings +#ifndef CONF_DMAC_CHANNEL_0_SETTINGS +#define CONF_DMAC_CHANNEL_0_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_0 +#ifndef CONF_DMAC_BURSTSIZE_0 +#define CONF_DMAC_BURSTSIZE_0 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_0 +#ifndef CONF_DMAC_CHUNKSIZE_0 +#define CONF_DMAC_CHUNKSIZE_0 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_0 +#ifndef CONF_DMAC_BEATSIZE_0 +#define CONF_DMAC_BEATSIZE_0 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_0 +#ifndef CONF_DMAC_SRC_INTERFACE_0 +#define CONF_DMAC_SRC_INTERFACE_0 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_0 +#ifndef CONF_DMAC_DES_INTERFACE_0 +#define CONF_DMAC_DES_INTERFACE_0 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_0 +#ifndef CONF_DMAC_SRCINC_0 +#define CONF_DMAC_SRCINC_0 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_0 +#ifndef CONF_DMAC_DSTINC_0 +#define CONF_DMAC_DSTINC_0 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_0 +#ifndef CONF_DMAC_TRANS_TYPE_0 +#define CONF_DMAC_TRANS_TYPE_0 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_0 +#ifndef CONF_DMAC_TRIGSRC_0 +#define CONF_DMAC_TRIGSRC_0 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_0 == 0 +#define CONF_DMAC_TYPE_0 0 +#define CONF_DMAC_DSYNC_0 0 +#elif CONF_DMAC_TRANS_TYPE_0 == 1 +#define CONF_DMAC_TYPE_0 1 +#define CONF_DMAC_DSYNC_0 0 +#elif CONF_DMAC_TRANS_TYPE_0 == 2 +#define CONF_DMAC_TYPE_0 1 +#define CONF_DMAC_DSYNC_0 1 +#endif + +#if CONF_DMAC_TRIGSRC_0 == 0xFF +#define CONF_DMAC_SWREQ_0 1 +#else +#define CONF_DMAC_SWREQ_0 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_0_SETTINGS == 1 && CONF_DMAC_BEATSIZE_0 != 2 && ((!CONF_DMAC_SRCINC_0) || (!CONF_DMAC_DSTINC_0))) +#if (!CONF_DMAC_SRCINC_0) +#define CONF_DMAC_SRC_STRIDE_0 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_0) +#define CONF_DMAC_DES_STRIDE_0 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_0 +#define CONF_DMAC_SRC_STRIDE_0 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_0 +#define CONF_DMAC_DES_STRIDE_0 0 +#endif + +// Channel 1 settings +// dmac_channel_1_settings +#ifndef CONF_DMAC_CHANNEL_1_SETTINGS +#define CONF_DMAC_CHANNEL_1_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_1 +#ifndef CONF_DMAC_BURSTSIZE_1 +#define CONF_DMAC_BURSTSIZE_1 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_1 +#ifndef CONF_DMAC_CHUNKSIZE_1 +#define CONF_DMAC_CHUNKSIZE_1 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_1 +#ifndef CONF_DMAC_BEATSIZE_1 +#define CONF_DMAC_BEATSIZE_1 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_1 +#ifndef CONF_DMAC_SRC_INTERFACE_1 +#define CONF_DMAC_SRC_INTERFACE_1 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_1 +#ifndef CONF_DMAC_DES_INTERFACE_1 +#define CONF_DMAC_DES_INTERFACE_1 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_1 +#ifndef CONF_DMAC_SRCINC_1 +#define CONF_DMAC_SRCINC_1 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_1 +#ifndef CONF_DMAC_DSTINC_1 +#define CONF_DMAC_DSTINC_1 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_1 +#ifndef CONF_DMAC_TRANS_TYPE_1 +#define CONF_DMAC_TRANS_TYPE_1 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_1 +#ifndef CONF_DMAC_TRIGSRC_1 +#define CONF_DMAC_TRIGSRC_1 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_1 == 0 +#define CONF_DMAC_TYPE_1 0 +#define CONF_DMAC_DSYNC_1 0 +#elif CONF_DMAC_TRANS_TYPE_1 == 1 +#define CONF_DMAC_TYPE_1 1 +#define CONF_DMAC_DSYNC_1 0 +#elif CONF_DMAC_TRANS_TYPE_1 == 2 +#define CONF_DMAC_TYPE_1 1 +#define CONF_DMAC_DSYNC_1 1 +#endif + +#if CONF_DMAC_TRIGSRC_1 == 0xFF +#define CONF_DMAC_SWREQ_1 1 +#else +#define CONF_DMAC_SWREQ_1 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_1_SETTINGS == 1 && CONF_DMAC_BEATSIZE_1 != 2 && ((!CONF_DMAC_SRCINC_1) || (!CONF_DMAC_DSTINC_1))) +#if (!CONF_DMAC_SRCINC_1) +#define CONF_DMAC_SRC_STRIDE_1 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_1) +#define CONF_DMAC_DES_STRIDE_1 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_1 +#define CONF_DMAC_SRC_STRIDE_1 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_1 +#define CONF_DMAC_DES_STRIDE_1 0 +#endif + +// Channel 2 settings +// dmac_channel_2_settings +#ifndef CONF_DMAC_CHANNEL_2_SETTINGS +#define CONF_DMAC_CHANNEL_2_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_2 +#ifndef CONF_DMAC_BURSTSIZE_2 +#define CONF_DMAC_BURSTSIZE_2 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_2 +#ifndef CONF_DMAC_CHUNKSIZE_2 +#define CONF_DMAC_CHUNKSIZE_2 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_2 +#ifndef CONF_DMAC_BEATSIZE_2 +#define CONF_DMAC_BEATSIZE_2 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_2 +#ifndef CONF_DMAC_SRC_INTERFACE_2 +#define CONF_DMAC_SRC_INTERFACE_2 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_2 +#ifndef CONF_DMAC_DES_INTERFACE_2 +#define CONF_DMAC_DES_INTERFACE_2 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_2 +#ifndef CONF_DMAC_SRCINC_2 +#define CONF_DMAC_SRCINC_2 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_2 +#ifndef CONF_DMAC_DSTINC_2 +#define CONF_DMAC_DSTINC_2 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_2 +#ifndef CONF_DMAC_TRANS_TYPE_2 +#define CONF_DMAC_TRANS_TYPE_2 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_2 +#ifndef CONF_DMAC_TRIGSRC_2 +#define CONF_DMAC_TRIGSRC_2 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_2 == 0 +#define CONF_DMAC_TYPE_2 0 +#define CONF_DMAC_DSYNC_2 0 +#elif CONF_DMAC_TRANS_TYPE_2 == 1 +#define CONF_DMAC_TYPE_2 1 +#define CONF_DMAC_DSYNC_2 0 +#elif CONF_DMAC_TRANS_TYPE_2 == 2 +#define CONF_DMAC_TYPE_2 1 +#define CONF_DMAC_DSYNC_2 1 +#endif + +#if CONF_DMAC_TRIGSRC_2 == 0xFF +#define CONF_DMAC_SWREQ_2 1 +#else +#define CONF_DMAC_SWREQ_2 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_2_SETTINGS == 1 && CONF_DMAC_BEATSIZE_2 != 2 && ((!CONF_DMAC_SRCINC_2) || (!CONF_DMAC_DSTINC_2))) +#if (!CONF_DMAC_SRCINC_2) +#define CONF_DMAC_SRC_STRIDE_2 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_2) +#define CONF_DMAC_DES_STRIDE_2 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_2 +#define CONF_DMAC_SRC_STRIDE_2 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_2 +#define CONF_DMAC_DES_STRIDE_2 0 +#endif + +// Channel 3 settings +// dmac_channel_3_settings +#ifndef CONF_DMAC_CHANNEL_3_SETTINGS +#define CONF_DMAC_CHANNEL_3_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_3 +#ifndef CONF_DMAC_BURSTSIZE_3 +#define CONF_DMAC_BURSTSIZE_3 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_3 +#ifndef CONF_DMAC_CHUNKSIZE_3 +#define CONF_DMAC_CHUNKSIZE_3 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_3 +#ifndef CONF_DMAC_BEATSIZE_3 +#define CONF_DMAC_BEATSIZE_3 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_3 +#ifndef CONF_DMAC_SRC_INTERFACE_3 +#define CONF_DMAC_SRC_INTERFACE_3 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_3 +#ifndef CONF_DMAC_DES_INTERFACE_3 +#define CONF_DMAC_DES_INTERFACE_3 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_3 +#ifndef CONF_DMAC_SRCINC_3 +#define CONF_DMAC_SRCINC_3 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_3 +#ifndef CONF_DMAC_DSTINC_3 +#define CONF_DMAC_DSTINC_3 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_3 +#ifndef CONF_DMAC_TRANS_TYPE_3 +#define CONF_DMAC_TRANS_TYPE_3 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_3 +#ifndef CONF_DMAC_TRIGSRC_3 +#define CONF_DMAC_TRIGSRC_3 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_3 == 0 +#define CONF_DMAC_TYPE_3 0 +#define CONF_DMAC_DSYNC_3 0 +#elif CONF_DMAC_TRANS_TYPE_3 == 1 +#define CONF_DMAC_TYPE_3 1 +#define CONF_DMAC_DSYNC_3 0 +#elif CONF_DMAC_TRANS_TYPE_3 == 2 +#define CONF_DMAC_TYPE_3 1 +#define CONF_DMAC_DSYNC_3 1 +#endif + +#if CONF_DMAC_TRIGSRC_3 == 0xFF +#define CONF_DMAC_SWREQ_3 1 +#else +#define CONF_DMAC_SWREQ_3 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_3_SETTINGS == 1 && CONF_DMAC_BEATSIZE_3 != 2 && ((!CONF_DMAC_SRCINC_3) || (!CONF_DMAC_DSTINC_3))) +#if (!CONF_DMAC_SRCINC_3) +#define CONF_DMAC_SRC_STRIDE_3 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_3) +#define CONF_DMAC_DES_STRIDE_3 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_3 +#define CONF_DMAC_SRC_STRIDE_3 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_3 +#define CONF_DMAC_DES_STRIDE_3 0 +#endif + +// Channel 4 settings +// dmac_channel_4_settings +#ifndef CONF_DMAC_CHANNEL_4_SETTINGS +#define CONF_DMAC_CHANNEL_4_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_4 +#ifndef CONF_DMAC_BURSTSIZE_4 +#define CONF_DMAC_BURSTSIZE_4 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_4 +#ifndef CONF_DMAC_CHUNKSIZE_4 +#define CONF_DMAC_CHUNKSIZE_4 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_4 +#ifndef CONF_DMAC_BEATSIZE_4 +#define CONF_DMAC_BEATSIZE_4 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_4 +#ifndef CONF_DMAC_SRC_INTERFACE_4 +#define CONF_DMAC_SRC_INTERFACE_4 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_4 +#ifndef CONF_DMAC_DES_INTERFACE_4 +#define CONF_DMAC_DES_INTERFACE_4 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_4 +#ifndef CONF_DMAC_SRCINC_4 +#define CONF_DMAC_SRCINC_4 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_4 +#ifndef CONF_DMAC_DSTINC_4 +#define CONF_DMAC_DSTINC_4 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_4 +#ifndef CONF_DMAC_TRANS_TYPE_4 +#define CONF_DMAC_TRANS_TYPE_4 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_4 +#ifndef CONF_DMAC_TRIGSRC_4 +#define CONF_DMAC_TRIGSRC_4 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_4 == 0 +#define CONF_DMAC_TYPE_4 0 +#define CONF_DMAC_DSYNC_4 0 +#elif CONF_DMAC_TRANS_TYPE_4 == 1 +#define CONF_DMAC_TYPE_4 1 +#define CONF_DMAC_DSYNC_4 0 +#elif CONF_DMAC_TRANS_TYPE_4 == 2 +#define CONF_DMAC_TYPE_4 1 +#define CONF_DMAC_DSYNC_4 1 +#endif + +#if CONF_DMAC_TRIGSRC_4 == 0xFF +#define CONF_DMAC_SWREQ_4 1 +#else +#define CONF_DMAC_SWREQ_4 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_4_SETTINGS == 1 && CONF_DMAC_BEATSIZE_4 != 2 && ((!CONF_DMAC_SRCINC_4) || (!CONF_DMAC_DSTINC_4))) +#if (!CONF_DMAC_SRCINC_4) +#define CONF_DMAC_SRC_STRIDE_4 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_4) +#define CONF_DMAC_DES_STRIDE_4 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_4 +#define CONF_DMAC_SRC_STRIDE_4 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_4 +#define CONF_DMAC_DES_STRIDE_4 0 +#endif + +// Channel 5 settings +// dmac_channel_5_settings +#ifndef CONF_DMAC_CHANNEL_5_SETTINGS +#define CONF_DMAC_CHANNEL_5_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_5 +#ifndef CONF_DMAC_BURSTSIZE_5 +#define CONF_DMAC_BURSTSIZE_5 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_5 +#ifndef CONF_DMAC_CHUNKSIZE_5 +#define CONF_DMAC_CHUNKSIZE_5 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_5 +#ifndef CONF_DMAC_BEATSIZE_5 +#define CONF_DMAC_BEATSIZE_5 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_5 +#ifndef CONF_DMAC_SRC_INTERFACE_5 +#define CONF_DMAC_SRC_INTERFACE_5 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_5 +#ifndef CONF_DMAC_DES_INTERFACE_5 +#define CONF_DMAC_DES_INTERFACE_5 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_5 +#ifndef CONF_DMAC_SRCINC_5 +#define CONF_DMAC_SRCINC_5 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_5 +#ifndef CONF_DMAC_DSTINC_5 +#define CONF_DMAC_DSTINC_5 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_5 +#ifndef CONF_DMAC_TRANS_TYPE_5 +#define CONF_DMAC_TRANS_TYPE_5 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_5 +#ifndef CONF_DMAC_TRIGSRC_5 +#define CONF_DMAC_TRIGSRC_5 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_5 == 0 +#define CONF_DMAC_TYPE_5 0 +#define CONF_DMAC_DSYNC_5 0 +#elif CONF_DMAC_TRANS_TYPE_5 == 1 +#define CONF_DMAC_TYPE_5 1 +#define CONF_DMAC_DSYNC_5 0 +#elif CONF_DMAC_TRANS_TYPE_5 == 2 +#define CONF_DMAC_TYPE_5 1 +#define CONF_DMAC_DSYNC_5 1 +#endif + +#if CONF_DMAC_TRIGSRC_5 == 0xFF +#define CONF_DMAC_SWREQ_5 1 +#else +#define CONF_DMAC_SWREQ_5 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_5_SETTINGS == 1 && CONF_DMAC_BEATSIZE_5 != 2 && ((!CONF_DMAC_SRCINC_5) || (!CONF_DMAC_DSTINC_5))) +#if (!CONF_DMAC_SRCINC_5) +#define CONF_DMAC_SRC_STRIDE_5 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_5) +#define CONF_DMAC_DES_STRIDE_5 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_5 +#define CONF_DMAC_SRC_STRIDE_5 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_5 +#define CONF_DMAC_DES_STRIDE_5 0 +#endif + +// Channel 6 settings +// dmac_channel_6_settings +#ifndef CONF_DMAC_CHANNEL_6_SETTINGS +#define CONF_DMAC_CHANNEL_6_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_6 +#ifndef CONF_DMAC_BURSTSIZE_6 +#define CONF_DMAC_BURSTSIZE_6 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_6 +#ifndef CONF_DMAC_CHUNKSIZE_6 +#define CONF_DMAC_CHUNKSIZE_6 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_6 +#ifndef CONF_DMAC_BEATSIZE_6 +#define CONF_DMAC_BEATSIZE_6 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_6 +#ifndef CONF_DMAC_SRC_INTERFACE_6 +#define CONF_DMAC_SRC_INTERFACE_6 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_6 +#ifndef CONF_DMAC_DES_INTERFACE_6 +#define CONF_DMAC_DES_INTERFACE_6 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_6 +#ifndef CONF_DMAC_SRCINC_6 +#define CONF_DMAC_SRCINC_6 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_6 +#ifndef CONF_DMAC_DSTINC_6 +#define CONF_DMAC_DSTINC_6 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_6 +#ifndef CONF_DMAC_TRANS_TYPE_6 +#define CONF_DMAC_TRANS_TYPE_6 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_6 +#ifndef CONF_DMAC_TRIGSRC_6 +#define CONF_DMAC_TRIGSRC_6 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_6 == 0 +#define CONF_DMAC_TYPE_6 0 +#define CONF_DMAC_DSYNC_6 0 +#elif CONF_DMAC_TRANS_TYPE_6 == 1 +#define CONF_DMAC_TYPE_6 1 +#define CONF_DMAC_DSYNC_6 0 +#elif CONF_DMAC_TRANS_TYPE_6 == 2 +#define CONF_DMAC_TYPE_6 1 +#define CONF_DMAC_DSYNC_6 1 +#endif + +#if CONF_DMAC_TRIGSRC_6 == 0xFF +#define CONF_DMAC_SWREQ_6 1 +#else +#define CONF_DMAC_SWREQ_6 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_6_SETTINGS == 1 && CONF_DMAC_BEATSIZE_6 != 2 && ((!CONF_DMAC_SRCINC_6) || (!CONF_DMAC_DSTINC_6))) +#if (!CONF_DMAC_SRCINC_6) +#define CONF_DMAC_SRC_STRIDE_6 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_6) +#define CONF_DMAC_DES_STRIDE_6 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_6 +#define CONF_DMAC_SRC_STRIDE_6 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_6 +#define CONF_DMAC_DES_STRIDE_6 0 +#endif + +// Channel 7 settings +// dmac_channel_7_settings +#ifndef CONF_DMAC_CHANNEL_7_SETTINGS +#define CONF_DMAC_CHANNEL_7_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_7 +#ifndef CONF_DMAC_BURSTSIZE_7 +#define CONF_DMAC_BURSTSIZE_7 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_7 +#ifndef CONF_DMAC_CHUNKSIZE_7 +#define CONF_DMAC_CHUNKSIZE_7 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_7 +#ifndef CONF_DMAC_BEATSIZE_7 +#define CONF_DMAC_BEATSIZE_7 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_7 +#ifndef CONF_DMAC_SRC_INTERFACE_7 +#define CONF_DMAC_SRC_INTERFACE_7 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_7 +#ifndef CONF_DMAC_DES_INTERFACE_7 +#define CONF_DMAC_DES_INTERFACE_7 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_7 +#ifndef CONF_DMAC_SRCINC_7 +#define CONF_DMAC_SRCINC_7 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_7 +#ifndef CONF_DMAC_DSTINC_7 +#define CONF_DMAC_DSTINC_7 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_7 +#ifndef CONF_DMAC_TRANS_TYPE_7 +#define CONF_DMAC_TRANS_TYPE_7 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_7 +#ifndef CONF_DMAC_TRIGSRC_7 +#define CONF_DMAC_TRIGSRC_7 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_7 == 0 +#define CONF_DMAC_TYPE_7 0 +#define CONF_DMAC_DSYNC_7 0 +#elif CONF_DMAC_TRANS_TYPE_7 == 1 +#define CONF_DMAC_TYPE_7 1 +#define CONF_DMAC_DSYNC_7 0 +#elif CONF_DMAC_TRANS_TYPE_7 == 2 +#define CONF_DMAC_TYPE_7 1 +#define CONF_DMAC_DSYNC_7 1 +#endif + +#if CONF_DMAC_TRIGSRC_7 == 0xFF +#define CONF_DMAC_SWREQ_7 1 +#else +#define CONF_DMAC_SWREQ_7 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_7_SETTINGS == 1 && CONF_DMAC_BEATSIZE_7 != 2 && ((!CONF_DMAC_SRCINC_7) || (!CONF_DMAC_DSTINC_7))) +#if (!CONF_DMAC_SRCINC_7) +#define CONF_DMAC_SRC_STRIDE_7 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_7) +#define CONF_DMAC_DES_STRIDE_7 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_7 +#define CONF_DMAC_SRC_STRIDE_7 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_7 +#define CONF_DMAC_DES_STRIDE_7 0 +#endif + +// Channel 8 settings +// dmac_channel_8_settings +#ifndef CONF_DMAC_CHANNEL_8_SETTINGS +#define CONF_DMAC_CHANNEL_8_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_8 +#ifndef CONF_DMAC_BURSTSIZE_8 +#define CONF_DMAC_BURSTSIZE_8 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_8 +#ifndef CONF_DMAC_CHUNKSIZE_8 +#define CONF_DMAC_CHUNKSIZE_8 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_8 +#ifndef CONF_DMAC_BEATSIZE_8 +#define CONF_DMAC_BEATSIZE_8 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_8 +#ifndef CONF_DMAC_SRC_INTERFACE_8 +#define CONF_DMAC_SRC_INTERFACE_8 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_8 +#ifndef CONF_DMAC_DES_INTERFACE_8 +#define CONF_DMAC_DES_INTERFACE_8 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_8 +#ifndef CONF_DMAC_SRCINC_8 +#define CONF_DMAC_SRCINC_8 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_8 +#ifndef CONF_DMAC_DSTINC_8 +#define CONF_DMAC_DSTINC_8 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_8 +#ifndef CONF_DMAC_TRANS_TYPE_8 +#define CONF_DMAC_TRANS_TYPE_8 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_8 +#ifndef CONF_DMAC_TRIGSRC_8 +#define CONF_DMAC_TRIGSRC_8 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_8 == 0 +#define CONF_DMAC_TYPE_8 0 +#define CONF_DMAC_DSYNC_8 0 +#elif CONF_DMAC_TRANS_TYPE_8 == 1 +#define CONF_DMAC_TYPE_8 1 +#define CONF_DMAC_DSYNC_8 0 +#elif CONF_DMAC_TRANS_TYPE_8 == 2 +#define CONF_DMAC_TYPE_8 1 +#define CONF_DMAC_DSYNC_8 1 +#endif + +#if CONF_DMAC_TRIGSRC_8 == 0xFF +#define CONF_DMAC_SWREQ_8 1 +#else +#define CONF_DMAC_SWREQ_8 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_8_SETTINGS == 1 && CONF_DMAC_BEATSIZE_8 != 2 && ((!CONF_DMAC_SRCINC_8) || (!CONF_DMAC_DSTINC_8))) +#if (!CONF_DMAC_SRCINC_8) +#define CONF_DMAC_SRC_STRIDE_8 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_8) +#define CONF_DMAC_DES_STRIDE_8 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_8 +#define CONF_DMAC_SRC_STRIDE_8 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_8 +#define CONF_DMAC_DES_STRIDE_8 0 +#endif + +// Channel 9 settings +// dmac_channel_9_settings +#ifndef CONF_DMAC_CHANNEL_9_SETTINGS +#define CONF_DMAC_CHANNEL_9_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_9 +#ifndef CONF_DMAC_BURSTSIZE_9 +#define CONF_DMAC_BURSTSIZE_9 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_9 +#ifndef CONF_DMAC_CHUNKSIZE_9 +#define CONF_DMAC_CHUNKSIZE_9 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_9 +#ifndef CONF_DMAC_BEATSIZE_9 +#define CONF_DMAC_BEATSIZE_9 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_9 +#ifndef CONF_DMAC_SRC_INTERFACE_9 +#define CONF_DMAC_SRC_INTERFACE_9 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_9 +#ifndef CONF_DMAC_DES_INTERFACE_9 +#define CONF_DMAC_DES_INTERFACE_9 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_9 +#ifndef CONF_DMAC_SRCINC_9 +#define CONF_DMAC_SRCINC_9 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_9 +#ifndef CONF_DMAC_DSTINC_9 +#define CONF_DMAC_DSTINC_9 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_9 +#ifndef CONF_DMAC_TRANS_TYPE_9 +#define CONF_DMAC_TRANS_TYPE_9 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_9 +#ifndef CONF_DMAC_TRIGSRC_9 +#define CONF_DMAC_TRIGSRC_9 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_9 == 0 +#define CONF_DMAC_TYPE_9 0 +#define CONF_DMAC_DSYNC_9 0 +#elif CONF_DMAC_TRANS_TYPE_9 == 1 +#define CONF_DMAC_TYPE_9 1 +#define CONF_DMAC_DSYNC_9 0 +#elif CONF_DMAC_TRANS_TYPE_9 == 2 +#define CONF_DMAC_TYPE_9 1 +#define CONF_DMAC_DSYNC_9 1 +#endif + +#if CONF_DMAC_TRIGSRC_9 == 0xFF +#define CONF_DMAC_SWREQ_9 1 +#else +#define CONF_DMAC_SWREQ_9 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_9_SETTINGS == 1 && CONF_DMAC_BEATSIZE_9 != 2 && ((!CONF_DMAC_SRCINC_9) || (!CONF_DMAC_DSTINC_9))) +#if (!CONF_DMAC_SRCINC_9) +#define CONF_DMAC_SRC_STRIDE_9 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_9) +#define CONF_DMAC_DES_STRIDE_9 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_9 +#define CONF_DMAC_SRC_STRIDE_9 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_9 +#define CONF_DMAC_DES_STRIDE_9 0 +#endif + +// Channel 10 settings +// dmac_channel_10_settings +#ifndef CONF_DMAC_CHANNEL_10_SETTINGS +#define CONF_DMAC_CHANNEL_10_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_10 +#ifndef CONF_DMAC_BURSTSIZE_10 +#define CONF_DMAC_BURSTSIZE_10 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_10 +#ifndef CONF_DMAC_CHUNKSIZE_10 +#define CONF_DMAC_CHUNKSIZE_10 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_10 +#ifndef CONF_DMAC_BEATSIZE_10 +#define CONF_DMAC_BEATSIZE_10 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_10 +#ifndef CONF_DMAC_SRC_INTERFACE_10 +#define CONF_DMAC_SRC_INTERFACE_10 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_10 +#ifndef CONF_DMAC_DES_INTERFACE_10 +#define CONF_DMAC_DES_INTERFACE_10 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_10 +#ifndef CONF_DMAC_SRCINC_10 +#define CONF_DMAC_SRCINC_10 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_10 +#ifndef CONF_DMAC_DSTINC_10 +#define CONF_DMAC_DSTINC_10 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_10 +#ifndef CONF_DMAC_TRANS_TYPE_10 +#define CONF_DMAC_TRANS_TYPE_10 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_10 +#ifndef CONF_DMAC_TRIGSRC_10 +#define CONF_DMAC_TRIGSRC_10 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_10 == 0 +#define CONF_DMAC_TYPE_10 0 +#define CONF_DMAC_DSYNC_10 0 +#elif CONF_DMAC_TRANS_TYPE_10 == 1 +#define CONF_DMAC_TYPE_10 1 +#define CONF_DMAC_DSYNC_10 0 +#elif CONF_DMAC_TRANS_TYPE_10 == 2 +#define CONF_DMAC_TYPE_10 1 +#define CONF_DMAC_DSYNC_10 1 +#endif + +#if CONF_DMAC_TRIGSRC_10 == 0xFF +#define CONF_DMAC_SWREQ_10 1 +#else +#define CONF_DMAC_SWREQ_10 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_10_SETTINGS == 1 && CONF_DMAC_BEATSIZE_10 != 2 \ + && ((!CONF_DMAC_SRCINC_10) || (!CONF_DMAC_DSTINC_10))) +#if (!CONF_DMAC_SRCINC_10) +#define CONF_DMAC_SRC_STRIDE_10 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_10) +#define CONF_DMAC_DES_STRIDE_10 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_10 +#define CONF_DMAC_SRC_STRIDE_10 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_10 +#define CONF_DMAC_DES_STRIDE_10 0 +#endif + +// Channel 11 settings +// dmac_channel_11_settings +#ifndef CONF_DMAC_CHANNEL_11_SETTINGS +#define CONF_DMAC_CHANNEL_11_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_11 +#ifndef CONF_DMAC_BURSTSIZE_11 +#define CONF_DMAC_BURSTSIZE_11 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_11 +#ifndef CONF_DMAC_CHUNKSIZE_11 +#define CONF_DMAC_CHUNKSIZE_11 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_11 +#ifndef CONF_DMAC_BEATSIZE_11 +#define CONF_DMAC_BEATSIZE_11 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_11 +#ifndef CONF_DMAC_SRC_INTERFACE_11 +#define CONF_DMAC_SRC_INTERFACE_11 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_11 +#ifndef CONF_DMAC_DES_INTERFACE_11 +#define CONF_DMAC_DES_INTERFACE_11 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_11 +#ifndef CONF_DMAC_SRCINC_11 +#define CONF_DMAC_SRCINC_11 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_11 +#ifndef CONF_DMAC_DSTINC_11 +#define CONF_DMAC_DSTINC_11 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_11 +#ifndef CONF_DMAC_TRANS_TYPE_11 +#define CONF_DMAC_TRANS_TYPE_11 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_11 +#ifndef CONF_DMAC_TRIGSRC_11 +#define CONF_DMAC_TRIGSRC_11 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_11 == 0 +#define CONF_DMAC_TYPE_11 0 +#define CONF_DMAC_DSYNC_11 0 +#elif CONF_DMAC_TRANS_TYPE_11 == 1 +#define CONF_DMAC_TYPE_11 1 +#define CONF_DMAC_DSYNC_11 0 +#elif CONF_DMAC_TRANS_TYPE_11 == 2 +#define CONF_DMAC_TYPE_11 1 +#define CONF_DMAC_DSYNC_11 1 +#endif + +#if CONF_DMAC_TRIGSRC_11 == 0xFF +#define CONF_DMAC_SWREQ_11 1 +#else +#define CONF_DMAC_SWREQ_11 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_11_SETTINGS == 1 && CONF_DMAC_BEATSIZE_11 != 2 \ + && ((!CONF_DMAC_SRCINC_11) || (!CONF_DMAC_DSTINC_11))) +#if (!CONF_DMAC_SRCINC_11) +#define CONF_DMAC_SRC_STRIDE_11 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_11) +#define CONF_DMAC_DES_STRIDE_11 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_11 +#define CONF_DMAC_SRC_STRIDE_11 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_11 +#define CONF_DMAC_DES_STRIDE_11 0 +#endif + +// Channel 12 settings +// dmac_channel_12_settings +#ifndef CONF_DMAC_CHANNEL_12_SETTINGS +#define CONF_DMAC_CHANNEL_12_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_12 +#ifndef CONF_DMAC_BURSTSIZE_12 +#define CONF_DMAC_BURSTSIZE_12 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_12 +#ifndef CONF_DMAC_CHUNKSIZE_12 +#define CONF_DMAC_CHUNKSIZE_12 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_12 +#ifndef CONF_DMAC_BEATSIZE_12 +#define CONF_DMAC_BEATSIZE_12 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_12 +#ifndef CONF_DMAC_SRC_INTERFACE_12 +#define CONF_DMAC_SRC_INTERFACE_12 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_12 +#ifndef CONF_DMAC_DES_INTERFACE_12 +#define CONF_DMAC_DES_INTERFACE_12 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_12 +#ifndef CONF_DMAC_SRCINC_12 +#define CONF_DMAC_SRCINC_12 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_12 +#ifndef CONF_DMAC_DSTINC_12 +#define CONF_DMAC_DSTINC_12 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_12 +#ifndef CONF_DMAC_TRANS_TYPE_12 +#define CONF_DMAC_TRANS_TYPE_12 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_12 +#ifndef CONF_DMAC_TRIGSRC_12 +#define CONF_DMAC_TRIGSRC_12 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_12 == 0 +#define CONF_DMAC_TYPE_12 0 +#define CONF_DMAC_DSYNC_12 0 +#elif CONF_DMAC_TRANS_TYPE_12 == 1 +#define CONF_DMAC_TYPE_12 1 +#define CONF_DMAC_DSYNC_12 0 +#elif CONF_DMAC_TRANS_TYPE_12 == 2 +#define CONF_DMAC_TYPE_12 1 +#define CONF_DMAC_DSYNC_12 1 +#endif + +#if CONF_DMAC_TRIGSRC_12 == 0xFF +#define CONF_DMAC_SWREQ_12 1 +#else +#define CONF_DMAC_SWREQ_12 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_12_SETTINGS == 1 && CONF_DMAC_BEATSIZE_12 != 2 \ + && ((!CONF_DMAC_SRCINC_12) || (!CONF_DMAC_DSTINC_12))) +#if (!CONF_DMAC_SRCINC_12) +#define CONF_DMAC_SRC_STRIDE_12 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_12) +#define CONF_DMAC_DES_STRIDE_12 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_12 +#define CONF_DMAC_SRC_STRIDE_12 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_12 +#define CONF_DMAC_DES_STRIDE_12 0 +#endif + +// Channel 13 settings +// dmac_channel_13_settings +#ifndef CONF_DMAC_CHANNEL_13_SETTINGS +#define CONF_DMAC_CHANNEL_13_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_13 +#ifndef CONF_DMAC_BURSTSIZE_13 +#define CONF_DMAC_BURSTSIZE_13 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_13 +#ifndef CONF_DMAC_CHUNKSIZE_13 +#define CONF_DMAC_CHUNKSIZE_13 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_13 +#ifndef CONF_DMAC_BEATSIZE_13 +#define CONF_DMAC_BEATSIZE_13 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_13 +#ifndef CONF_DMAC_SRC_INTERFACE_13 +#define CONF_DMAC_SRC_INTERFACE_13 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_13 +#ifndef CONF_DMAC_DES_INTERFACE_13 +#define CONF_DMAC_DES_INTERFACE_13 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_13 +#ifndef CONF_DMAC_SRCINC_13 +#define CONF_DMAC_SRCINC_13 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_13 +#ifndef CONF_DMAC_DSTINC_13 +#define CONF_DMAC_DSTINC_13 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_13 +#ifndef CONF_DMAC_TRANS_TYPE_13 +#define CONF_DMAC_TRANS_TYPE_13 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_13 +#ifndef CONF_DMAC_TRIGSRC_13 +#define CONF_DMAC_TRIGSRC_13 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_13 == 0 +#define CONF_DMAC_TYPE_13 0 +#define CONF_DMAC_DSYNC_13 0 +#elif CONF_DMAC_TRANS_TYPE_13 == 1 +#define CONF_DMAC_TYPE_13 1 +#define CONF_DMAC_DSYNC_13 0 +#elif CONF_DMAC_TRANS_TYPE_13 == 2 +#define CONF_DMAC_TYPE_13 1 +#define CONF_DMAC_DSYNC_13 1 +#endif + +#if CONF_DMAC_TRIGSRC_13 == 0xFF +#define CONF_DMAC_SWREQ_13 1 +#else +#define CONF_DMAC_SWREQ_13 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_13_SETTINGS == 1 && CONF_DMAC_BEATSIZE_13 != 2 \ + && ((!CONF_DMAC_SRCINC_13) || (!CONF_DMAC_DSTINC_13))) +#if (!CONF_DMAC_SRCINC_13) +#define CONF_DMAC_SRC_STRIDE_13 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_13) +#define CONF_DMAC_DES_STRIDE_13 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_13 +#define CONF_DMAC_SRC_STRIDE_13 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_13 +#define CONF_DMAC_DES_STRIDE_13 0 +#endif + +// Channel 14 settings +// dmac_channel_14_settings +#ifndef CONF_DMAC_CHANNEL_14_SETTINGS +#define CONF_DMAC_CHANNEL_14_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_14 +#ifndef CONF_DMAC_BURSTSIZE_14 +#define CONF_DMAC_BURSTSIZE_14 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_14 +#ifndef CONF_DMAC_CHUNKSIZE_14 +#define CONF_DMAC_CHUNKSIZE_14 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_14 +#ifndef CONF_DMAC_BEATSIZE_14 +#define CONF_DMAC_BEATSIZE_14 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_14 +#ifndef CONF_DMAC_SRC_INTERFACE_14 +#define CONF_DMAC_SRC_INTERFACE_14 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_14 +#ifndef CONF_DMAC_DES_INTERFACE_14 +#define CONF_DMAC_DES_INTERFACE_14 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_14 +#ifndef CONF_DMAC_SRCINC_14 +#define CONF_DMAC_SRCINC_14 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_14 +#ifndef CONF_DMAC_DSTINC_14 +#define CONF_DMAC_DSTINC_14 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_14 +#ifndef CONF_DMAC_TRANS_TYPE_14 +#define CONF_DMAC_TRANS_TYPE_14 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_14 +#ifndef CONF_DMAC_TRIGSRC_14 +#define CONF_DMAC_TRIGSRC_14 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_14 == 0 +#define CONF_DMAC_TYPE_14 0 +#define CONF_DMAC_DSYNC_14 0 +#elif CONF_DMAC_TRANS_TYPE_14 == 1 +#define CONF_DMAC_TYPE_14 1 +#define CONF_DMAC_DSYNC_14 0 +#elif CONF_DMAC_TRANS_TYPE_14 == 2 +#define CONF_DMAC_TYPE_14 1 +#define CONF_DMAC_DSYNC_14 1 +#endif + +#if CONF_DMAC_TRIGSRC_14 == 0xFF +#define CONF_DMAC_SWREQ_14 1 +#else +#define CONF_DMAC_SWREQ_14 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_14_SETTINGS == 1 && CONF_DMAC_BEATSIZE_14 != 2 \ + && ((!CONF_DMAC_SRCINC_14) || (!CONF_DMAC_DSTINC_14))) +#if (!CONF_DMAC_SRCINC_14) +#define CONF_DMAC_SRC_STRIDE_14 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_14) +#define CONF_DMAC_DES_STRIDE_14 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_14 +#define CONF_DMAC_SRC_STRIDE_14 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_14 +#define CONF_DMAC_DES_STRIDE_14 0 +#endif + +// Channel 15 settings +// dmac_channel_15_settings +#ifndef CONF_DMAC_CHANNEL_15_SETTINGS +#define CONF_DMAC_CHANNEL_15_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_15 +#ifndef CONF_DMAC_BURSTSIZE_15 +#define CONF_DMAC_BURSTSIZE_15 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_15 +#ifndef CONF_DMAC_CHUNKSIZE_15 +#define CONF_DMAC_CHUNKSIZE_15 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_15 +#ifndef CONF_DMAC_BEATSIZE_15 +#define CONF_DMAC_BEATSIZE_15 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_15 +#ifndef CONF_DMAC_SRC_INTERFACE_15 +#define CONF_DMAC_SRC_INTERFACE_15 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_15 +#ifndef CONF_DMAC_DES_INTERFACE_15 +#define CONF_DMAC_DES_INTERFACE_15 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_15 +#ifndef CONF_DMAC_SRCINC_15 +#define CONF_DMAC_SRCINC_15 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_15 +#ifndef CONF_DMAC_DSTINC_15 +#define CONF_DMAC_DSTINC_15 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_15 +#ifndef CONF_DMAC_TRANS_TYPE_15 +#define CONF_DMAC_TRANS_TYPE_15 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_15 +#ifndef CONF_DMAC_TRIGSRC_15 +#define CONF_DMAC_TRIGSRC_15 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_15 == 0 +#define CONF_DMAC_TYPE_15 0 +#define CONF_DMAC_DSYNC_15 0 +#elif CONF_DMAC_TRANS_TYPE_15 == 1 +#define CONF_DMAC_TYPE_15 1 +#define CONF_DMAC_DSYNC_15 0 +#elif CONF_DMAC_TRANS_TYPE_15 == 2 +#define CONF_DMAC_TYPE_15 1 +#define CONF_DMAC_DSYNC_15 1 +#endif + +#if CONF_DMAC_TRIGSRC_15 == 0xFF +#define CONF_DMAC_SWREQ_15 1 +#else +#define CONF_DMAC_SWREQ_15 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_15_SETTINGS == 1 && CONF_DMAC_BEATSIZE_15 != 2 \ + && ((!CONF_DMAC_SRCINC_15) || (!CONF_DMAC_DSTINC_15))) +#if (!CONF_DMAC_SRCINC_15) +#define CONF_DMAC_SRC_STRIDE_15 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_15) +#define CONF_DMAC_DES_STRIDE_15 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_15 +#define CONF_DMAC_SRC_STRIDE_15 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_15 +#define CONF_DMAC_DES_STRIDE_15 0 +#endif + +// Channel 16 settings +// dmac_channel_16_settings +#ifndef CONF_DMAC_CHANNEL_16_SETTINGS +#define CONF_DMAC_CHANNEL_16_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_16 +#ifndef CONF_DMAC_BURSTSIZE_16 +#define CONF_DMAC_BURSTSIZE_16 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_16 +#ifndef CONF_DMAC_CHUNKSIZE_16 +#define CONF_DMAC_CHUNKSIZE_16 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_16 +#ifndef CONF_DMAC_BEATSIZE_16 +#define CONF_DMAC_BEATSIZE_16 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_16 +#ifndef CONF_DMAC_SRC_INTERFACE_16 +#define CONF_DMAC_SRC_INTERFACE_16 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_16 +#ifndef CONF_DMAC_DES_INTERFACE_16 +#define CONF_DMAC_DES_INTERFACE_16 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_16 +#ifndef CONF_DMAC_SRCINC_16 +#define CONF_DMAC_SRCINC_16 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_16 +#ifndef CONF_DMAC_DSTINC_16 +#define CONF_DMAC_DSTINC_16 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_16 +#ifndef CONF_DMAC_TRANS_TYPE_16 +#define CONF_DMAC_TRANS_TYPE_16 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_16 +#ifndef CONF_DMAC_TRIGSRC_16 +#define CONF_DMAC_TRIGSRC_16 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_16 == 0 +#define CONF_DMAC_TYPE_16 0 +#define CONF_DMAC_DSYNC_16 0 +#elif CONF_DMAC_TRANS_TYPE_16 == 1 +#define CONF_DMAC_TYPE_16 1 +#define CONF_DMAC_DSYNC_16 0 +#elif CONF_DMAC_TRANS_TYPE_16 == 2 +#define CONF_DMAC_TYPE_16 1 +#define CONF_DMAC_DSYNC_16 1 +#endif + +#if CONF_DMAC_TRIGSRC_16 == 0xFF +#define CONF_DMAC_SWREQ_16 1 +#else +#define CONF_DMAC_SWREQ_16 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_16_SETTINGS == 1 && CONF_DMAC_BEATSIZE_16 != 2 \ + && ((!CONF_DMAC_SRCINC_16) || (!CONF_DMAC_DSTINC_16))) +#if (!CONF_DMAC_SRCINC_16) +#define CONF_DMAC_SRC_STRIDE_16 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_16) +#define CONF_DMAC_DES_STRIDE_16 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_16 +#define CONF_DMAC_SRC_STRIDE_16 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_16 +#define CONF_DMAC_DES_STRIDE_16 0 +#endif + +// Channel 17 settings +// dmac_channel_17_settings +#ifndef CONF_DMAC_CHANNEL_17_SETTINGS +#define CONF_DMAC_CHANNEL_17_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_17 +#ifndef CONF_DMAC_BURSTSIZE_17 +#define CONF_DMAC_BURSTSIZE_17 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_17 +#ifndef CONF_DMAC_CHUNKSIZE_17 +#define CONF_DMAC_CHUNKSIZE_17 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_17 +#ifndef CONF_DMAC_BEATSIZE_17 +#define CONF_DMAC_BEATSIZE_17 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_17 +#ifndef CONF_DMAC_SRC_INTERFACE_17 +#define CONF_DMAC_SRC_INTERFACE_17 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_17 +#ifndef CONF_DMAC_DES_INTERFACE_17 +#define CONF_DMAC_DES_INTERFACE_17 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_17 +#ifndef CONF_DMAC_SRCINC_17 +#define CONF_DMAC_SRCINC_17 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_17 +#ifndef CONF_DMAC_DSTINC_17 +#define CONF_DMAC_DSTINC_17 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_17 +#ifndef CONF_DMAC_TRANS_TYPE_17 +#define CONF_DMAC_TRANS_TYPE_17 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_17 +#ifndef CONF_DMAC_TRIGSRC_17 +#define CONF_DMAC_TRIGSRC_17 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_17 == 0 +#define CONF_DMAC_TYPE_17 0 +#define CONF_DMAC_DSYNC_17 0 +#elif CONF_DMAC_TRANS_TYPE_17 == 1 +#define CONF_DMAC_TYPE_17 1 +#define CONF_DMAC_DSYNC_17 0 +#elif CONF_DMAC_TRANS_TYPE_17 == 2 +#define CONF_DMAC_TYPE_17 1 +#define CONF_DMAC_DSYNC_17 1 +#endif + +#if CONF_DMAC_TRIGSRC_17 == 0xFF +#define CONF_DMAC_SWREQ_17 1 +#else +#define CONF_DMAC_SWREQ_17 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_17_SETTINGS == 1 && CONF_DMAC_BEATSIZE_17 != 2 \ + && ((!CONF_DMAC_SRCINC_17) || (!CONF_DMAC_DSTINC_17))) +#if (!CONF_DMAC_SRCINC_17) +#define CONF_DMAC_SRC_STRIDE_17 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_17) +#define CONF_DMAC_DES_STRIDE_17 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_17 +#define CONF_DMAC_SRC_STRIDE_17 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_17 +#define CONF_DMAC_DES_STRIDE_17 0 +#endif + +// Channel 18 settings +// dmac_channel_18_settings +#ifndef CONF_DMAC_CHANNEL_18_SETTINGS +#define CONF_DMAC_CHANNEL_18_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_18 +#ifndef CONF_DMAC_BURSTSIZE_18 +#define CONF_DMAC_BURSTSIZE_18 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_18 +#ifndef CONF_DMAC_CHUNKSIZE_18 +#define CONF_DMAC_CHUNKSIZE_18 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_18 +#ifndef CONF_DMAC_BEATSIZE_18 +#define CONF_DMAC_BEATSIZE_18 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_18 +#ifndef CONF_DMAC_SRC_INTERFACE_18 +#define CONF_DMAC_SRC_INTERFACE_18 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_18 +#ifndef CONF_DMAC_DES_INTERFACE_18 +#define CONF_DMAC_DES_INTERFACE_18 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_18 +#ifndef CONF_DMAC_SRCINC_18 +#define CONF_DMAC_SRCINC_18 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_18 +#ifndef CONF_DMAC_DSTINC_18 +#define CONF_DMAC_DSTINC_18 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_18 +#ifndef CONF_DMAC_TRANS_TYPE_18 +#define CONF_DMAC_TRANS_TYPE_18 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_18 +#ifndef CONF_DMAC_TRIGSRC_18 +#define CONF_DMAC_TRIGSRC_18 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_18 == 0 +#define CONF_DMAC_TYPE_18 0 +#define CONF_DMAC_DSYNC_18 0 +#elif CONF_DMAC_TRANS_TYPE_18 == 1 +#define CONF_DMAC_TYPE_18 1 +#define CONF_DMAC_DSYNC_18 0 +#elif CONF_DMAC_TRANS_TYPE_18 == 2 +#define CONF_DMAC_TYPE_18 1 +#define CONF_DMAC_DSYNC_18 1 +#endif + +#if CONF_DMAC_TRIGSRC_18 == 0xFF +#define CONF_DMAC_SWREQ_18 1 +#else +#define CONF_DMAC_SWREQ_18 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_18_SETTINGS == 1 && CONF_DMAC_BEATSIZE_18 != 2 \ + && ((!CONF_DMAC_SRCINC_18) || (!CONF_DMAC_DSTINC_18))) +#if (!CONF_DMAC_SRCINC_18) +#define CONF_DMAC_SRC_STRIDE_18 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_18) +#define CONF_DMAC_DES_STRIDE_18 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_18 +#define CONF_DMAC_SRC_STRIDE_18 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_18 +#define CONF_DMAC_DES_STRIDE_18 0 +#endif + +// Channel 19 settings +// dmac_channel_19_settings +#ifndef CONF_DMAC_CHANNEL_19_SETTINGS +#define CONF_DMAC_CHANNEL_19_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_19 +#ifndef CONF_DMAC_BURSTSIZE_19 +#define CONF_DMAC_BURSTSIZE_19 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_19 +#ifndef CONF_DMAC_CHUNKSIZE_19 +#define CONF_DMAC_CHUNKSIZE_19 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_19 +#ifndef CONF_DMAC_BEATSIZE_19 +#define CONF_DMAC_BEATSIZE_19 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_19 +#ifndef CONF_DMAC_SRC_INTERFACE_19 +#define CONF_DMAC_SRC_INTERFACE_19 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_19 +#ifndef CONF_DMAC_DES_INTERFACE_19 +#define CONF_DMAC_DES_INTERFACE_19 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_19 +#ifndef CONF_DMAC_SRCINC_19 +#define CONF_DMAC_SRCINC_19 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_19 +#ifndef CONF_DMAC_DSTINC_19 +#define CONF_DMAC_DSTINC_19 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_19 +#ifndef CONF_DMAC_TRANS_TYPE_19 +#define CONF_DMAC_TRANS_TYPE_19 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_19 +#ifndef CONF_DMAC_TRIGSRC_19 +#define CONF_DMAC_TRIGSRC_19 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_19 == 0 +#define CONF_DMAC_TYPE_19 0 +#define CONF_DMAC_DSYNC_19 0 +#elif CONF_DMAC_TRANS_TYPE_19 == 1 +#define CONF_DMAC_TYPE_19 1 +#define CONF_DMAC_DSYNC_19 0 +#elif CONF_DMAC_TRANS_TYPE_19 == 2 +#define CONF_DMAC_TYPE_19 1 +#define CONF_DMAC_DSYNC_19 1 +#endif + +#if CONF_DMAC_TRIGSRC_19 == 0xFF +#define CONF_DMAC_SWREQ_19 1 +#else +#define CONF_DMAC_SWREQ_19 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_19_SETTINGS == 1 && CONF_DMAC_BEATSIZE_19 != 2 \ + && ((!CONF_DMAC_SRCINC_19) || (!CONF_DMAC_DSTINC_19))) +#if (!CONF_DMAC_SRCINC_19) +#define CONF_DMAC_SRC_STRIDE_19 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_19) +#define CONF_DMAC_DES_STRIDE_19 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_19 +#define CONF_DMAC_SRC_STRIDE_19 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_19 +#define CONF_DMAC_DES_STRIDE_19 0 +#endif + +// Channel 20 settings +// dmac_channel_20_settings +#ifndef CONF_DMAC_CHANNEL_20_SETTINGS +#define CONF_DMAC_CHANNEL_20_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_20 +#ifndef CONF_DMAC_BURSTSIZE_20 +#define CONF_DMAC_BURSTSIZE_20 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_20 +#ifndef CONF_DMAC_CHUNKSIZE_20 +#define CONF_DMAC_CHUNKSIZE_20 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_20 +#ifndef CONF_DMAC_BEATSIZE_20 +#define CONF_DMAC_BEATSIZE_20 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_20 +#ifndef CONF_DMAC_SRC_INTERFACE_20 +#define CONF_DMAC_SRC_INTERFACE_20 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_20 +#ifndef CONF_DMAC_DES_INTERFACE_20 +#define CONF_DMAC_DES_INTERFACE_20 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_20 +#ifndef CONF_DMAC_SRCINC_20 +#define CONF_DMAC_SRCINC_20 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_20 +#ifndef CONF_DMAC_DSTINC_20 +#define CONF_DMAC_DSTINC_20 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_20 +#ifndef CONF_DMAC_TRANS_TYPE_20 +#define CONF_DMAC_TRANS_TYPE_20 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_20 +#ifndef CONF_DMAC_TRIGSRC_20 +#define CONF_DMAC_TRIGSRC_20 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_20 == 0 +#define CONF_DMAC_TYPE_20 0 +#define CONF_DMAC_DSYNC_20 0 +#elif CONF_DMAC_TRANS_TYPE_20 == 1 +#define CONF_DMAC_TYPE_20 1 +#define CONF_DMAC_DSYNC_20 0 +#elif CONF_DMAC_TRANS_TYPE_20 == 2 +#define CONF_DMAC_TYPE_20 1 +#define CONF_DMAC_DSYNC_20 1 +#endif + +#if CONF_DMAC_TRIGSRC_20 == 0xFF +#define CONF_DMAC_SWREQ_20 1 +#else +#define CONF_DMAC_SWREQ_20 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_20_SETTINGS == 1 && CONF_DMAC_BEATSIZE_20 != 2 \ + && ((!CONF_DMAC_SRCINC_20) || (!CONF_DMAC_DSTINC_20))) +#if (!CONF_DMAC_SRCINC_20) +#define CONF_DMAC_SRC_STRIDE_20 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_20) +#define CONF_DMAC_DES_STRIDE_20 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_20 +#define CONF_DMAC_SRC_STRIDE_20 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_20 +#define CONF_DMAC_DES_STRIDE_20 0 +#endif + +// Channel 21 settings +// dmac_channel_21_settings +#ifndef CONF_DMAC_CHANNEL_21_SETTINGS +#define CONF_DMAC_CHANNEL_21_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_21 +#ifndef CONF_DMAC_BURSTSIZE_21 +#define CONF_DMAC_BURSTSIZE_21 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_21 +#ifndef CONF_DMAC_CHUNKSIZE_21 +#define CONF_DMAC_CHUNKSIZE_21 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_21 +#ifndef CONF_DMAC_BEATSIZE_21 +#define CONF_DMAC_BEATSIZE_21 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_21 +#ifndef CONF_DMAC_SRC_INTERFACE_21 +#define CONF_DMAC_SRC_INTERFACE_21 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_21 +#ifndef CONF_DMAC_DES_INTERFACE_21 +#define CONF_DMAC_DES_INTERFACE_21 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_21 +#ifndef CONF_DMAC_SRCINC_21 +#define CONF_DMAC_SRCINC_21 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_21 +#ifndef CONF_DMAC_DSTINC_21 +#define CONF_DMAC_DSTINC_21 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_21 +#ifndef CONF_DMAC_TRANS_TYPE_21 +#define CONF_DMAC_TRANS_TYPE_21 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_21 +#ifndef CONF_DMAC_TRIGSRC_21 +#define CONF_DMAC_TRIGSRC_21 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_21 == 0 +#define CONF_DMAC_TYPE_21 0 +#define CONF_DMAC_DSYNC_21 0 +#elif CONF_DMAC_TRANS_TYPE_21 == 1 +#define CONF_DMAC_TYPE_21 1 +#define CONF_DMAC_DSYNC_21 0 +#elif CONF_DMAC_TRANS_TYPE_21 == 2 +#define CONF_DMAC_TYPE_21 1 +#define CONF_DMAC_DSYNC_21 1 +#endif + +#if CONF_DMAC_TRIGSRC_21 == 0xFF +#define CONF_DMAC_SWREQ_21 1 +#else +#define CONF_DMAC_SWREQ_21 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_21_SETTINGS == 1 && CONF_DMAC_BEATSIZE_21 != 2 \ + && ((!CONF_DMAC_SRCINC_21) || (!CONF_DMAC_DSTINC_21))) +#if (!CONF_DMAC_SRCINC_21) +#define CONF_DMAC_SRC_STRIDE_21 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_21) +#define CONF_DMAC_DES_STRIDE_21 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_21 +#define CONF_DMAC_SRC_STRIDE_21 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_21 +#define CONF_DMAC_DES_STRIDE_21 0 +#endif + +// Channel 22 settings +// dmac_channel_22_settings +#ifndef CONF_DMAC_CHANNEL_22_SETTINGS +#define CONF_DMAC_CHANNEL_22_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_22 +#ifndef CONF_DMAC_BURSTSIZE_22 +#define CONF_DMAC_BURSTSIZE_22 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_22 +#ifndef CONF_DMAC_CHUNKSIZE_22 +#define CONF_DMAC_CHUNKSIZE_22 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_22 +#ifndef CONF_DMAC_BEATSIZE_22 +#define CONF_DMAC_BEATSIZE_22 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_22 +#ifndef CONF_DMAC_SRC_INTERFACE_22 +#define CONF_DMAC_SRC_INTERFACE_22 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_22 +#ifndef CONF_DMAC_DES_INTERFACE_22 +#define CONF_DMAC_DES_INTERFACE_22 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_22 +#ifndef CONF_DMAC_SRCINC_22 +#define CONF_DMAC_SRCINC_22 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_22 +#ifndef CONF_DMAC_DSTINC_22 +#define CONF_DMAC_DSTINC_22 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_22 +#ifndef CONF_DMAC_TRANS_TYPE_22 +#define CONF_DMAC_TRANS_TYPE_22 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_22 +#ifndef CONF_DMAC_TRIGSRC_22 +#define CONF_DMAC_TRIGSRC_22 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_22 == 0 +#define CONF_DMAC_TYPE_22 0 +#define CONF_DMAC_DSYNC_22 0 +#elif CONF_DMAC_TRANS_TYPE_22 == 1 +#define CONF_DMAC_TYPE_22 1 +#define CONF_DMAC_DSYNC_22 0 +#elif CONF_DMAC_TRANS_TYPE_22 == 2 +#define CONF_DMAC_TYPE_22 1 +#define CONF_DMAC_DSYNC_22 1 +#endif + +#if CONF_DMAC_TRIGSRC_22 == 0xFF +#define CONF_DMAC_SWREQ_22 1 +#else +#define CONF_DMAC_SWREQ_22 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_22_SETTINGS == 1 && CONF_DMAC_BEATSIZE_22 != 2 \ + && ((!CONF_DMAC_SRCINC_22) || (!CONF_DMAC_DSTINC_22))) +#if (!CONF_DMAC_SRCINC_22) +#define CONF_DMAC_SRC_STRIDE_22 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_22) +#define CONF_DMAC_DES_STRIDE_22 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_22 +#define CONF_DMAC_SRC_STRIDE_22 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_22 +#define CONF_DMAC_DES_STRIDE_22 0 +#endif + +// Channel 23 settings +// dmac_channel_23_settings +#ifndef CONF_DMAC_CHANNEL_23_SETTINGS +#define CONF_DMAC_CHANNEL_23_SETTINGS 0 +#endif + +// Burst Size +// <0x0=> 1 burst size +// <0x1=> 4 burst size +// <0x2=> 8 burst size +// <0x3=> 16 burst size +// Define the memory burst size +// dmac_burstsize_23 +#ifndef CONF_DMAC_BURSTSIZE_23 +#define CONF_DMAC_BURSTSIZE_23 0x0 +#endif + +// Chunk Size +// <0x0=> 1 data transferred +// <0x1=> 2 data transferred +// <0x2=> 4 data transferred +// <0x3=> 8 data transferred +// <0x4=> 16 data transferred +// Define the peripheral chunk size +// dmac_chunksize_23 +#ifndef CONF_DMAC_CHUNKSIZE_23 +#define CONF_DMAC_CHUNKSIZE_23 0x0 +#endif + +// Beat Size +// <0=> 8-bit bus transfer +// <1=> 16-bit bus transfer +// <2=> 32-bit bus transfer +// Defines the size of one beat +// dmac_beatsize_23 +#ifndef CONF_DMAC_BEATSIZE_23 +#define CONF_DMAC_BEATSIZE_23 0x0 +#endif + +// Source Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is read through the system bus interface 0 or 1 +// dma_src_interface_23 +#ifndef CONF_DMAC_SRC_INTERFACE_23 +#define CONF_DMAC_SRC_INTERFACE_23 0x0 +#endif + +// Destination Interface Identifier +// <0x0=> AHB_IF0 +// <0x1=> AHB_IF1 +// Define the data is written through the system bus interface 0 or 1 +// dma_des_interface_23 +#ifndef CONF_DMAC_DES_INTERFACE_23 +#define CONF_DMAC_DES_INTERFACE_23 0x0 +#endif + +// Source Address Increment +// Indicates whether the source address incremented as beat size or not +// dmac_srcinc_23 +#ifndef CONF_DMAC_SRCINC_23 +#define CONF_DMAC_SRCINC_23 0 +#endif + +// Destination Address Increment +// Indicates whether the destination address incremented as beat size or not +// dmac_dstinc_23 +#ifndef CONF_DMAC_DSTINC_23 +#define CONF_DMAC_DSTINC_23 0 +#endif + +// Transfer Type +// <0x0=> Memory to Memory Transfer +// <0x1=> Peripheral to Memory Transfer +// <0x2=> Memory to Peripheral Transfer +// Define the data transfer type +// dma_trans_type_23 +#ifndef CONF_DMAC_TRANS_TYPE_23 +#define CONF_DMAC_TRANS_TYPE_23 0x0 +#endif + +// Trigger source +// <0xFF=> Software Trigger +// <0x00=> HSMCI TX/RX Trigger +// <0x01=> SPI0 TX Trigger +// <0x02=> SPI0 RX Trigger +// <0x03=> SPI1 TX Trigger +// <0x04=> SPI1 RX Trigger +// <0x05=> QSPI TX Trigger +// <0x06=> QSPI RX Trigger +// <0x07=> USART0 TX Trigger +// <0x08=> USART0 RX Trigger +// <0x09=> USART1 TX Trigger +// <0x0A=> USART1 RX Trigger +// <0x0B=> USART2 TX Trigger +// <0x0C=> USART2 RX Trigger +// <0x0D=> PWM0 TX Trigger +// <0x0E=> TWIHS0 TX Trigger +// <0x0F=> TWIHS0 RX Trigger +// <0x10=> TWIHS1 TX Trigger +// <0x11=> TWIHS1 RX Trigger +// <0x12=> TWIHS2 TX Trigger +// <0x13=> TWIHS2 RX Trigger +// <0x14=> UART0 TX Trigger +// <0x15=> UART0 RX Trigger +// <0x16=> UART1 TX Trigger +// <0x17=> UART1 RX Trigger +// <0x18=> UART2 TX Trigger +// <0x19=> UART2 RX Trigger +// <0x1A=> UART3 TX Trigger +// <0x1B=> UART3 RX Trigger +// <0x1C=> UART4 TX Trigger +// <0x1D=> UART4 RX Trigger +// <0x1E=> DACC TX Trigger +// <0x20=> SSC TX Trigger +// <0x21=> SSC RX Trigger +// <0x22=> PIOA RX Trigger +// <0x23=> AFEC0 RX Trigger +// <0x24=> AFEC1 RX Trigger +// <0x25=> AES TX Trigger +// <0x26=> AES RX Trigger +// <0x27=> PWM1 TX Trigger +// <0x28=> TC0 RX Trigger +// <0x29=> TC3 RX Trigger +// <0x2A=> TC6 RX Trigger +// <0x2B=> TC9 RX Trigger +// <0x2C=> I2SC0 TX Left Trigger +// <0x2D=> I2SC0 RX Left Trigger +// <0x2E=> I2SC1 TX Left Trigger +// <0x2F=> I2SC1 RX Left Trigger +// <0x30=> I2SC0 TX Right Trigger +// <0x31=> I2SC0 RX Right Trigger +// <0x32=> I2SC1 TX Right Trigger +// <0x33=> I2SC1 RX Right Trigger +// Define the DMA trigger source +// dmac_trifsrc_23 +#ifndef CONF_DMAC_TRIGSRC_23 +#define CONF_DMAC_TRIGSRC_23 0xff +#endif + +// + +#if CONF_DMAC_TRANS_TYPE_23 == 0 +#define CONF_DMAC_TYPE_23 0 +#define CONF_DMAC_DSYNC_23 0 +#elif CONF_DMAC_TRANS_TYPE_23 == 1 +#define CONF_DMAC_TYPE_23 1 +#define CONF_DMAC_DSYNC_23 0 +#elif CONF_DMAC_TRANS_TYPE_23 == 2 +#define CONF_DMAC_TYPE_23 1 +#define CONF_DMAC_DSYNC_23 1 +#endif + +#if CONF_DMAC_TRIGSRC_23 == 0xFF +#define CONF_DMAC_SWREQ_23 1 +#else +#define CONF_DMAC_SWREQ_23 0 +#endif + +/* Errata: If XDMA is used to transfer 8-bit or 16-bit data in fixed source address + * or fixed destination address mode, source and destination addresses are incremented + * by 8-bit or 16-bit. + * Workaround: The user can fix the problem by setting the source addressing mode to + * use microblock and data striding with microblock stride set to 0 and data stride set to -1. + */ +#if (CONF_DMAC_CHANNEL_23_SETTINGS == 1 && CONF_DMAC_BEATSIZE_23 != 2 \ + && ((!CONF_DMAC_SRCINC_23) || (!CONF_DMAC_DSTINC_23))) +#if (!CONF_DMAC_SRCINC_23) +#define CONF_DMAC_SRC_STRIDE_23 ((int16_t)(-1)) +#endif +#if (!CONF_DMAC_DSTINC_23) +#define CONF_DMAC_DES_STRIDE_23 ((int16_t)(-1)) +#endif +#endif + +#ifndef CONF_DMAC_SRC_STRIDE_23 +#define CONF_DMAC_SRC_STRIDE_23 0 +#endif + +#ifndef CONF_DMAC_DES_STRIDE_23 +#define CONF_DMAC_DES_STRIDE_23 0 +#endif + +// + +// <<< end of configuration section >>> + +#endif // HPL_XDMAC_CONFIG_H diff --git a/hw/bsp/same70_qmtech/peripheral_clk_config.h b/hw/bsp/same70_qmtech/peripheral_clk_config.h new file mode 100644 index 000000000..84756f5ac --- /dev/null +++ b/hw/bsp/same70_qmtech/peripheral_clk_config.h @@ -0,0 +1,126 @@ +/* Auto-generated config file peripheral_clk_config.h */ +#ifndef PERIPHERAL_CLK_CONFIG_H +#define PERIPHERAL_CLK_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +/** + * \def CONF_HCLK_FREQUENCY + * \brief HCLK's Clock frequency + */ +#ifndef CONF_HCLK_FREQUENCY +#define CONF_HCLK_FREQUENCY 300000000 +#endif + +/** + * \def CONF_FCLK_FREQUENCY + * \brief FCLK's Clock frequency + */ +#ifndef CONF_FCLK_FREQUENCY +#define CONF_FCLK_FREQUENCY 300000000 +#endif + +/** + * \def CONF_CPU_FREQUENCY + * \brief CPU's Clock frequency + */ +#ifndef CONF_CPU_FREQUENCY +#define CONF_CPU_FREQUENCY 300000000 +#endif + +/** + * \def CONF_SLCK_FREQUENCY + * \brief Slow Clock frequency + */ +#define CONF_SLCK_FREQUENCY 0 + +/** + * \def CONF_MCK_FREQUENCY + * \brief Master Clock frequency + */ +#define CONF_MCK_FREQUENCY 150000000 + +/** + * \def CONF_PCK6_FREQUENCY + * \brief Programmable Clock Controller 6 frequency + */ +#define CONF_PCK6_FREQUENCY 1714285 + +// USART Clock Settings +// USART Clock source + +// <0=> Master Clock (MCK) +// <1=> MCK / 8 for USART +// <2=> Programmable Clock Controller 4 (PMC_PCK4) +// <3=> External Clock +// This defines the clock source for the USART +// usart_clock_source +#ifndef CONF_USART1_CK_SRC +#define CONF_USART1_CK_SRC 0 +#endif + +// USART External Clock Input on SCK <1-4294967295> +// Inputs the external clock frequency on SCK +// usart_clock_freq +#ifndef CONF_USART1_SCK_FREQ +#define CONF_USART1_SCK_FREQ 10000000 +#endif + +// + +/** + * \def USART FREQUENCY + * \brief USART's Clock frequency + */ +#ifndef CONF_USART1_FREQUENCY +#define CONF_USART1_FREQUENCY 150000000 +#endif + +#ifndef CONF_SRC_USB_480M +#define CONF_SRC_USB_480M 0 +#endif + +#ifndef CONF_SRC_USB_48M +#define CONF_SRC_USB_48M 1 +#endif + +// USB Full/Low Speed Clock +// USB Clock Controller (USB_48M) +// usb_fsls_clock_source +// 48MHz clock source for low speed and full speed. +// It must be available when low speed is supported by host driver. +// It must be available when low power mode is selected. +#ifndef CONF_USBHS_FSLS_SRC +#define CONF_USBHS_FSLS_SRC CONF_SRC_USB_48M +#endif + +// USB Clock Source(Normal/Low-power Mode Selection) +// USB High Speed Clock (USB_480M) +// USB Clock Controller (USB_48M) +// usb_clock_source +// Select the clock source for USB. +// In normal mode, use "USB High Speed Clock (USB_480M)". +// In low-power mode, use "USB Clock Controller (USB_48M)". +#ifndef CONF_USBHS_SRC +#define CONF_USBHS_SRC CONF_SRC_USB_480M +#endif + +/** + * \def CONF_USBHS_FSLS_FREQUENCY + * \brief USBHS's Full/Low Speed Clock Source frequency + */ +#ifndef CONF_USBHS_FSLS_FREQUENCY +#define CONF_USBHS_FSLS_FREQUENCY 48000000 +#endif + +/** + * \def CONF_USBHS_FREQUENCY + * \brief USBHS's Selected Clock Source frequency + */ +#ifndef CONF_USBHS_FREQUENCY +#define CONF_USBHS_FREQUENCY 480000000 +#endif + +// <<< end of configuration section >>> + +#endif // PERIPHERAL_CLK_CONFIG_H diff --git a/hw/bsp/same70_qmtech/same70_qmtech.c b/hw/bsp/same70_qmtech/same70_qmtech.c new file mode 100644 index 000000000..6e6ad0602 --- /dev/null +++ b/hw/bsp/same70_qmtech/same70_qmtech.c @@ -0,0 +1,159 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019, hathach (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 "sam.h" +#include "bsp/board.h" + +#include "peripheral_clk_config.h" +#include "hpl/usart/hpl_usart_base.h" +#include "hpl/pmc/hpl_pmc.h" +#include "hal/include/hal_init.h" +#include "hal/include/hal_usart_async.h" +#include "hal/include/hal_gpio.h" + + +// You can get the board here: +// https://www.aliexpress.com/item/1005003173783268.html + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +#define LED_PIN GPIO(GPIO_PORTA, 15) + +#define BUTTON_PIN GPIO(GPIO_PORTA, 21) +#define BUTTON_STATE_ACTIVE 0 + +#define UART_TX_PIN GPIO(GPIO_PORTB, 1) +#define UART_RX_PIN GPIO(GPIO_PORTB, 0) + +static struct usart_async_descriptor edbg_com; +static uint8_t edbg_com_buffer[64]; +static volatile bool uart_busy = false; + +static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr) +{ + (void) io_descr; + uart_busy = false; +} + +//------------- IMPLEMENTATION -------------// +void board_init(void) +{ + init_mcu(); + + /* Disable Watchdog */ + hri_wdt_set_MR_WDDIS_bit(WDT); + + // LED + _pmc_enable_periph_clock(ID_PIOB); + gpio_set_pin_level(LED_PIN, false); + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_function(LED_PIN, GPIO_PIN_FUNCTION_OFF); + + // Button + _pmc_enable_periph_clock(ID_PIOA); + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); + gpio_set_pin_function(BUTTON_PIN, GPIO_PIN_FUNCTION_OFF); + + // Uart via EDBG Com + _pmc_enable_periph_clock(ID_USART1); + gpio_set_pin_function(UART_RX_PIN, MUX_PA21A_USART1_RXD1); + gpio_set_pin_function(UART_TX_PIN, MUX_PB4D_USART1_TXD1); + + usart_async_init(&edbg_com, USART1, edbg_com_buffer, sizeof(edbg_com_buffer), _usart_get_usart_async()); + usart_async_set_baud_rate(&edbg_com, CFG_BOARD_UART_BAUDRATE); + usart_async_register_callback(&edbg_com, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM); + usart_async_enable(&edbg_com); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer (samd SystemCoreClock may not correct) + SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif + + // Enable USB clock + _pmc_enable_periph_clock(ID_USBHS); + +} + +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USBHS_Handler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_set_pin_level(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + // while until previous transfer is complete + while(uart_busy) {} + uart_busy = true; + + io_write(&edbg_com.io, buf, len); + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index c9bc0cea3..cb2decf50 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -11,7 +11,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_SAMX7X # suppress following warnings from mcu driver -CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual ASF_DIR = hw/mcu/microchip/same70 diff --git a/hw/bsp/samg55xplained/board.mk b/hw/bsp/samg55xplained/board.mk index aed4de68e..deff6944c 100644 --- a/hw/bsp/samg55xplained/board.mk +++ b/hw/bsp/samg55xplained/board.mk @@ -12,7 +12,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_SAMG # suppress following warnings from mcu driver -CFLAGS += -Wno-error=undef +CFLAGS += -Wno-error=undef -Wno-error=cast-qual -Wno-error=null-dereference ASF_DIR = hw/mcu/microchip/samg55 diff --git a/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk b/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk index 81b4ecdcb..5b9acb90b 100644 --- a/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk +++ b/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAML21J18B__ +CFLAGS += -D__SAML21J18B__ -DCFG_EXAMPLE_VIDEO_READONLY SAML_VARIANT = saml21 diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.mk b/hw/bsp/saml2x/boards/saml22_feather/board.mk index 0605dca19..0adfdd62c 100644 --- a/hw/bsp/saml2x/boards/saml22_feather/board.mk +++ b/hw/bsp/saml2x/boards/saml22_feather/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAML22J18A__ +CFLAGS += -D__SAML22J18A__ -DCFG_EXAMPLE_VIDEO_READONLY SAML_VARIANT = saml22 diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk b/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk index 0605dca19..0adfdd62c 100644 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk +++ b/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -D__SAML22J18A__ +CFLAGS += -D__SAML22J18A__ -DCFG_EXAMPLE_VIDEO_READONLY SAML_VARIANT = saml22 diff --git a/hw/bsp/saml2x/family.mk b/hw/bsp/saml2x/family.mk index e0f6b2f77..bb1faeb7f 100644 --- a/hw/bsp/saml2x/family.mk +++ b/hw/bsp/saml2x/family.mk @@ -13,6 +13,9 @@ CFLAGS += \ -DCONF_OSC32K_CALIB_ENABLE=0 \ -DCFG_TUSB_MCU=OPT_MCU_SAML22 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-qual + SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ $(MCU_DIR)/gcc/gcc/startup_$(SAML_VARIANT).c \ diff --git a/hw/bsp/sltb009a/board.mk b/hw/bsp/sltb009a/board.mk index e8a24d1bd..f5c240ca2 100644 --- a/hw/bsp/sltb009a/board.mk +++ b/hw/bsp/sltb009a/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -D__STARTUP_CLEAR_BSS \ -D__START=main \ -DEFM32GG12B810F1024GM64 \ - -DCFG_TUSB_MCU=OPT_MCU_EFM32GG12 + -DCFG_TUSB_MCU=OPT_MCU_EFM32GG # mcu driver cause following warnings #CFLAGS += -Wno-error=unused-parameter @@ -24,7 +24,7 @@ LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(SILABS_FAMILY).ld SRC_C += \ $(SILABS_CMSIS)/Source/system_$(SILABS_FAMILY).c \ - src/portable/silabs/efm32/dcd_efm32.c + src/portable/synopsys/dwc2/dcd_dwc2.c SRC_S += \ $(SILABS_CMSIS)/Source/GCC/startup_$(SILABS_FAMILY).S @@ -34,12 +34,8 @@ INC += \ $(TOP)/$(SILABS_CMSIS)/Include \ $(TOP)/hw/bsp/$(BOARD) -# For TinyUSB port source -VENDOR = silabs -CHIP_FAMILY = efm32 - # For freeRTOS port source -FREERTOS_PORT = ARM_CM4 +FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = EFM32GG12B810F1024 diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk index a46c42bd6..ba291e817 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/spresense/board.mk @@ -70,4 +70,5 @@ $(BUILD)/$(PROJECT).spk: $(MKSPK) # flash flash: $(BUILD)/$(PROJECT).spk - @$(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< + @echo FLASH $< + @$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< diff --git a/hw/bsp/stm32f0/boards/stm32f070rbnucleo/board.mk b/hw/bsp/stm32f0/boards/stm32f070rbnucleo/board.mk index 9e636cd76..7c0ee40b6 100644 --- a/hw/bsp/stm32f0/boards/stm32f070rbnucleo/board.mk +++ b/hw/bsp/stm32f0/boards/stm32f070rbnucleo/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DSTM32F070xB +CFLAGS += -DSTM32F070xB -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/stm32F070rbtx_flash.ld diff --git a/hw/bsp/stm32f0/boards/stm32f072disco/board.mk b/hw/bsp/stm32f0/boards/stm32f072disco/board.mk index 2ef0ee63c..7c72d8f4c 100644 --- a/hw/bsp/stm32f0/boards/stm32f072disco/board.mk +++ b/hw/bsp/stm32f0/boards/stm32f072disco/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DSTM32F072xB +CFLAGS += -DSTM32F072xB -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/STM32F072RBTx_FLASH.ld diff --git a/hw/bsp/stm32f0/boards/stm32f072eval/board.mk b/hw/bsp/stm32f0/boards/stm32f072eval/board.mk index f7f8c84ee..b625c3ebd 100644 --- a/hw/bsp/stm32f0/boards/stm32f072eval/board.mk +++ b/hw/bsp/stm32f0/boards/stm32f072eval/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DSTM32F072xB -DLSI_VALUE=40000 +CFLAGS += -DSTM32F072xB -DLSI_VALUE=40000 -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/STM32F072VBTx_FLASH.ld diff --git a/hw/bsp/stm32f0/family.c b/hw/bsp/stm32f0/family.c index 68b924432..8de3147e2 100644 --- a/hw/bsp/stm32f0/family.c +++ b/hw/bsp/stm32f0/family.c @@ -134,7 +134,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); return len; } diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk index 08cbf5626..39831e154 100644 --- a/hw/bsp/stm32f0/family.mk +++ b/hw/bsp/stm32f0/family.mk @@ -18,7 +18,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32F0 # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ diff --git a/hw/bsp/stm32f1/boards/stm32f103_bluepill/board.mk b/hw/bsp/stm32f1/boards/stm32f103_bluepill/board.mk index 9c690ca7e..db64b3a3f 100644 --- a/hw/bsp/stm32f1/boards/stm32f103_bluepill/board.mk +++ b/hw/bsp/stm32f1/boards/stm32f103_bluepill/board.mk @@ -1,4 +1,4 @@ -CFLAGS += -DSTM32F103xB -DHSE_VALUE=8000000U +CFLAGS += -DSTM32F103xB -DHSE_VALUE=8000000U -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/STM32F103X8_FLASH.ld diff --git a/hw/bsp/stm32f207nucleo/board.mk b/hw/bsp/stm32f207nucleo/board.mk index 2b979f3d8..fa7d28399 100644 --- a/hw/bsp/stm32f207nucleo/board.mk +++ b/hw/bsp/stm32f207nucleo/board.mk @@ -21,7 +21,7 @@ CFLAGS += -Wno-error=sign-compare LD_FILE = hw/bsp/$(BOARD)/STM32F207ZGTx_FLASH.ld SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f4/boards/stm32f412nucleo/STM32F412ZGTx_FLASH.ld b/hw/bsp/stm32f4/boards/stm32f412nucleo/STM32F412ZGTx_FLASH.ld new file mode 100644 index 000000000..b00b5dbe0 --- /dev/null +++ b/hw/bsp/stm32f4/boards/stm32f412nucleo/STM32F412ZGTx_FLASH.ld @@ -0,0 +1,169 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F412ZGTx Device with +** 1024KByte FLASH, 256KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20040000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/stm32f4/boards/stm32f412nucleo/board.h b/hw/bsp/stm32f4/boards/stm32f412nucleo/board.h new file mode 100644 index 000000000..73c5f83b9 --- /dev/null +++ b/hw/bsp/stm32f4/boards/stm32f412nucleo/board.h @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_14 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 1 + +// UART Enable for STLink VCOM +#define UART_DEV USART3 +#define UART_GPIO_PORT GPIOD +#define UART_GPIO_AF GPIO_AF7_USART3 +#define UART_TX_PIN GPIO_PIN_8 +#define UART_RX_PIN GPIO_PIN_9 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void board_clock_init(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + + /* Enable Power Control clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* The voltage scaling allows optimizing the power consumption when the + * device is clocked below the maximum system frequency, to update the + * voltage scaling value regarding system frequency refer to product + * datasheet. */ + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/1000000; + RCC_OscInitStruct.PLL.PLLN = 200; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + RCC_OscInitStruct.PLL.PLLR = 2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select PLLSAI output as USB clock source */ + PeriphClkInitStruct.PLLI2S.PLLI2SM = 8; + PeriphClkInitStruct.PLLI2S.PLLI2SQ = 4; + PeriphClkInitStruct.PLLI2S.PLLI2SN = 192; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CK48; + PeriphClkInitStruct.Clk48ClockSelection = RCC_CK48CLKSOURCE_PLLI2SQ; + PeriphClkInitStruct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; + PeriphClkInitStruct.PLLI2S.PLLI2SR = 7; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + * clocks dividers */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); + + // Enable clocks for LED, Button, Uart + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_USART3_CLK_ENABLE(); +} + +static inline void board_vbus_sense_init(void) +{ + // Enable VBUS sense (B device) via pin PA9 + USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32f4/boards/stm32f412nucleo/board.mk b/hw/bsp/stm32f4/boards/stm32f412nucleo/board.mk new file mode 100644 index 000000000..50973f737 --- /dev/null +++ b/hw/bsp/stm32f4/boards/stm32f412nucleo/board.mk @@ -0,0 +1,11 @@ +CFLAGS += -DSTM32F412Zx + +LD_FILE = $(BOARD_PATH)/STM32F412ZGTx_FLASH.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f412zx.s + +# For flash-jlink target +JLINK_DEVICE = stm32f412zg + +# flash target using on-board stlink +flash: flash-stlink diff --git a/hw/bsp/stm32f4/boards/stm32f412nucleo/stm32f4xx_hal_conf.h b/hw/bsp/stm32f4/boards/stm32f412nucleo/stm32f4xx_hal_conf.h new file mode 100644 index 000000000..7864f8d5f --- /dev/null +++ b/hw/bsp/stm32f4/boards/stm32f412nucleo/stm32f4xx_hal_conf.h @@ -0,0 +1,493 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +/* #define HAL_EXTI_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +#define HAL_PWR_MODULE_ENABLED +/* #define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RCC_MODULE_ENABLED +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +// #define HAL_SPI_MODULE_ENABLED +/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +/* #define HAL_PCD_MODULE_ENABLED */ +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE (8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT (100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE (16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE (32000U) +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE (32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT (5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE (12288000U) /*!< Value of the External oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE (3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (0x0FU) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x0010) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x0011) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "stm32f4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index cf0cb2b08..82d4957e7 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -36,6 +36,11 @@ void OTG_FS_IRQHandler(void) tud_int_handler(0); } +void OTG_HS_IRQHandler(void) +{ + tud_int_handler(1); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -134,6 +139,8 @@ void board_init(void) // Enable USB OTG clock __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); +// __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + board_vbus_sense_init(); } @@ -160,7 +167,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { #ifdef UART_DEV - HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); return len; #else (void) buf; (void) len; (void) UartHandle; diff --git a/hw/bsp/stm32f4/family.mk b/hw/bsp/stm32f4/family.mk index 584d69405..9811d3371 100644 --- a/hw/bsp/stm32f4/family.mk +++ b/hw/bsp/stm32f4/family.mk @@ -21,7 +21,7 @@ CFLAGS += \ CFLAGS += -Wno-error=cast-align SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f7/boards/stm32f723disco/board.mk b/hw/bsp/stm32f7/boards/stm32f723disco/board.mk index 8f05199d0..66d9ff8fb 100644 --- a/hw/bsp/stm32f7/boards/stm32f723disco/board.mk +++ b/hw/bsp/stm32f7/boards/stm32f723disco/board.mk @@ -10,3 +10,6 @@ SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f723xx.s # flash target using on-board stlink flash: flash-stlink + +# For flash-jlink target +JLINK_DEVICE = stm32f723ie diff --git a/hw/bsp/stm32f7/boards/stm32f746nucleo/board.h b/hw/bsp/stm32f7/boards/stm32f746nucleo/board.h index 093445ede..92c109a72 100644 --- a/hw/bsp/stm32f7/boards/stm32f746nucleo/board.h +++ b/hw/bsp/stm32f7/boards/stm32f746nucleo/board.h @@ -76,6 +76,8 @@ static inline void board_clock_init(void) RCC_OscInitStruct.PLL.PLLQ = 9; HAL_RCC_OscConfig(&RCC_OscInitStruct); + // TODO need to enable usb clock source + /* Activate the OverDrive to reach the 216 MHz Frequency */ HAL_PWREx_EnableOverDrive(); diff --git a/hw/bsp/stm32f7/boards/stm32f767nucleo/board.mk b/hw/bsp/stm32f7/boards/stm32f767nucleo/board.mk index 2400a4ba7..7710619e5 100644 --- a/hw/bsp/stm32f7/boards/stm32f767nucleo/board.mk +++ b/hw/bsp/stm32f7/boards/stm32f767nucleo/board.mk @@ -8,5 +8,8 @@ CFLAGS += \ LD_FILE = $(BOARD_PATH)/STM32F767ZITx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f767xx.s +# For flash-jlink target +JLINK_DEVICE = stm32f767zi + # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index 2eb737ee3..14e3b2fd9 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -284,7 +284,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); return len; } diff --git a/hw/bsp/stm32f7/family.mk b/hw/bsp/stm32f7/family.mk index ead0c977a..8482e6dd2 100644 --- a/hw/bsp/stm32f7/family.mk +++ b/hw/bsp/stm32f7/family.mk @@ -34,7 +34,7 @@ endif CFLAGS += -Wno-error=shadow -Wno-error=cast-align SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32g4/boards/stm32g474nucleo/STM32G474RETx_FLASH.ld b/hw/bsp/stm32g4/boards/stm32g474nucleo/STM32G474RETx_FLASH.ld new file mode 100644 index 000000000..935d97c87 --- /dev/null +++ b/hw/bsp/stm32g4/boards/stm32g474nucleo/STM32G474RETx_FLASH.ld @@ -0,0 +1,190 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** Author : Auto-generated by Ac6 System Workbench +** +** Abstract : Linker script for STM32G474RETx series +** 512Kbytes FLASH and 160Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2014 Ac6

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of Ac6 nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +CCMSRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 32K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/stm32g4/boards/stm32g474nucleo/board.h b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.h new file mode 100644 index 000000000..fd9d50183 --- /dev/null +++ b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.h @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// G474RE Nucleo does not has usb connection. We need to manually connect +// - PA11 for D+, CN10.14 +// - PA12 for D-, CN10.12 + +// LED +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_5 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 1 + +// UART Enable for STLink VCOM +#define UART_DEV LPUART1 +#define UART_CLK_EN __HAL_RCC_LPUART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOA +#define UART_GPIO_AF GPIO_AF12_LPUART1 +#define UART_TX_PIN GPIO_PIN_2 +#define UART_RX_PIN GPIO_PIN_3 + + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void board_clock_init(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + // Configure the main internal regulator output voltage + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + + // Initializes the CPU, AHB and APB busses clocks + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; + RCC_OscInitStruct.PLL.PLLN = 85; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + // Initializes the CPU, AHB and APB busses clocks + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8); + +#if 0 // TODO need to check if USB clock is enabled + /* Enable HSI48 */ + memset(&RCC_OscInitStruct, 0, sizeof(RCC_OscInitStruct)); + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /*Enable CRS Clock*/ + RCC_CRSInitTypeDef RCC_CRSInitStruct= {0}; + __HAL_RCC_CRS_CLK_ENABLE(); + + /* Default Synchro Signal division factor (not divided) */ + RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + + /* Set the SYNCSRC[1:0] bits according to CRS_Source value */ + RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + + /* HSI48 is synchronized with USB SOF at 1KHz rate */ + RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000); + RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; + + /* Set the TRIM[5:0] to the default value */ + RCC_CRSInitStruct.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT; + + /* Start automatic synchronization */ + HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct); +#endif +} + +static inline void board_vbus_sense_init(void) +{ + // Enable VBUS sense (B device) via pin PA9 +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32g4/boards/stm32g474nucleo/board.mk b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.mk new file mode 100644 index 000000000..1951fcba0 --- /dev/null +++ b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.mk @@ -0,0 +1,8 @@ +CFLAGS += -DSTM32G474xx + +LD_FILE = $(BOARD_PATH)/STM32G474RETx_FLASH.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32g474xx.s + +# For flash-jlink target +JLINK_DEVICE = stm32g474re diff --git a/hw/bsp/stm32g4/family.c b/hw/bsp/stm32g4/family.c new file mode 100644 index 000000000..318f50746 --- /dev/null +++ b/hw/bsp/stm32g4/family.c @@ -0,0 +1,186 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "stm32g4xx_hal.h" +#include "bsp/board.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_HP_IRQHandler(void) +{ + tud_int_handler(0); +} + +void USB_LP_IRQHandler(void) +{ + tud_int_handler(0); +} + +void USBWakeUp_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ +UART_HandleTypeDef UartHandle; + +void board_init(void) +{ + board_clock_init(); + + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + UART_CLK_EN(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + +#ifdef UART_DEV + // UART + GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = UART_GPIO_AF; + HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); + + UartHandle = (UART_HandleTypeDef){ + .Instance = UART_DEV, + .Init.BaudRate = CFG_BOARD_UART_BAUDRATE, + .Init.WordLength = UART_WORDLENGTH_8B, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.Mode = UART_MODE_TX_RX, + .Init.OverSampling = UART_OVERSAMPLING_16 + }; + HAL_UART_Init(&UartHandle); +#endif + + // USB Pins TODO double check USB clock and pin setup + // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. +// GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); +// GPIO_InitStruct.Mode = GPIO_MODE_INPUT; +// GPIO_InitStruct.Pull = GPIO_NOPULL; +// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; +// HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +// +// __HAL_RCC_USB_CLK_ENABLE(); + + board_vbus_sense_init(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; (void) UartHandle; + return 0; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32g4/family.mk similarity index 53% rename from hw/bsp/stm32l476disco/board.mk rename to hw/bsp/stm32g4/family.mk index 28824efdc..04222f3bb 100644 --- a/hw/bsp/stm32l476disco/board.mk +++ b/hw/bsp/stm32g4/family.mk @@ -1,9 +1,12 @@ -ST_FAMILY = l4 +UF2_FAMILY_ID = 0x4c71240a +ST_FAMILY = g4 DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ -mthumb \ @@ -12,45 +15,30 @@ CFLAGS += \ -mfloat-abi=hard \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ - -DSTM32L476xx \ - -DCFG_TUSB_MCU=OPT_MCU_STM32L4 + -DCFG_TUSB_MCU=OPT_MCU_STM32G4 # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align - -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/STM32L476VGTx_FLASH.ld +CFLAGS += -Wno-error=cast-align SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c - -SRC_S += \ - $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l476xx.s + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c INC += \ + $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ - $(TOP)/$(ST_HAL_DRIVER)/Inc \ - $(TOP)/hw/bsp/$(BOARD) + $(TOP)/$(ST_HAL_DRIVER)/Inc # For freeRTOS port source FREERTOS_PORT = ARM_CM4F -# For flash-jlink target -JLINK_DEVICE = stm32l476vg - -# Path to STM32 Cube Programmer CLI, should be added into system path -STM32Prog = STM32_Programmer_CLI - # flash target using on-board stlink -flash: $(BUILD)/$(PROJECT).elf - $(STM32Prog) --connect port=swd --write $< --go +flash: flash-stlink diff --git a/hw/bsp/stm32g4/stm32g4xx_hal_conf.h b/hw/bsp/stm32g4/stm32g4xx_hal_conf.h new file mode 100644 index 000000000..ad5f7dbd4 --- /dev/null +++ b/hw/bsp/stm32g4/stm32g4xx_hal_conf.h @@ -0,0 +1,381 @@ +/** + ****************************************************************************** + * @file stm32g4xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32G4xx_HAL_CONF_H +#define STM32G4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED + + /*#define HAL_ADC_MODULE_ENABLED */ +/*#define HAL_COMP_MODULE_ENABLED */ +/*#define HAL_CORDIC_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +/*#define HAL_FDCAN_MODULE_ENABLED */ +/*#define HAL_FMAC_MODULE_ENABLED */ +/*#define HAL_HRTIM_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_I2C_MODULE_ENABLED */ +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_OPAMP_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_QSPI_MODULE_ENABLED */ +/*#define HAL_RNG_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SAI_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +/*#define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Register Callbacks selection ############################## */ +/** + * @brief This is the list of modules where register callback can be used + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U +#define USE_HAL_EXTI_REGISTER_CALLBACKS 0U +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE (24000000UL) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE (48000000UL) /*!< Value of the Internal High Speed oscillator for USB FS/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +/*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations in voltage and temperature.*/ +#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE (32768UL) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S and SAI peripherals + * This value is used by the I2S and SAI HAL modules to compute the I2S and SAI clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE (12288000UL) /*!< Value of the External oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (0UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32g4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32g4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32g4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32g4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32g4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32g4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32g4xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32g4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32g4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32g4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32g4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32g4xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32g4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32g4xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_HRTIM_MODULE_ENABLED +#include "stm32g4xx_hal_hrtim.h" +#endif /* HAL_HRTIM_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32g4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32g4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32g4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32g4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32g4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32g4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32g4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32g4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32g4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32g4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED +#include "stm32g4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32g4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32g4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32g4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32g4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32g4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32g4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32g4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32g4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32g4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32g4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32g4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32G4xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.mk b/hw/bsp/stm32h7/boards/stm32h743eval/board.mk index 96d14a795..b768a0ee6 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.mk +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.mk @@ -2,6 +2,7 @@ CFLAGS += -DSTM32H743xx -DHSE_VALUE=25000000 # Default is Highspeed port PORT ?= 1 +SPEED ?= high SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s LD_FILE = $(BOARD_PATH)/stm32h743xx_flash.ld diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index a2116d0bd..84976b4e4 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -237,7 +237,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); return len; } diff --git a/hw/bsp/stm32h7/family.mk b/hw/bsp/stm32h7/family.mk index e35e75610..096d04d0c 100644 --- a/hw/bsp/stm32h7/family.mk +++ b/hw/bsp/stm32h7/family.mk @@ -19,18 +19,24 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED - $(info "PORT1 High Speed") + ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") + else + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") + endif else - $(info "PORT0 Full Speed") + $(info "Using OTG_FS") endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align # All source paths should be relative to the top level. + SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk index c46887f14..e19101d64 100644 --- a/hw/bsp/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0538disco/board.mk @@ -13,6 +13,7 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DSTM32L053xx \ -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32L0 # mcu driver cause following warnings diff --git a/hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld b/hw/bsp/stm32l4/boards/stm32l476disco/STM32L476VGTx_FLASH.ld similarity index 100% rename from hw/bsp/stm32l476disco/STM32L476VGTx_FLASH.ld rename to hw/bsp/stm32l4/boards/stm32l476disco/STM32L476VGTx_FLASH.ld diff --git a/hw/bsp/stm32l476disco/stm32l476disco.c b/hw/bsp/stm32l4/boards/stm32l476disco/board.h similarity index 59% rename from hw/bsp/stm32l476disco/stm32l476disco.c rename to hw/bsp/stm32l4/boards/stm32l476disco/board.h index b18846685..42c657d5e 100644 --- a/hw/bsp/stm32l476disco/stm32l476disco.c +++ b/hw/bsp/stm32l4/boards/stm32l476disco/board.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020, 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 @@ -24,21 +24,12 @@ * This file is part of the TinyUSB stack. */ -#include "../board.h" +#ifndef BOARD_H_ +#define BOARD_H_ -#include "stm32l4xx_hal.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void OTG_FS_IRQHandler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ +#ifdef __cplusplus + extern "C" { +#endif #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_2 @@ -48,15 +39,16 @@ void OTG_FS_IRQHandler(void) #define BUTTON_PIN GPIO_PIN_0 #define BUTTON_STATE_ACTIVE 1 +#define UART_DEV USART2 +#define UART_CLK_EN __HAL_RCC_USART2_CLK_ENABLE +#define UART_GPIO_PORT GPIOD +#define UART_GPIO_AF GPIO_AF7_USART2 +#define UART_TX_PIN GPIO_PIN_5 +#define UART_RX_PIN GPIO_PIN_6 -// enable all LED, Button, Uart, USB clock -static void all_rcc_clk_enable(void) -{ - __HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+, D-, Button - __HAL_RCC_GPIOB_CLK_ENABLE(); // LED - __HAL_RCC_GPIOC_CLK_ENABLE(); // VBUS pin -} - +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ /** * @brief System Clock Configuration @@ -80,7 +72,7 @@ static void all_rcc_clk_enable(void) * @param None * @retval None */ -static void SystemClock_Config(void) +static inline void board_clock_init(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; @@ -131,112 +123,17 @@ static void SystemClock_Config(void) HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); } -void board_init(void) +static inline void board_vbus_sense_init(void) { - SystemClock_Config(); - all_rcc_clk_enable(); + // L476Disco use general GPIO PC11 for VBUS sensing instead of dedicated PA9 as others + // Disable VBUS Sense and force device mode + USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL; +} + +#ifdef __cplusplus + } #endif - /* Enable Power Clock*/ - __HAL_RCC_PWR_CLK_ENABLE(); - - /* Enable USB power on Pwrctrl CR2 register */ - HAL_PWREx_EnableVddUSB(); - - GPIO_InitTypeDef GPIO_InitStruct; - - // LED - GPIO_InitStruct.Pin = LED_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FAST; - HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); - - board_led_write(false); - - // Button - GPIO_InitStruct.Pin = BUTTON_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_FAST; - HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); - - // USB - /* Configure DM DP Pins */ - GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* Configure VBUS Pin */ - GPIO_InitStruct.Pin = GPIO_PIN_11; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - /* Enable USB FS Clock */ - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - - // Enable VBUS sense (B device) via pin PA9 - USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; -} - -//--------------------------------------------------------------------+ -// board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); -} - -uint32_t board_button_read(void) -{ - return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ - system_ticks++; -} - -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif - -void HardFault_Handler (void) -{ - asm("bkpt"); -} - -// Required by __libc_init_array in startup code if we are compiling using -// -nostdlib/-nostartfiles. -void _init(void) -{ - -} +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32l4/boards/stm32l476disco/board.mk b/hw/bsp/stm32l4/boards/stm32l476disco/board.mk new file mode 100644 index 000000000..e7b8557a5 --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l476disco/board.mk @@ -0,0 +1,10 @@ +CFLAGS += \ + -DSTM32L476xx \ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/STM32L476VGTx_FLASH.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l476xx.s + +# For flash-jlink target +JLINK_DEVICE = stm32l476vg diff --git a/hw/bsp/stm32l4/boards/stm32l4p5nucleo/STM32L4P5ZGTX_FLASH.ld b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/STM32L4P5ZGTX_FLASH.ld new file mode 100644 index 000000000..c1a490a70 --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/STM32L4P5ZGTX_FLASH.ld @@ -0,0 +1,200 @@ +/* +****************************************************************************** +** +** File : LinkerScript.ld +** +** Author : Auto-generated by STM32CubeIDE +** +** Abstract : Linker script for STM32L4P5ZGTx Device from STM32L4PLUS series +** 1024Kbytes ROM +** 320Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2019 STMicroelectronics

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of STMicroelectronics nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + 0x0001FFFF; /* end of "SRAM1" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K + ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "ROM" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >ROM + + /* The program code and other data into "ROM" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >ROM + + /* Constant data into "ROM" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >ROM + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >ROM + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >ROM + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >ROM + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >ROM + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >ROM + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> ROM + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.h b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.h new file mode 100644 index 000000000..1df389aed --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.h @@ -0,0 +1,137 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_14 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 1 + +#define UART_DEV LPUART1 +#define UART_CLK_EN __HAL_RCC_LPUART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOG +#define UART_GPIO_AF GPIO_AF8_LPUART1 +#define UART_TX_PIN GPIO_PIN_7 +#define UART_RX_PIN GPIO_PIN_8 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (MSI) + * SYSCLK(Hz) = 120000000 + * HCLK(Hz) = 120000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 1 + * APB2 Prescaler = 1 + * MSI Frequency(Hz) = 48000000 + * PLL_M = 12 + * PLL_N = 60 + * PLL_P = 2 + * PLL_Q = 2 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * The USB clock configuration from PLLSAI: + * PLLSAIP = 8 FIXME + * PLLSAIN = 384 FIXME + * PLLSAIQ = 7 FIXME + * @param None + * @retval None + */ + +static inline void board_clock_init(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /* Activate PLL with MSI , stabilizied via PLL by LSE */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; + RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 60; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Enable MSI Auto-calibration through LSE */ + HAL_RCCEx_EnableMSIPLLMode(); + + /* Select MSI output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select MSI output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPUART1; + PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + // Avoid overshoot and start with HCLK 60 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); + + /* AHB prescaler divider at 1 as second step */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +static inline void board_vbus_sense_init(void) +{ + // Enable VBUS sense (B device) via pin PA9 + USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.mk b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.mk new file mode 100644 index 000000000..8252dd838 --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l4p5nucleo/board.mk @@ -0,0 +1,10 @@ +CFLAGS += \ + -DSTM32L4P5xx \ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/STM32L4P5ZGTX_FLASH.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l4p5xx.s + +# For flash-jlink target +JLINK_DEVICE = stm32l4p5zg diff --git a/hw/bsp/stm32l4r5nucleo/STM32L4RXxI_FLASH.ld b/hw/bsp/stm32l4/boards/stm32l4r5nucleo/STM32L4RXxI_FLASH.ld similarity index 100% rename from hw/bsp/stm32l4r5nucleo/STM32L4RXxI_FLASH.ld rename to hw/bsp/stm32l4/boards/stm32l4r5nucleo/STM32L4RXxI_FLASH.ld diff --git a/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.h b/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.h new file mode 100644 index 000000000..1df389aed --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.h @@ -0,0 +1,137 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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 BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_14 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 1 + +#define UART_DEV LPUART1 +#define UART_CLK_EN __HAL_RCC_LPUART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOG +#define UART_GPIO_AF GPIO_AF8_LPUART1 +#define UART_TX_PIN GPIO_PIN_7 +#define UART_RX_PIN GPIO_PIN_8 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (MSI) + * SYSCLK(Hz) = 120000000 + * HCLK(Hz) = 120000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 1 + * APB2 Prescaler = 1 + * MSI Frequency(Hz) = 48000000 + * PLL_M = 12 + * PLL_N = 60 + * PLL_P = 2 + * PLL_Q = 2 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * The USB clock configuration from PLLSAI: + * PLLSAIP = 8 FIXME + * PLLSAIN = 384 FIXME + * PLLSAIQ = 7 FIXME + * @param None + * @retval None + */ + +static inline void board_clock_init(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /* Activate PLL with MSI , stabilizied via PLL by LSE */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; + RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 60; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Enable MSI Auto-calibration through LSE */ + HAL_RCCEx_EnableMSIPLLMode(); + + /* Select MSI output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select MSI output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPUART1; + PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + // Avoid overshoot and start with HCLK 60 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); + + /* AHB prescaler divider at 1 as second step */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +static inline void board_vbus_sense_init(void) +{ + // Enable VBUS sense (B device) via pin PA9 + USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.mk b/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.mk new file mode 100644 index 000000000..3d7fa227b --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l4r5nucleo/board.mk @@ -0,0 +1,14 @@ +CFLAGS += \ + -DHSE_VALUE=8000000 \ + -DSTM32L4R5xx \ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/STM32L4RXxI_FLASH.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l4r5xx.s + +# For flash-jlink target +JLINK_DEVICE = stm32l4r5zi + +# flash target using on-board stlink +flash: flash-stlink diff --git a/hw/bsp/stm32l4r5nucleo/stm32l4r5nucleo.c b/hw/bsp/stm32l4/family.c similarity index 54% rename from hw/bsp/stm32l4r5nucleo/stm32l4r5nucleo.c rename to hw/bsp/stm32l4/family.c index bab66b550..c15be98e5 100644 --- a/hw/bsp/stm32l4r5nucleo/stm32l4r5nucleo.c +++ b/hw/bsp/stm32l4/family.c @@ -26,9 +26,9 @@ * This file is part of the TinyUSB stack. */ -#include "../board.h" - #include "stm32l4xx_hal.h" +#include "bsp/board.h" +#include "board.h" //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler @@ -42,119 +42,22 @@ void OTG_FS_IRQHandler(void) // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -#define LED_PORT GPIOB -#define LED_PIN GPIO_PIN_14 -#define LED_STATE_ON 1 - -#define BUTTON_PORT GPIOC -#define BUTTON_PIN GPIO_PIN_13 -#define BUTTON_STATE_ACTIVE 1 - -#define UARTx LPUART1 -#define UART_GPIO_PORT GPIOG -#define UART_GPIO_AF GPIO_AF8_LPUART1 -#define UART_TX_PIN GPIO_PIN_7 -#define UART_RX_PIN GPIO_PIN_8 - UART_HandleTypeDef UartHandle; -// enable all LED, Button, Uart, USB clock -static void all_rcc_clk_enable(void) -{ - __HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+, D- - __HAL_RCC_GPIOB_CLK_ENABLE(); // LED - __HAL_RCC_GPIOC_CLK_ENABLE(); // Button - __HAL_RCC_GPIOG_CLK_ENABLE(); // Uart TX, RX - __HAL_RCC_LPUART1_CLK_ENABLE(); // LPUart1 module -} - -/** - * @brief System Clock Configuration - * The system Clock is configured as follow : - * System Clock source = PLL (MSI) - * SYSCLK(Hz) = 120000000 - * HCLK(Hz) = 120000000 - * AHB Prescaler = 1 - * APB1 Prescaler = 1 - * APB2 Prescaler = 1 - * MSI Frequency(Hz) = 48000000 - * PLL_M = 12 - * PLL_N = 60 - * PLL_P = 2 - * PLL_Q = 2 - * VDD(V) = 3.3 - * Main regulator output voltage = Scale1 mode - * Flash Latency(WS) = 5 - * The USB clock configuration from PLLSAI: - * PLLSAIP = 8 FIXME - * PLLSAIN = 384 FIXME - * PLLSAIQ = 7 FIXME - * @param None - * @retval None - */ -void SystemClock_Config(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct; - RCC_OscInitTypeDef RCC_OscInitStruct; - RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; - - /* Activate PLL with MSI , stabilizied via PLL by LSE */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.LSEState = RCC_LSE_ON; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; - RCC_OscInitStruct.PLL.PLLM = 12; - RCC_OscInitStruct.PLL.PLLN = 60; - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = 2; - HAL_RCC_OscConfig(&RCC_OscInitStruct); - - /* Enable MSI Auto-calibration through LSE */ - HAL_RCCEx_EnableMSIPLLMode(); - - /* Select MSI output as USB clock source */ - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); - - /* Select MSI output as USB clock source */ - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPUART1; - PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); - - /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 - clocks dividers */ - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - // Avoid overshoot and start with HCLK 60 MHz - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; - HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); - - /* AHB prescaler divider at 1 as second step */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); -} - void board_init(void) { - /* Enable Power Clock*/ - __HAL_RCC_PWR_CLK_ENABLE(); - /* Enable voltage range 1 boost mode for frequency above 80 Mhz */ - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + board_clock_init(); - /* Set tick interrupt priority, default HAL value is intentionally invalid - and that prevents PLL initialization in HAL_RCC_OscConfig() */ - - HAL_InitTick((1UL << __NVIC_PRIO_BITS) - 1UL); - - SystemClock_Config(); - all_rcc_clk_enable(); + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + UART_CLK_EN(); #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -164,6 +67,15 @@ void board_init(void) //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); #endif + /* Enable USB power on Pwrctrl CR2 register */ + /* Enable Power Clock*/ + __HAL_RCC_PWR_CLK_ENABLE(); + +#if defined(PWR_CR5_R1MODE) + /* Enable voltage range 1 boost mode for frequency above 80 Mhz */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); +#endif + /* Enable USB power on Pwrctrl CR2 register */ HAL_PWREx_EnableVddUSB(); @@ -192,7 +104,7 @@ void board_init(void) GPIO_InitStruct.Alternate = UART_GPIO_AF; HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); - UartHandle.Instance = UARTx; + UartHandle.Instance = UART_DEV; UartHandle.Init.BaudRate = CFG_BOARD_UART_BAUDRATE; UartHandle.Init.WordLength = UART_WORDLENGTH_8B; UartHandle.Init.StopBits = UART_STOPBITS_1; @@ -201,7 +113,7 @@ void board_init(void) UartHandle.Init.Mode = UART_MODE_TX_RX; UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; - UartHandle.Init.ClockPrescaler = UART_PRESCALER_DIV1; + //UartHandle.Init.ClockPrescaler = UART_PRESCALER_DIV1; UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; HAL_UART_Init(&UartHandle); @@ -231,8 +143,7 @@ void board_init(void) /* Enable USB FS Clocks */ __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - // Enable VBUS sense (B device) via pin PA9 - USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; + board_vbus_sense_init(); } //--------------------------------------------------------------------+ @@ -257,7 +168,7 @@ int board_uart_read(uint8_t* buf, int len) int board_uart_write(void const * buf, int len) { - HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); return len; } diff --git a/hw/bsp/stm32l4r5nucleo/board.mk b/hw/bsp/stm32l4/family.mk similarity index 81% rename from hw/bsp/stm32l4r5nucleo/board.mk rename to hw/bsp/stm32l4/family.mk index 12a291d0a..d6f55e5f9 100644 --- a/hw/bsp/stm32l4r5nucleo/board.mk +++ b/hw/bsp/stm32l4/family.mk @@ -4,6 +4,8 @@ DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ -mthumb \ @@ -12,18 +14,14 @@ CFLAGS += \ -mfloat-abi=hard \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ - -DHSE_VALUE=8000000 \ - -DSTM32L4R5xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32L4 # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/STM32L4RXxI_FLASH.ld - +#src/portable/st/synopsys/dcd_synopsys.c SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ @@ -34,14 +32,11 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c -SRC_S += \ - $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l4r5xx.s - INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ - $(TOP)/hw/bsp/$(BOARD) + $(TOP)/$(BOARD_PATH) # For freeRTOS port source FREERTOS_PORT = ARM_CM4F diff --git a/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h b/hw/bsp/stm32l4/stm32l4xx_hal_conf.h similarity index 100% rename from hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h rename to hw/bsp/stm32l4/stm32l4xx_hal_conf.h diff --git a/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h b/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h deleted file mode 100644 index 470ef1290..000000000 --- a/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h +++ /dev/null @@ -1,419 +0,0 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -/* #define HAL_ADC_MODULE_ENABLED */ -/* #define HAL_CAN_MODULE_ENABLED */ -/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -// #define HAL_NOR_MODULE_ENABLED -// #define HAL_SRAM_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -//#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -//#define HAL_LCD_MODULE_ENABLED -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -//#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -/* #define HAL_RNG_MODULE_ENABLED */ -/* #define HAL_RTC_MODULE_ENABLED */ -//#define HAL_SAI_MODULE_ENABLED -//#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -/* #define HAL_SPI_MODULE_ENABLED */ -/* #define HAL_SWPMI_MODULE_ENABLED */ -/* #define HAL_TIM_MODULE_ENABLED */ -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. - * This internal oscillator is mainly dedicated to provide a high precision clock to - * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. - * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency - * which is subject to manufacturing process variations. - */ -#if !defined (HSI48_VALUE) - #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. - The real value my vary depending on manufacturing process variations.*/ -#endif /* HSI48_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature.*/ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE 48000U /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE 48000U /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE 3300U /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */ -#define USE_RTOS 0U -#define PREFETCH_ENABLE 0U -#define INSTRUCTION_CACHE_ENABLE 1U -#define DATA_CACHE_ENABLE 1U - -#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ -#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ -#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ -#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ -#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ -#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ -#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ -#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ -#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ -#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ -#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ -#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ -#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ -#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ -#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ -#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ -#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ -#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ -#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ -#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ -#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ -#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ -#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ -#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ -#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ -#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ -#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ -#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ -#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ -#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ -#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ -#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ -#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ -#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ -#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ -#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ -#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ -#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1U */ - -/* ################## SPI peripheral configuration ########################## */ - -/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver - * Activated: CRC code is present inside driver - * Deactivated: CRC code cleaned from driver - */ - -#define USE_SPI_CRC 1U - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CAN_LEGACY_MODULE_ENABLED - #include "Legacy/stm32l4xx_hal_can_legacy.h" -#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t *file, uint32_t line); -#else - #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.h b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.h new file mode 100644 index 000000000..5732056ae --- /dev/null +++ b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.h @@ -0,0 +1,52 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define BOARD_UART UART0 +#define BOARD_UART_PORT GPIOA + +#define BOARD_BTN_PORT GPIOF +#define BOARD_BTN 4 +#define BOARD_BTN_Msk (1u<<4) +#define BUTTON_STATE_ACTIVE 0 + +#define LED_PORT GPIOF +#define LED_PIN_RED 1 +#define LED_PIN_BLUE 2 +#define LED_PIN_GREEN 3 +#define LED_STATE_ON 1 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.mk b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.mk new file mode 100644 index 000000000..d60365d1d --- /dev/null +++ b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/board.mk @@ -0,0 +1,11 @@ +CFLAGS += -DTM4C123GH6PM + +LD_FILE = $(BOARD_PATH)/tm4c123.ld + +# For flash-jlink target +JLINK_DEVICE = TM4C123GH6PM + +# flash using openocd +OPENOCD_OPTION = -f board/ti_ek-tm4c123gxl.cfg + +flash: flash-openocd diff --git a/hw/bsp/tm4c123/boards/ek-tm4c123gxl/tm4c123.ld b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/tm4c123.ld new file mode 100644 index 000000000..e2720a9ac --- /dev/null +++ b/hw/bsp/tm4c123/boards/ek-tm4c123gxl/tm4c123.ld @@ -0,0 +1,65 @@ +ENTRY(Reset_Handler) + +_estack = 0x20008000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x1000; /* required amount of stack */ + + +MEMORY +{ + FLASH(rx) : ORIGIN = 0x00000000, LENGTH = 256K + SRAM(rwx) : ORIGIN = 0x20000000, LENGTH = 32K +} + +SECTIONS +{ + .text : + { + . = ALIGN(4) ; + *(.vectors) + *(.text) + *(.text.*) + *(.init) + *(.fini) + *(.rodata) + *(.rodata.*) + . = ALIGN(4) ; + __end_text = . ; + } >FLASH + + .data : AT(ADDR(.text) + SIZEOF(.text)) + { + . = ALIGN(4); + __start_data = . ; + __la_data = LOADADDR(.data); + *(.data) + *(.data.*) + . = ALIGN(4); + __end_data = . ; + + } >SRAM + + .bss : + { + . = ALIGN(4) ; + __start_bss = . ; + __bss_start__ = __start_bss; + *(.bss) + *(.bss.*) + *(.COMMON) + __end_bss = . ; + . = ALIGN(4); + }>SRAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >SRAM +} diff --git a/hw/bsp/tm4c123/family.c b/hw/bsp/tm4c123/family.c new file mode 100644 index 000000000..449781ce1 --- /dev/null +++ b/hw/bsp/tm4c123/family.c @@ -0,0 +1,178 @@ +#include "TM4C123.h" +#include "bsp/board.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_Handler(void) +{ +#if TUSB_OPT_HOST_ENABLED + tuh_int_handler(0); +#endif + +#if TUSB_OPT_DEVICE_ENABLED + tud_int_handler(0); +#endif +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +static void board_uart_init (void) +{ + SYSCTL->RCGCUART |= (1 << 0); // Enable the clock to UART0 + SYSCTL->RCGCGPIO |= (1 << 0); // Enable the clock to GPIOA + + GPIOA->AFSEL |= (1 << 1) | (1 << 0); // Enable the alternate function on pin PA0 & PA1 + GPIOA->PCTL |= (1 << 0) | (1 << 4); // Configure the GPIOPCTL register to select UART0 in PA0 and PA1 + GPIOA->DEN |= (1 << 0) | (1 << 1); // Enable the digital functionality in PA0 and PA1 + + // BAUDRATE = 115200, with SystemCoreClock = 50 Mhz refer manual for calculation + // - BRDI = SystemCoreClock / (16* baud) + // - BRDF = int(fraction*64 + 0.5) + UART0->CTL &= ~(1 << 0); // Disable UART0 by clearing UARTEN bit in the UARTCTL register + UART0->IBRD = 27; // Write the integer portion of the BRD to the UARTIRD register + UART0->FBRD = 8; // Write the fractional portion of the BRD to the UARTFBRD registerer + + UART0->LCRH = (0x3 << 5); // 8-bit, no parity, 1 stop bit + UART0->CC = 0x0; // Configure the UART clock source as system clock + + UART0->CTL = (1 << 0) | (1 << 8) | (1 << 9); // UART0 Enable, Transmit Enable, Recieve Enable +} + +static void initialize_board_led (GPIOA_Type *port, uint8_t PinMsk, uint8_t dirmsk) +{ + /* Enable PortF Clock */ + SYSCTL->RCGCGPIO |= (1 << 5); + + /* Let the clock stabilize */ + while ( !((SYSCTL->PRGPIO) & (1 << 5)) ) {} + + /* Port Digital Enable */ + port->DEN |= PinMsk; + + /* Set direction */ + port->DIR = dirmsk; +} + +static void board_switch_init (void) +{ + GPIOF->DIR &= ~(1 << BOARD_BTN); + GPIOF->PUR |= (1 << BOARD_BTN); + GPIOF->DEN |= (1 << BOARD_BTN); +} + +static void WriteGPIOPin (GPIOA_Type *port, uint8_t PinMsk, bool state) +{ + if ( state ) + { + port->DATA |= PinMsk; + } + else + { + port->DATA &= ~(PinMsk); + } +} + +static uint32_t ReadGPIOPin (GPIOA_Type *port, uint8_t pinMsk) +{ + return (port->DATA & pinMsk); +} + +void board_init (void) +{ + SystemCoreClockUpdate(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + /* Reset USB */ + SYSCTL->SRCR2 |= (1u << 16); + + for ( volatile uint8_t i = 0; i < 20; i++ ) {} + + SYSCTL->SRCR2 &= ~(1u << 16); + + /* Open the USB clock gate */ + SYSCTL->RCGCUSB |= (1 << 0); + + /* Power-up USB PLL */ + SYSCTL->RCC2 &= ~(1u << 14); + + /* USB IO Initialization */ + SYSCTL->RCGCGPIO |= (1u << 3); + + /* Let the clock stabilize */ + while ( !(SYSCTL->PRGPIO & (1u << 3)) ) {} + + /* USB IOs to Analog Mode */ + GPIOD->AFSEL &= ~((1u << 4) | (1u << 5)); + GPIOD->DEN &= ~((1u << 4) | (1u << 5)); + GPIOD->AMSEL |= ((1u << 4) | (1u << 5)); + + uint8_t leds = (1 << LED_PIN_RED) | (1 << LED_PIN_BLUE) | (1 << LED_PIN_GREEN); + uint8_t dirmsk = (1 << LED_PIN_RED) | (1 << LED_PIN_BLUE) | (1 << LED_PIN_GREEN); + + /* Configure GPIO for board LED */ + initialize_board_led(LED_PORT, leds, dirmsk); + + /* Configure GPIO for board switch */ + board_switch_init(); + + /* Initialize board UART */ + board_uart_init(); + + TU_LOG1_INT(SystemCoreClock); +} + +void board_led_write (bool state) +{ + WriteGPIOPin(LED_PORT, (1 << LED_PIN_BLUE), state); +} + +uint32_t board_button_read (void) +{ + uint32_t gpio_value = ReadGPIOPin(BOARD_BTN_PORT, BOARD_BTN_Msk); + return BUTTON_STATE_ACTIVE ? gpio_value : !gpio_value; +} + +int board_uart_write (void const *buf, int len) +{ + uint8_t const * data = buf; + + for ( int i = 0; i < len; i++ ) + { + while ( (UART0->FR & (1 << 5)) != 0 ) {} // Poll until previous data was shofted out + UART0->DR = data[i]; // Write UART0 DATA REGISTER + } + + return len; +} + +int board_uart_read (uint8_t *buf, int len) +{ + (void) buf; + (void) len; + return 0; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis (void) +{ + return system_ticks; +} +#endif + diff --git a/hw/bsp/tm4c123/family.mk b/hw/bsp/tm4c123/family.mk new file mode 100644 index 000000000..751076196 --- /dev/null +++ b/hw/bsp/tm4c123/family.mk @@ -0,0 +1,36 @@ +DEPS_SUBMODULES += hw/mcu/ti + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -DCFG_TUSB_MCU=OPT_MCU_TM4C123 \ + -uvectors \ + -DTM4C123GH6PM + +# mcu driver cause following warnings +CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual + +MCU_DIR=hw/mcu/ti/tm4c123xx/ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/tm4c123.ld + +INC += \ + $(TOP)/$(MCU_DIR)/CMSIS/5.7.0/CMSIS/Include \ + $(TOP)/$(MCU_DIR)/Include/TM4C123 \ + $(TOP)/$(BOARD_PATH) + +SRC_C += \ + src/portable/mentor/musb/dcd_musb.c \ + src/portable/mentor/musb/hcd_musb.c \ + $(MCU_DIR)/Source/system_TM4C123.c \ + $(MCU_DIR)/Source/GCC/tm4c123_startup.c + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F diff --git a/hw/bsp/xmc4000/boards/xmc4500_relax/board.h b/hw/bsp/xmc4000/boards/xmc4500_relax/board.h new file mode 100644 index 000000000..3e2cb9583 --- /dev/null +++ b/hw/bsp/xmc4000/boards/xmc4500_relax/board.h @@ -0,0 +1,88 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define LED_PIN P1_1 +#define LED_STATE_ON 1 + +#define BUTTON_PIN P1_14 +#define BUTTON_STATE_ACTIVE 0 + +//#define UART_DEV USART6 +//#define UART_CLK_EN __HAL_RCC_USART6_CLK_ENABLE +//#define UART_GPIO_AF GPIO_AF8_USART6 +// +//#define UART_TX_PORT GPIOC +//#define UART_TX_PIN GPIO_PIN_6 +// +//#define UART_RX_PORT GPIOC +//#define UART_RX_PIN GPIO_PIN_7 + +static inline void board_clock_init(void) +{ + /* Clock configuration */ + /* fPLL = 120MHz */ + /* fSYS = 120MHz */ + /* fUSBPLL = 192MHz */ + /* fUSB = 48MHz */ + const XMC_SCU_CLOCK_CONFIG_t clock_config = + { + .syspll_config.p_div = 2, + .syspll_config.n_div = 80, + .syspll_config.k_div = 4, + .syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL, + .syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP, + .enable_oschp = true, + .calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY, + .fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL, + .fsys_clkdiv = 1, + .fcpu_clkdiv = 1, + .fccu_clkdiv = 1, + .fperipheral_clkdiv = 1 + }; + + /* Setup settings for USB clock */ + XMC_SCU_CLOCK_Init(&clock_config); + + XMC_SCU_CLOCK_EnableUsbPll(); + XMC_SCU_CLOCK_StartUsbPll(2, 64); + XMC_SCU_CLOCK_SetUsbClockDivider(4); + XMC_SCU_CLOCK_SetUsbClockSource(XMC_SCU_CLOCK_USBCLKSRC_USBPLL); + XMC_SCU_CLOCK_EnableClock(XMC_SCU_CLOCK_USB); +} + + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/xmc4000/boards/xmc4500_relax/board.mk b/hw/bsp/xmc4000/boards/xmc4500_relax/board.mk new file mode 100644 index 000000000..a2c2c5aaf --- /dev/null +++ b/hw/bsp/xmc4000/boards/xmc4500_relax/board.mk @@ -0,0 +1,9 @@ +MCU_VARIANT = XMC4500 +CFLAGS += \ + -DXMC4500_F100x1024 \ + +LD_FILE = $(MCU_DIR)/CMSIS/Infineon/COMPONENT_$(MCU_VARIANT)/Source/TOOLCHAIN_GCC_ARM/XMC4500x1024.ld + +JLINK_DEVICE = XMC4500-1024 + +flash: flash-jlink diff --git a/hw/bsp/xmc4000/family.c b/hw/bsp/xmc4000/family.c new file mode 100644 index 000000000..bf6684736 --- /dev/null +++ b/hw/bsp/xmc4000/family.c @@ -0,0 +1,130 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "xmc_gpio.h" +#include "xmc_scu.h" + +#include "bsp/board.h" +#include "board.h" + + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_0_IRQHandler(void) +{ + tud_int_handler(0); +} + +void board_init(void) +{ + board_clock_init(); + SystemCoreClockUpdate(); + + // LED + XMC_GPIO_CONFIG_t led_cfg; + led_cfg.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL; + led_cfg.output_level = XMC_GPIO_OUTPUT_LEVEL_HIGH; + led_cfg.output_strength = XMC_GPIO_OUTPUT_STRENGTH_MEDIUM; + XMC_GPIO_Init(LED_PIN, &led_cfg); + + // Button + XMC_GPIO_CONFIG_t button_cfg; + button_cfg.mode = XMC_GPIO_MODE_INPUT_TRISTATE; + XMC_GPIO_Init(BUTTON_PIN, &button_cfg); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB0_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + // USB Power Enable + XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USB0); + XMC_SCU_POWER_EnableUsb(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + uint32_t is_high = state ? LED_STATE_ON : (1-LED_STATE_ON); + + XMC_GPIO_SetOutputLevel(LED_PIN, is_high ? XMC_GPIO_OUTPUT_LEVEL_HIGH : XMC_GPIO_OUTPUT_LEVEL_LOW); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == XMC_GPIO_GetInput(BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) +{ +#ifdef UART_DEV + for(int i=0;inum_entry; i++) @@ -162,11 +162,11 @@ uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) int fill_options(void *dest, uint8_t msg_type, const char *domain, - ip_addr_t dns, + ip4_addr_t dns, int lease_time, - ip_addr_t serverid, - ip_addr_t router, - ip_addr_t subnet) + ip4_addr_t serverid, + ip4_addr_t router, + ip4_addr_t subnet) { uint8_t *ptr = (uint8_t *)dest; /* ACK message type */ diff --git a/lib/networking/dhserver.h b/lib/networking/dhserver.h index 0d22461c7..2a0b15854 100644 --- a/lib/networking/dhserver.h +++ b/lib/networking/dhserver.h @@ -41,16 +41,16 @@ typedef struct dhcp_entry { - uint8_t mac[6]; - ip_addr_t addr; - uint32_t lease; + uint8_t mac[6]; + ip4_addr_t addr; + uint32_t lease; } dhcp_entry_t; typedef struct dhcp_config { - ip_addr_t router; + ip4_addr_t router; uint16_t port; - ip_addr_t dns; + ip4_addr_t dns; const char *domain; int num_entry; dhcp_entry_t *entries; diff --git a/lib/networking/dnserver.c b/lib/networking/dnserver.c index 6df0bd0c4..e4e7c3492 100644 --- a/lib/networking/dnserver.c +++ b/lib/networking/dnserver.c @@ -136,7 +136,7 @@ static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const dns_header_t *header; static dns_query_t query; struct pbuf *out; - ip_addr_t host_addr; + ip4_addr_t host_addr; dns_answer_t *answer; (void)arg; diff --git a/lib/networking/dnserver.h b/lib/networking/dnserver.h index 130991f5f..a062e3aa7 100644 --- a/lib/networking/dnserver.h +++ b/lib/networking/dnserver.h @@ -39,7 +39,7 @@ #include "lwip/udp.h" #include "netif/etharp.h" -typedef bool (*dns_query_proc_t)(const char *name, ip_addr_t *addr); +typedef bool (*dns_query_proc_t)(const char *name, ip4_addr_t *addr); err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); void dnserv_free(void); diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f99061eae..6f9c1a6b5 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -494,18 +494,6 @@ typedef enum /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification -/// Isochronous End Point Attributes -typedef enum -{ - TUSB_ISO_EP_ATT_NO_SYNC = 0x00, - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point - TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -} tusb_iso_ep_attribute_t; - /// Audio Class-Control Values UAC2 typedef enum { diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ff4e312a7..d9f2e284e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -64,10 +64,19 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +// Use ring buffer if it's available, some MCUs need extra RAM requirements +#ifndef TUD_AUDIO_PREFER_RING_BUFFER +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define TUD_AUDIO_PREFER_RING_BUFFER 0 +#else +#define TUD_AUDIO_PREFER_RING_BUFFER 1 +#endif +#endif + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer // is available or driver is would need to be changed dramatically -// Only STM32 synopsys use non-linear buffer for now +// Only STM32 synopsys and dcd_transdimension use non-linear buffer for now // Synopsys detection copied from dcd_synopsys.c (refactor later on) #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ defined (STM32F107xB) || defined (STM32F107xC) @@ -90,11 +99,19 @@ CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ CFG_TUSB_MCU == OPT_MCU_RX72N || \ - CFG_TUSB_MCU == OPT_MCU_GD32VF103 + CFG_TUSB_MCU == OPT_MCU_GD32VF103 || \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_MSP432E4 +#if TUD_AUDIO_PREFER_RING_BUFFER #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 #endif +#else +#define USE_LINEAR_BUFFER 1 +#endif // Declaration of buffers @@ -1553,20 +1570,21 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + uint8_t const ep_addr = desc_ep->bEndpointAddress; //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address audio->ep_in = ep_addr; audio->ep_in_as_intf_num = itf; - audio->ep_in_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; + audio->ep_in_sz = tu_edpt_packet_size(desc_ep); // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters #if CFG_TUD_AUDIO_ENABLE_ENCODING @@ -1600,7 +1618,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Save address audio->ep_out = ep_addr; audio->ep_out_as_intf_num = itf; - audio->ep_out_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; + audio->ep_out_sz = tu_edpt_packet_size(desc_ep); #if CFG_TUD_AUDIO_ENABLE_DECODING audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); @@ -1619,7 +1637,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // In case of asynchronous EP, call Cb after ep_fb is set - if (!(((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync == 0x01 && audio->ep_fb == 0)) + if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) ) { if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } @@ -1636,7 +1654,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback { audio->ep_fb = ep_addr; diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 1d27ae7c5..8ef609622 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -112,74 +112,78 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - // Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol - if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size) - { - _btd_itf.itf_num = itf_desc->bInterfaceNumber; + TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + _btd_itf.itf_num = itf_desc->bInterfaceNumber; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - _btd_itf.ep_ev = desc_ep->bEndpointAddress; + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, - &_btd_itf.ep_acl_in), 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; - // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); - drv_len = hci_itf_size; - } - else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size) - { - uint8_t dir; + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + + // Ensure this is still BT Primary Controller + TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); + + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); drv_len += iso_alt_itf_size; - - for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { - // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); - if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || - TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || - TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { - // Not an Iso interface instance - break; - } - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; - drv_len += iso_alt_itf_size; - } } return drv_len; @@ -214,14 +218,14 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c } else return false; - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); } else if ( stage == CONTROL_STAGE_DATA ) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); } return true; diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 5df47f70b..e345139ea 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -58,31 +58,32 @@ typedef enum /// Communication Interface Subclass Codes typedef enum { - CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL , ///< Abstract Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] - CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2] - CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1] - CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1] - CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL , ///< Mobile Direct Line Model [USBWMC1.1] - CDC_COMM_SUBCLASS_OBEX , ///< OBEX [USBWMC1.1] - CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model [USBEEM1.0] + CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL = 0x02 , ///< Abstract Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL = 0x03 , ///< Telephone Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL = 0x04 , ///< Multi-Channel Control Model [USBISDN1.2] + CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL = 0x05 , ///< CAPI Control Model [USBISDN1.2] + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL = 0x06 , ///< Ethernet Networking Control Model [USBECM1.2] + CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL = 0x07 , ///< ATM Networking Control Model [USBATM1.2] + CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL = 0x08 , ///< Wireless Handset Control Model [USBWMC1.1] + CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT = 0x09 , ///< Device Management [USBWMC1.1] + CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL = 0x0A , ///< Mobile Direct Line Model [USBWMC1.1] + CDC_COMM_SUBCLASS_OBEX = 0x0B , ///< OBEX [USBWMC1.1] + CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL = 0x0C , ///< Ethernet Emulation Model [USBEEM1.0] + CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL = 0x0D ///< Network Control Model [USBNCM1.0] } cdc_comm_sublcass_type_t; /// Communication Interface Protocol Codes typedef enum { - CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol - CDC_COMM_PROTOCOL_ATCOMMAND , ///< AT Commands: V.250 etc - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 , ///< AT Commands defined by PCCA-101 - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO , ///< AT Commands defined by PCCA-101 & Annex O - CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 , ///< AT Commands defined by GSM 07.07 - CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 , ///< AT Commands defined by 3GPP 27.007 - CDC_COMM_PROTOCOL_ATCOMMAND_CDMA , ///< AT Commands defined by TIA for CDMA - CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL ///< Ethernet Emulation Model + CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol + CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , ///< AT Commands: V.250 etc + CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 = 0x02 , ///< AT Commands defined by PCCA-101 + CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO = 0x03 , ///< AT Commands defined by PCCA-101 & Annex O + CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 = 0x04 , ///< AT Commands defined by GSM 07.07 + CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 = 0x05 , ///< AT Commands defined by 3GPP 27.007 + CDC_COMM_PROTOCOL_ATCOMMAND_CDMA = 0x06 , ///< AT Commands defined by TIA for CDMA + CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL = 0x07 ///< Ethernet Emulation Model } cdc_comm_protocol_type_t; //------------- SubType Descriptor in COMM Functional Descriptor -------------// @@ -114,7 +115,8 @@ typedef enum CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor - CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 ///< OBEX Service Identifier Functional Descriptor + CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 , ///< OBEX Service Identifier Functional Descriptor + CDC_FUNC_DESC_NCM = 0x1A , ///< NCM Functional Descriptor }cdc_func_desc_type_t; //--------------------------------------------------------------------+ @@ -122,7 +124,8 @@ typedef enum //--------------------------------------------------------------------+ // SUBCLASS code of Data Interface is not used and should/must be zero -/// Data Interface Protocol Codes + +// Data Interface Protocol Codes typedef enum{ CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC @@ -147,7 +150,6 @@ typedef enum { CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. - CDC_REQUEST_SET_COMM_FEATURE = 0x02, CDC_REQUEST_GET_COMM_FEATURE = 0x03, CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04, @@ -194,21 +196,18 @@ typedef enum // Management Elemenent Notification (Notification Endpoint) //--------------------------------------------------------------------+ -/// Communication Interface Management Element Notification Codes +/// 6.3 Notification Codes typedef enum { - NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. - RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. - - AUX_JACK_HOOK_STATE = 0x08, - RING_DETECT = 0x09, - - SERIAL_STATE = 0x20, - - CALL_STATE_CHANGE = 0x28, - LINE_STATE_CHANGE = 0x29, - CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred - MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, + CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. + CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. + CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, + CDC_NOTIF_RING_DETECT = 0x09, + CDC_NOTIF_SERIAL_STATE = 0x20, + CDC_NOTIF_CALL_STATE_CHANGE = 0x28, + CDC_NOTIF_LINE_STATE_CHANGE = 0x29, + CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred + CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, }cdc_notification_request_t; //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e622bd616..08f2af253 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -80,7 +80,7 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -static void _prep_out_transaction (cdcd_interface_t* p_cdc) +static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { uint8_t const rhport = TUD_OPT_RHPORT; uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); @@ -89,21 +89,23 @@ static void _prep_out_transaction (cdcd_interface_t* p_cdc) // TODO Actually we can still carry out the transfer, keeping count of received bytes // and slowly move it to the FIFO when read(). // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_cdc->epout_buf), ); + TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), ); + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); // fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&p_cdc->rx_ff); if ( available >= sizeof(p_cdc->epout_buf) ) { - usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); }else { // Release endpoint since we don't make any transfer usbd_edpt_release(rhport, p_cdc->ep_out); + + return false; } } @@ -229,7 +231,7 @@ void cdcd_init(void) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - p_cdc->wanted_char = -1; + p_cdc->wanted_char = (char) -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 p_cdc->line_coding.bit_rate = 115200; diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 7ff757add..fbc7162a3 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -82,7 +82,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); void tud_cdc_n_read_flush (uint8_t itf); // Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, uint8_t* u8); +bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); // Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); @@ -116,7 +116,7 @@ static inline uint32_t tud_cdc_available (void); static inline int32_t tud_cdc_read_char (void); static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (uint8_t* u8); +static inline bool tud_cdc_peek (uint8_t* ui8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); @@ -206,9 +206,9 @@ static inline void tud_cdc_read_flush (void) tud_cdc_n_read_flush(0); } -static inline bool tud_cdc_peek (uint8_t* u8) +static inline bool tud_cdc_peek (uint8_t* ui8) { - return tud_cdc_n_peek(0, u8); + return tud_cdc_n_peek(0, ui8); } static inline uint32_t tud_cdc_write_char (char ch) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e7eaf4d05..f4fb6c1d6 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -105,7 +105,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; - return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); + return usbh_edpt_xfer(dev_addr, ep_out, (void*)(uintptr_t) p_data, length); } bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 28abf6e83..ddfa608e4 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -190,7 +190,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); return drv_len; diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2ee80750a..588b61254 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -206,8 +206,8 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); + TU_ASSERT(HID_DESC_TYPE_HID == tu_desc_type(p_desc), 0); p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType, 0); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -216,10 +216,10 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode - p_hid->itf_num = desc_itf->bInterfaceNumber; + p_hid->itf_num = desc_itf->bInterfaceNumber; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); + p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); // Prepare for output endpoint if (p_hid->ep_out) @@ -256,13 +256,13 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) { - TU_VERIFY(p_hid->hid_descriptor != NULL); - TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); + TU_VERIFY(p_hid->hid_descriptor); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); + tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); } else { @@ -282,7 +282,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_id = tu_u16_low(request->wValue); uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = request->wLength; + uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); uint16_t xferlen = 0; @@ -314,7 +314,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_id = tu_u16_low(request->wValue); uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = request->wLength; + uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); // If host request a specific Report ID, extract report ID in buffer before invoking callback if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index e2c950dd1..078b67349 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -195,16 +195,7 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y HID_REPORT_COUNT ( 1 ) ,\ HID_REPORT_SIZE ( 8 ) ,\ HID_INPUT ( HID_CONSTANT ) ,\ - /* 6-byte Keycodes */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX_N ( 255, 2 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N( 255, 2 ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - /* 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ + /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ HID_USAGE_MIN ( 1 ) ,\ HID_USAGE_MAX ( 5 ) ,\ @@ -215,6 +206,15 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y HID_REPORT_COUNT ( 1 ) ,\ HID_REPORT_SIZE ( 3 ) ,\ HID_OUTPUT ( HID_CONSTANT ) ,\ + /* 6-byte Keycodes */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ + HID_USAGE_MIN ( 0 ) ,\ + HID_USAGE_MAX_N ( 255, 2 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX_N( 255, 2 ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ // Mouse Report Descriptor Template @@ -310,8 +310,8 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y HID_COLLECTION_END \ // Gamepad Report Descriptor Template -// with 16 buttons, 2 joysticks and 1 hat/dpad with following layout -// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (2 bytes) | +// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout +// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | #define TUD_HID_REPORT_DESC_GAMEPAD(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ @@ -319,37 +319,37 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* Report ID if any */\ __VA_ARGS__ \ /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ /* 8 bit DPad/Hat Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 8 ) ,\ - HID_PHYSICAL_MIN ( 0 ) ,\ - HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 16 bit Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 32 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 32 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ + HID_LOGICAL_MIN ( 1 ) ,\ + HID_LOGICAL_MAX ( 8 ) ,\ + HID_PHYSICAL_MIN ( 0 ) ,\ + HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 32 bit Button Map */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 32 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + HID_REPORT_COUNT ( 32 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ // HID Generic Input & Output @@ -364,14 +364,14 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* Input */ \ HID_USAGE ( 0x02 ),\ HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX ( 0xff ),\ + HID_LOGICAL_MAX_N ( 0xff, 2 ),\ HID_REPORT_SIZE ( 8 ),\ HID_REPORT_COUNT( report_size ),\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ /* Output */ \ HID_USAGE ( 0x03 ),\ HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX ( 0xff ),\ + HID_LOGICAL_MAX_N ( 0xff, 2 ),\ HID_REPORT_SIZE ( 8 ),\ HID_REPORT_COUNT( report_size ),\ HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8c66477b3..f19f1ba81 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -291,7 +291,15 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + // first endpoint may be OUT, skip to IN endpoint // TODO also open endpoint OUT + if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) + { + p_desc = tu_desc_next(p_desc); + desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + } + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); @@ -299,7 +307,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->epin_size = desc_ep->wMaxPacketSize.size; + hid_itf->epin_size = tu_edpt_packet_size(desc_ep); // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index eb85b668c..b08b362f9 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -279,6 +279,12 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* stream->buffer[0] = (cable_num << 4) | msg; stream->total = 4; } + else if ( msg == 0xC || msg == 0xD) + { + // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 3; + } else if ( msg == 0xf ) { // System message @@ -433,6 +439,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint break; } } + TU_ASSERT(p_midi); p_midi->itf_num = desc_midi->bInterfaceNumber; (void) p_midi->itf_num; diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 014e8b69e..97837b114 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -46,7 +46,8 @@ enum MSC_STAGE_CMD = 0, MSC_STAGE_DATA, MSC_STAGE_STATUS, - MSC_STAGE_STATUS_SENT + MSC_STAGE_STATUS_SENT, + MSC_STAGE_NEED_RESET, }; typedef struct @@ -61,7 +62,7 @@ typedef struct // Bulk Only Transfer (BOT) Protocol uint8_t stage; - uint32_t total_len; + uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage // Sense Response Data @@ -78,7 +79,55 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_ //--------------------------------------------------------------------+ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); + static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); +static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); + +TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) +{ + return tu_bit_test(dir, 7); +} + +static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) +{ + // Data residue is always = host expect - actual transferred + p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + + p_msc->stage = MSC_STAGE_STATUS_SENT; + return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); +} + +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)); +} + +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; + + p_csw->status = status; + p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + p_msc->stage = MSC_STAGE_STATUS; + + // failed but sense key is not set: default to Illegal Request + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + + // If there is data stage and not yet complete, stall it + if ( p_cbw->total_bytes && p_csw->data_residue ) + { + if ( is_data_in(p_cbw->dir) ) + { + usbd_edpt_stall(rhport, p_msc->ep_in); + } + else + { + usbd_edpt_stall(rhport, p_msc->ep_out); + } + } +} static inline uint32_t rdwr10_get_lba(uint8_t const command[]) { @@ -89,15 +138,65 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) return tu_ntohl(lba); } -static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) +static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) { - // use offsetof to avoid pointer to the odd/misaligned address - uint16_t const block_count = tu_unaligned_read16(command + offsetof(scsi_write10_t, block_count)); - - // block count is in Big Endian + uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); return tu_ntohs(block_count); } +static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) +{ + // first extract block count in the command + uint16_t const block_count = rdwr10_get_blockcount(cbw); + + // invalid block count + if (block_count == 0) return 0; + + return (uint16_t) (cbw->total_bytes / block_count); +} + +uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) +{ + uint8_t status = MSC_CSW_STATUS_PASSED; + uint16_t const block_count = rdwr10_get_blockcount(cbw); + + if ( cbw->total_bytes == 0 ) + { + if ( block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + }else + { + // no data transfer, only exist in complaint test suite + } + }else + { + if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( 0 == block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); + status = MSC_CSW_STATUS_FAILED; + } + else if ( cbw->total_bytes / block_count == 0 ) + { + TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + } + + return status; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -164,7 +263,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - // Max length mus be at least 1 interface + 2 endpoints + // Max length must be at least 1 interface + 2 endpoints TU_ASSERT(max_len >= drv_len, 0); mscd_interface_t * p_msc = &_mscd_itf; @@ -174,35 +273,93 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); // Prepare for Command Block Wrapper - if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ) - { - TU_LOG_FAILED(); - TU_BREAKPOINT(); - } + TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); return drv_len; } +static void proc_bot_reset(mscd_interface_t* p_msc) +{ + p_msc->stage = MSC_STAGE_CMD; + p_msc->total_len = 0; + p_msc->xferred_len = 0; + + p_msc->sense_key = 0; + p_msc->add_sense_code = 0; + p_msc->add_sense_qualifier = 0; +} + // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request) +bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { // nothing to do with DATA & ACK stage if (stage != CONTROL_STAGE_SETUP) return true; - // Handle class request only - TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + mscd_interface_t* p_msc = &_mscd_itf; - switch ( p_request->bRequest ) + // Clear Endpoint Feature (stall) for recovery + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && + TUSB_REQ_CLEAR_FEATURE == request->bRequest && + TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) + { + uint8_t const ep_addr = tu_u16_low(request->wIndex); + + if ( p_msc->stage == MSC_STAGE_NEED_RESET ) + { + // reset recovery is required to recover from this stage + // Clear Stall request cannot resolve this -> continue to stall endpoint + usbd_edpt_stall(rhport, ep_addr); + } + else + { + if ( ep_addr == p_msc->ep_in ) + { + if ( p_msc->stage == MSC_STAGE_STATUS ) + { + // resume sending SCSI status if we are in this stage previously before stalled + TU_ASSERT( send_csw(rhport, p_msc) ); + } + } + else if ( ep_addr == p_msc->ep_out ) + { + if ( p_msc->stage == MSC_STAGE_CMD ) + { + // part of reset recovery (probably due to invalid CBW) -> prepare for new command + // Note: skip if already queued previously + if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) + { + TU_ASSERT( prepare_cbw(rhport, p_msc) ); + } + } + } + } + + return true; + } + + // From this point only handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch ( request->bRequest ) { case MSC_REQ_RESET: - // TODO: Actually reset interface. - tud_control_status(rhport, p_request); + TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); + TU_VERIFY(request->wValue == 0 && request->wLength == 0); + + // driver state reset + proc_bot_reset(p_msc); + + tud_control_status(rhport, request); break; case MSC_REQ_GET_MAX_LUN: { + TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); + TU_VERIFY(request->wValue == 0 && request->wLength == 1); + uint8_t maxlun = 1; if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); TU_VERIFY(maxlun); @@ -210,7 +367,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t // MAX LUN is minus 1 by specs maxlun--; - tud_control_xfer(rhport, p_request, &maxlun, 1); + tud_control_xfer(rhport, request, &maxlun, 1); } break; @@ -222,6 +379,8 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { + (void) event; + mscd_interface_t* p_msc = &_mscd_itf; msc_cbw_t const * p_cbw = &p_msc->cbw; msc_csw_t * p_csw = &p_msc->csw; @@ -233,46 +392,79 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if(ep_addr != p_msc->ep_out) return true; - TU_ASSERT( event == XFER_RESULT_SUCCESS && - xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); + if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) + { + TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); + + // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery + p_msc->stage = MSC_STAGE_NEED_RESET; + + // invalid CBW stall both endpoints + usbd_edpt_stall(rhport, p_msc->ep_in); + usbd_edpt_stall(rhport, p_msc->ep_out); + + return false; + } TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - // TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); + //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; p_csw->data_residue = 0; + p_csw->status = MSC_CSW_STATUS_PASSED; /*------------- Parse command and prepare DATA -------------*/ p_msc->stage = MSC_STAGE_DATA; p_msc->total_len = p_cbw->total_bytes; p_msc->xferred_len = 0; - if (SCSI_CMD_READ_10 == p_cbw->command[0]) + // Read10 or Write10 + if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) { - proc_read10_cmd(rhport, p_msc); - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_cmd(rhport, p_msc); + uint8_t const status = rdwr10_validate_cmd(p_cbw); + + if ( status != MSC_CSW_STATUS_PASSED) + { + fail_scsi_op(rhport, p_msc, status); + }else if ( p_cbw->total_bytes ) + { + if (SCSI_CMD_READ_10 == p_cbw->command[0]) + { + proc_read10_cmd(rhport, p_msc); + }else + { + proc_write10_cmd(rhport, p_msc); + } + }else + { + // no data transfer, only exist in complaint test suite + p_msc->stage = MSC_STAGE_STATUS; + } } else { // For other SCSI commands // 1. OUT : queue transfer (invoke app callback after done) // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length - if ( (p_cbw->total_bytes > 0 ) && !tu_bit_test(p_cbw->dir, 7) ) + if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) { - // queue transfer - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); + if (p_cbw->total_bytes > sizeof(_mscd_buf)) + { + TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first + // but it is OK to just receive data then responded with failed status + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); + } }else { - int32_t resplen; - // First process if it is a built-in commands - resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); + int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - // Not built-in, invoke user callback + // 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, p_msc->total_len); @@ -280,28 +472,35 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if ( resplen < 0 ) { - p_msc->total_len = 0; - p_csw->status = MSC_CSW_STATUS_FAILED; - p_msc->stage = MSC_STAGE_STATUS; - - // failed but senskey is not set: default to Illegal Request - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - // Stall bulk In if needed - if (p_cbw->total_bytes) usbd_edpt_stall(rhport, p_msc->ep_in); + // unsupported command + TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + } + else if (resplen == 0) + { + if (p_cbw->total_bytes) + { + // 6.7 The 13 Cases: case 4 (Hi > Dn) + // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // case 1 Hn = Dn: all good + p_msc->stage = MSC_STAGE_STATUS; + } } else { - p_msc->total_len = (uint32_t) resplen; - p_csw->status = MSC_CSW_STATUS_PASSED; - - if (p_msc->total_len) + if ( p_cbw->total_bytes == 0 ) { - TU_ASSERT( p_cbw->total_bytes >= p_msc->total_len ); // cannot return more than host expect - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); + // 6.7 The 13 Cases: case 2 (Hn < Di) + // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); }else { - p_msc->stage = MSC_STAGE_STATUS; + // cannot return more than host expect + p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); } } } @@ -312,87 +511,51 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); - // OUT transfer, invoke callback if needed - if ( !tu_bit_test(p_cbw->dir, 7) ) + if (SCSI_CMD_READ_10 == p_cbw->command[0]) { - if ( SCSI_CMD_WRITE_10 != p_cbw->command[0] ) + p_msc->xferred_len += xferred_bytes; + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + }else + { + proc_read10_cmd(rhport, p_msc); + } + } + else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) + { + proc_write10_new_data(rhport, p_msc, xferred_bytes); + } + else + { + p_msc->xferred_len += xferred_bytes; + + // OUT transfer, invoke callback if needed + if ( !is_data_in(p_cbw->dir) ) { int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); if ( cb_result < 0 ) { - p_csw->status = MSC_CSW_STATUS_FAILED; - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation + // unsupported command + TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); }else { - p_csw->status = MSC_CSW_STATUS_PASSED; + // TODO haven't implement this scenario any further yet } } + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + } else { - uint16_t const block_sz = p_cbw->total_bytes / rdwr10_get_blockcount(p_cbw->command); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Application can consume smaller bytes - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, xferred_bytes); - - if ( nbytes < 0 ) - { - // negative means error -> skip to status phase, status in CSW set to failed - p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len; - p_csw->status = MSC_CSW_STATUS_FAILED; - p_msc->stage = MSC_STAGE_STATUS; - - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation - break; - }else - { - // Application consume less than what we got (including zero) - if ( nbytes < (int32_t) xferred_bytes ) - { - if ( nbytes > 0 ) - { - p_msc->xferred_len += nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes); - } - - // simulate an transfer complete with adjusted parameters --> this driver callback will fired again - dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false); - - return true; // skip the rest - } - else - { - // Application consume all bytes in our buffer. Nothing to do, process with normal flow - } - } - } - } - - // Accumulate data so far - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - } - else - { - // READ10 & WRITE10 Can be executed with large bulk of data e.g write 8K bytes (several flash write) - // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_EP_BUFSIZE - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - proc_read10_cmd(rhport, p_msc); - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_cmd(rhport, p_msc); - }else - { - // No other command take more than one transfer yet -> unlikely error + // This scenario with command that take more than one transfer is already rejected at Command stage TU_BREAKPOINT(); } } @@ -406,7 +569,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG(MSC_DEBUG, " SCSI Status: %u\r\n", p_csw->status); + TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status); // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); // Invoke complete callback if defined @@ -427,11 +590,11 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; } - // Move to default CMD stage - p_msc->stage = MSC_STAGE_CMD; - - // Queue for the next CBW - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ); + TU_ASSERT( prepare_cbw(rhport, p_msc) ); + }else + { + // Any xfer ended here is consider unknown error, ignore it + TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); } break; @@ -440,22 +603,30 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if ( p_msc->stage == MSC_STAGE_STATUS ) { - // Either endpoints is stalled, need to wait until it is cleared by host - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) || usbd_edpt_stalled(rhport, p_msc->ep_out) ) + // skip status if epin is currently stalled, will do it when received Clear Stall request + if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) { - // simulate an transfer complete with adjusted parameters --> this driver callback will fired again - // and response with status phase after halted endpoints are cleared. - // note: use ep_out to prevent confusing with STATUS complete - dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, XFER_RESULT_SUCCESS, false); + if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) + { + // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status + // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); + usbd_edpt_stall(rhport, p_msc->ep_in); + }else + { + TU_ASSERT( send_csw(rhport, p_msc) ); + } } - else - { - // Move to Status Sent stage - p_msc->stage = MSC_STAGE_STATUS_SENT; - // Send SCSI Status - TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); + #if TU_CHECK_MCU(OPT_MCU_CXD56) + // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. + // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and + // hope everything will work + if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) + { + usbd_edpt_clear_stall(rhport, p_msc->ep_in); + send_csw(rhport, p_msc); } + #endif } return true; @@ -472,6 +643,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ (void) bufsize; // TODO refractor later int32_t resplen; + mscd_interface_t* p_msc = &_mscd_itf; + switch ( scsi_cmd[0] ) { case SCSI_CMD_TEST_UNIT_READY: @@ -482,7 +655,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = - 1; // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); } break; @@ -498,7 +671,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = - 1; // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); } } break; @@ -519,7 +692,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = -1; // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); }else { scsi_read_capacity10_resp_t read_capa10; @@ -555,7 +728,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = -1; // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); }else { read_fmt_capa.block_num = tu_htonl(block_count); @@ -600,9 +773,11 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ }; bool writable = true; - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(lun); + if ( tud_msc_is_writable_cb ) + { + writable = tud_msc_is_writable_cb(lun); } + mode_resp.write_protected = !writable; resplen = sizeof(mode_resp); @@ -620,9 +795,9 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - sense_rsp.sense_key = _mscd_itf.sense_key; - sense_rsp.add_sense_code = _mscd_itf.add_sense_code; - sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; + sense_rsp.sense_key = p_msc->sense_key; + sense_rsp.add_sense_code = p_msc->add_sense_code; + sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; resplen = sizeof(sense_rsp); memcpy(buffer, &sense_rsp, resplen); @@ -641,13 +816,9 @@ 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_csw_t * p_csw = &p_msc->csw; - uint16_t const block_cnt = rdwr10_get_blockcount(p_cbw->command); - TU_ASSERT(block_cnt, ); // prevent div by zero - - uint16_t const block_sz = p_cbw->total_bytes / block_cnt; - TU_ASSERT(block_sz, ); // prevent div by zero + // block size already verified not zero + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // Adjust lba with transferred bytes uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); @@ -656,16 +827,18 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); // Application can consume smaller bytes - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, (uint32_t) nbytes); + 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); if ( nbytes < 0 ) { - // negative means error -> pipe is stalled & status in CSW set to failed - p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len; - p_csw->status = MSC_CSW_STATUS_FAILED; + // negative means error -> endpoint is stalled & status in CSW set to failed + TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation - usbd_edpt_stall(rhport, p_msc->ep_in); + // Sense = Flash not ready for access + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); + + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); } else if ( nbytes == 0 ) { @@ -682,16 +855,18 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { msc_cbw_t const * p_cbw = &p_msc->cbw; bool writable = true; - if (tud_msc_is_writable_cb) { + + if ( tud_msc_is_writable_cb ) + { writable = tud_msc_is_writable_cb(p_cbw->lun); } - if (!writable) { - msc_csw_t* p_csw = &p_msc->csw; - p_csw->data_residue = p_cbw->total_bytes; - p_csw->status = MSC_CSW_STATUS_FAILED; - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); // Sense = Write protected - usbd_edpt_stall(rhport, p_msc->ep_out); + if ( !writable ) + { + // Not writable, complete this SCSI op with error + // Sense = Write protected + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); return; } @@ -702,4 +877,63 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); } +// process new data arrived from WRITE10 +static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) +{ + msc_cbw_t const * p_cbw = &p_msc->cbw; + + // block size already verified not zero + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); + + // Adjust lba with transferred bytes + uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); + + // 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); + + if ( nbytes < 0 ) + { + // negative means error -> failed this scsi op + TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); + + // update actual byte before failed + p_msc->xferred_len += xferred_bytes; + + // Sense = Flash not ready for access + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); + + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // Application consume less than what we got (including zero) + if ( (uint32_t) nbytes < xferred_bytes ) + { + if ( nbytes > 0 ) + { + p_msc->xferred_len += nbytes; + memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes); + } + + // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter + dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false); + } + else + { + // Application consume all bytes in our buffer + p_msc->xferred_len += xferred_bytes; + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + }else + { + // prepare to receive more data from host + proc_write10_cmd(rhport, p_msc); + } + } + } +} + #endif diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 8f90ef4ad..d32694340 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -140,7 +140,7 @@ TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); // Invoked when command in tud_msc_scsi_cb is complete TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); -// Hook to make a mass storage device read-only. TODO remove +// Invoked to check if device is writable as part of SCSI WRITE10 TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 8069353cd..fa6519956 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -263,7 +263,7 @@ bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_ memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb); + return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb); } #if 0 diff --git a/src/class/net/net_device.c b/src/class/net/ecm_rndis_device.c similarity index 98% rename from src/class/net/net_device.c rename to src/class/net/ecm_rndis_device.c index 9d9719ce4..c6cd388e3 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/ecm_rndis_device.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_ECM_RNDIS ) #include "device/usbd.h" #include "device/usbd_pvt.h" @@ -119,6 +119,8 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { + // skip if previous report not yet acknowledged by host + if ( usbd_edpt_busy(TUD_OPT_RHPORT, _netd_itf.ep_notif) ) return; usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); } @@ -407,8 +409,10 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } -bool tud_network_can_xmit(void) +bool tud_network_can_xmit(uint16_t size) { + (void)size; + return can_xmit; } diff --git a/src/class/net/ncm.h b/src/class/net/ncm.h new file mode 100644 index 000000000..96ba11fbc --- /dev/null +++ b/src/class/net/ncm.h @@ -0,0 +1,69 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef _TUSB_NCM_H_ +#define _TUSB_NCM_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +// Table 4.3 Data Class Interface Protocol Codes +typedef enum +{ + NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 +} ncm_data_interface_protocol_code_t; + + +// Table 6.2 Class-Specific Request Codes for Network Control Model subclass +typedef enum +{ + NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, + NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, + NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, + NCM_SET_ETHERNET_PACKET_FILTER = 0x43, + NCM_GET_ETHERNET_STATISTIC = 0x44, + NCM_GET_NTB_PARAMETERS = 0x80, + NCM_GET_NET_ADDRESS = 0x81, + NCM_SET_NET_ADDRESS = 0x82, + NCM_GET_NTB_FORMAT = 0x83, + NCM_SET_NTB_FORMAT = 0x84, + NCM_GET_NTB_INPUT_SIZE = 0x85, + NCM_SET_NTB_INPUT_SIZE = 0x86, + NCM_GET_MAX_DATAGRAM_SIZE = 0x87, + NCM_SET_MAX_DATAGRAM_SIZE = 0x88, + NCM_GET_CRC_MODE = 0x89, + NCM_SET_CRC_MODE = 0x8A, +} ncm_request_code_t; + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c new file mode 100644 index 000000000..3e131a85c --- /dev/null +++ b/src/class/net/ncm_device.c @@ -0,0 +1,510 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jacob Berg Potter + * Copyright (c) 2020 Peter Lawrence + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NCM ) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" +#include "net_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#define NTH16_SIGNATURE 0x484D434E +#define NDP16_SIGNATURE_NCM0 0x304D434E +#define NDP16_SIGNATURE_NCM1 0x314D434E + +typedef struct TU_ATTR_PACKED +{ + uint16_t wLength; + uint16_t bmNtbFormatsSupported; + uint32_t dwNtbInMaxSize; + uint16_t wNdbInDivisor; + uint16_t wNdbInPayloadRemainder; + uint16_t wNdbInAlignment; + uint16_t wReserved; + uint32_t dwNtbOutMaxSize; + uint16_t wNdbOutDivisor; + uint16_t wNdbOutPayloadRemainder; + uint16_t wNdbOutAlignment; + uint16_t wNtbOutMaxDatagrams; +} ntb_parameters_t; + +typedef struct TU_ATTR_PACKED +{ + uint32_t dwSignature; + uint16_t wHeaderLength; + uint16_t wSequence; + uint16_t wBlockLength; + uint16_t wNdpIndex; +} nth16_t; + +typedef struct TU_ATTR_PACKED +{ + uint16_t wDatagramIndex; + uint16_t wDatagramLength; +} ndp16_datagram_t; + +typedef struct TU_ATTR_PACKED +{ + uint32_t dwSignature; + uint16_t wLength; + uint16_t wNextNdpIndex; + ndp16_datagram_t datagram[]; +} ndp16_t; + +typedef union TU_ATTR_PACKED { + struct { + nth16_t nth; + ndp16_t ndp; + }; + uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; +} transmit_ntb_t; + +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +typedef struct +{ + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + + const ndp16_t *ndp; + uint8_t num_datagrams, current_datagram_index; + + enum { + REPORT_SPEED, + REPORT_CONNECTED, + REPORT_DONE + } report_state; + bool report_pending; + + uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams + uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] + uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram + uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE + uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + + uint16_t nth_sequence; // Sequence number counter for transmitted NTBs + + bool transferring; + +} ncm_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static const ntb_parameters_t ntb_parameters = { + .wLength = sizeof(ntb_parameters_t), + .bmNtbFormatsSupported = 0x01, + .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, + .wNdbInDivisor = 4, + .wNdbInPayloadRemainder = 0, + .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, + .wReserved = 0, + .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, + .wNdbOutDivisor = 4, + .wNdbOutPayloadRemainder = 0, + .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, + .wNtbOutMaxDatagrams = 0 +}; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static transmit_ntb_t transmit_ntb[2]; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; + +static ncm_interface_t ncm_interface; + +/* + * Set up the NTB state in ncm_interface to be ready to add datagrams. + */ +static void ncm_prepare_for_tx(void) { + ncm_interface.datagram_count = 0; + // datagrams start after all the headers + ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) + + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); +} + +/* + * If not already transmitting, start sending the current NTB to the host and swap buffers + * to start filling the other one with datagrams. + */ +static void ncm_start_tx(void) { + if (ncm_interface.transferring) { + return; + } + + transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; + size_t ntb_length = ncm_interface.next_datagram_offset; + + // Fill in NTB header + ntb->nth.dwSignature = NTH16_SIGNATURE; + ntb->nth.wHeaderLength = sizeof(nth16_t); + ntb->nth.wSequence = ncm_interface.nth_sequence++; + ntb->nth.wBlockLength = ntb_length; + ntb->nth.wNdpIndex = sizeof(nth16_t); + + // Fill in NDP16 header and terminator + ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; + ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); + ntb->ndp.wNextNdpIndex = 0; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; + + // Kick off an endpoint transfer + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_in, ntb->data, ntb_length); + ncm_interface.transferring = true; + + // Swap to the other NTB and clear it out + ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; + ncm_prepare_for_tx(); +} + +static struct ecm_notify_struct ncm_notify_connected = +{ + .header = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = CDC_NOTIF_NETWORK_CONNECTION, + .wValue = 1 /* Connected */, + .wLength = 0, + }, +}; + +static struct ecm_notify_struct ncm_notify_speed_change = +{ + .header = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, + .wLength = 8, + }, + .downlink = 10000000, + .uplink = 10000000, +}; + +void tud_network_recv_renew(void) +{ + if (!ncm_interface.num_datagrams) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); + return; + } + + const ndp16_t *ndp = ncm_interface.ndp; + const int i = ncm_interface.current_datagram_index; + ncm_interface.current_datagram_index++; + ncm_interface.num_datagrams--; + + tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ + +void netd_init(void) +{ + tu_memclr(&ncm_interface, sizeof(ncm_interface)); + ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; + ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; + ncm_prepare_for_tx(); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + // confirm interface hasn't already been allocated + TU_ASSERT(0 == ncm_interface.ep_notif, 0); + + //------------- Management Interface -------------// + ncm_interface.itf_num = itf_desc->bInterfaceNumber; + + uint16_t drv_len = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); + + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); + + ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface -------------// + // - CDC-NCM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for transfer of NTBs + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); + + do + { + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); + + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); + + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); + + drv_len += 2*sizeof(tusb_desc_endpoint_t); + + return drv_len; +} + +static void ncm_report(void) +{ + if (ncm_interface.report_state == REPORT_SPEED) { + ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); + ncm_interface.report_state = REPORT_CONNECTED; + ncm_interface.report_pending = true; + } else if (ncm_interface.report_state == REPORT_CONNECTED) { + ncm_notify_connected.header.wIndex = ncm_interface.itf_num; + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); + ncm_interface.report_state = REPORT_DONE; + ncm_interface.report_pending = true; + } +} + +TU_ATTR_WEAK void tud_network_link_state_cb(bool state) +{ + (void)state; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage != CONTROL_STAGE_SETUP ) return true; + + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); + + tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); + } + break; + + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; + + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); + + if (req_alt != ncm_interface.itf_data_alt) { + ncm_interface.itf_data_alt = req_alt; + + if (ncm_interface.itf_data_alt) { + if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { + tud_network_recv_renew(); // prepare for incoming datagrams + } + if (!ncm_interface.report_pending) { + ncm_report(); + } + } + + tud_network_link_state_cb(ncm_interface.itf_data_alt); + } + + tud_control_status(rhport, request); + } + break; + + // unsupported request + default: return false; + } + break; + + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (ncm_interface.itf_num == request->wIndex); + + if (NCM_GET_NTB_PARAMETERS == request->bRequest) + { + tud_control_xfer(rhport, request, (void*)&ntb_parameters, sizeof(ntb_parameters)); + } + + break; + + // unsupported request + default: return false; + } + + return true; +} + +static void handle_incoming_datagram(uint32_t len) +{ + uint32_t size = len; + + if (len == 0) { + return; + } + + TU_ASSERT(size >= sizeof(nth16_t), ); + + const nth16_t *hdr = (const nth16_t *)receive_ntb; + TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); + TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); + + const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); + TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); + TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); + + int num_datagrams = (ndp->wLength - 12) / 4; + ncm_interface.current_datagram_index = 0; + ncm_interface.num_datagrams = 0; + ncm_interface.ndp = ndp; + for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) + { + ncm_interface.num_datagrams++; + } + + tud_network_recv_renew(); +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new datagram receive_ntb */ + if (ep_addr == ncm_interface.ep_out ) + { + handle_incoming_datagram(xferred_bytes); + } + + /* data transmission finished */ + if (ep_addr == ncm_interface.ep_in ) + { + if (ncm_interface.transferring) { + ncm_interface.transferring = false; + } + + // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now + if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { + ncm_start_tx(); + } + } + + if (ep_addr == ncm_interface.ep_notif ) + { + ncm_interface.report_pending = false; + ncm_report(); + } + + return true; +} + +// poll network driver for its ability to accept another packet to transmit +bool tud_network_can_xmit(uint16_t size) +{ + TU_VERIFY(ncm_interface.itf_data_alt == 1); + + if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { + TU_LOG2("NTB full [by count]\r\n"); + return false; + } + + size_t next_datagram_offset = ncm_interface.next_datagram_offset; + if (next_datagram_offset + size > ncm_interface.ntb_in_size) { + TU_LOG2("ntb full [by size]\r\n"); + return false; + } + + return true; +} + +void tud_network_xmit(void *ref, uint16_t arg) +{ + transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; + size_t next_datagram_offset = ncm_interface.next_datagram_offset; + + uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); + + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; + + ncm_interface.datagram_count++; + next_datagram_offset += size; + + // round up so the next datagram is aligned correctly + next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); + next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); + + ncm_interface.next_datagram_offset = next_datagram_offset; + + ncm_start_tx(); +} + +#endif diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index f030f3077..6e294465b 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -30,14 +30,36 @@ #include "class/cdc/cdc.h" +#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM +#error "Cannot enable both ECM_RNDIS and NCM network drivers" +#endif + +#include "ncm.h" + /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ #define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -/* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ +/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ #ifndef CFG_TUD_NET_MTU #define CFG_TUD_NET_MTU 1514 #endif +#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE +#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 +#endif + +#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE +#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 +#endif + +#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB +#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 +#endif + +#ifndef CFG_TUD_NCM_ALIGNMENT +#define CFG_TUD_NCM_ALIGNMENT 4 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -46,8 +68,18 @@ // Application API //--------------------------------------------------------------------+ -// client must provide this: initialize any network state back to the beginning -void tud_network_init_cb(void); +// indicate to network driver that client has finished with the packet provided to network_recv_cb() +void tud_network_recv_renew(void); + +// poll network driver for its ability to accept another packet to transmit +bool tud_network_can_xmit(uint16_t size); + +// if network_can_xmit() returns true, network_xmit() can be called once +void tud_network_xmit(void *ref, uint16_t arg); + +//--------------------------------------------------------------------+ +// Application Callbacks (WEAK is optional) +//--------------------------------------------------------------------+ // client must provide this: return false if the packet buffer was not accepted bool tud_network_recv_cb(const uint8_t *src, uint16_t size); @@ -55,18 +87,19 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size); // client must provide this: copy from network stack packet pointer to dst uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); +//------------- ECM/RNDIS -------------// + +// client must provide this: initialize any network state back to the beginning +void tud_network_init_cb(void); + // client must provide this: 48-bit MAC address // TODO removed later since it is not part of tinyusb stack extern const uint8_t tud_network_mac_address[6]; -// indicate to network driver that client has finished with the packet provided to network_recv_cb() -void tud_network_recv_renew(void); +//------------- NCM -------------// -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(void); - -// if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(void *ref, uint16_t arg); +// callback to client providing optional indication of internal state of network driver +void tud_network_link_state_cb(bool state); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index c1ee49f45..4bd1edf12 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -1,10 +1,3 @@ -/* - * usbtmc.c - * - * Created on: Sep 9, 2019 - * Author: nconrad - */ - /* * The MIT License (MIT) * @@ -205,7 +198,7 @@ bool tud_usbtmc_transmit_dev_msg_data( { TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t*)data)[len-1u] == termChar); + TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); } #endif @@ -228,7 +221,7 @@ bool tud_usbtmc_transmit_dev_msg_data( memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); usbtmc_state.transfer_size_remaining = len - dataLen; usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t*)data + (dataLen); + usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); bool stateChanged = atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); @@ -287,7 +280,7 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; switch(ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: - TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE, 0); + TU_ASSERT(tu_edpt_packet_size(ep_desc) == USBTMCD_MAX_PACKET_SIZE, 0); if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; @@ -508,13 +501,13 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_OUT: TU_VERIFY(false); return false; // Should be stalled by now, shouldn't have received a packet. + case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: case STATE_ABORTING_BULK_IN_SHORTED: case STATE_ABORTING_BULK_IN_ABORTED: default: - TU_VERIFY(false); } } @@ -528,37 +521,40 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { + { // FIXME! This removes const below! TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, - (void*)usbtmc_state.devInBuffer,sizeof(usbtmc_state.ep_bulk_in_buf))); + (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + } + else // last packet + { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; } } return true; + case STATE_ABORTING_BULK_IN: // need to send short packet (ZLP?) TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; return true; + case STATE_ABORTING_BULK_IN_SHORTED: /* Done. :)*/ usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; + return true; + default: TU_ASSERT(false); return false; @@ -787,7 +783,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); return true; } // USBTMC Optional Requests diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 622800315..0549a1569 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -1,9 +1,3 @@ -/* - * usbtmc_device.h - * - * Created on: Sep 10, 2019 - * Author: nconrad - */ /* * The MIT License (MIT) * diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8c59b4ea7..8a4ca1d2e 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -175,12 +175,12 @@ void vendord_reset(uint8_t rhport) } } -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0); + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_VERIFY(max_len >= drv_len, 0); + uint8_t const * p_desc = tu_desc_next(desc_itf); + uint8_t const * desc_end = p_desc + max_len; // Find available interface vendord_interface_t* p_vendor = NULL; @@ -194,21 +194,30 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui } TU_VERIFY(p_vendor, 0); - // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); - - p_vendor->itf_num = itf_desc->bInterfaceNumber; - - // Prepare for incoming data - if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) + p_vendor->itf_num = desc_itf->bInterfaceNumber; + if (desc_itf->bNumEndpoints) { - TU_LOG_FAILED(); - TU_BREAKPOINT(); + // skip non-endpoint descriptors + while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) + { + p_desc = tu_desc_next(p_desc); + } + + // Open endpoint pair with usbd helper + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); + + p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + + // Prepare for incoming data + if ( p_vendor->ep_out ) + { + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), 0); + } + + if ( p_vendor->ep_in ) maybe_transmit(p_vendor); } - maybe_transmit(p_vendor); - - return drv_len; + return (uintptr_t) p_desc - (uintptr_t) desc_itf; } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 844693c68..d71c2a3e9 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -44,7 +44,7 @@ bool tud_vendor_n_mounted (uint8_t itf); uint32_t tud_vendor_n_available (uint8_t itf); uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, uint8_t* u8); +bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); void tud_vendor_n_read_flush (uint8_t itf); uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); @@ -59,7 +59,7 @@ uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); static inline bool tud_vendor_mounted (void); static inline uint32_t tud_vendor_available (void); static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (uint8_t* u8); +static inline bool tud_vendor_peek (uint8_t* ui8); static inline void tud_vendor_read_flush (void); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); @@ -96,9 +96,9 @@ static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) return tud_vendor_n_read(0, buffer, bufsize); } -static inline bool tud_vendor_peek (uint8_t* u8) +static inline bool tud_vendor_peek (uint8_t* ui8) { - return tud_vendor_n_peek(0, u8); + return tud_vendor_n_peek(0, ui8); } static inline void tud_vendor_read_flush(void) diff --git a/src/class/video/video.h b/src/class/video/video.h new file mode 100644 index 000000000..844746546 --- /dev/null +++ b/src/class/video/video.h @@ -0,0 +1,480 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * + * 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_VIDEO_H_ +#define TUSB_VIDEO_H_ + +#include "common/tusb_common.h" + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, + VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) + VIDEO_COLOR_PRIMARIES_BT470_2M, + VIDEO_COLOR_PRIMARIES_BT470_2BG, + VIDEO_COLOR_PRIMARIES_SMPTE170M, + VIDEO_COLOR_PRIMARIES_SMPTE240M, +} video_color_primaries_t; + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, + VIDEO_COLOR_XFER_CH_BT709, // default + VIDEO_COLOR_XFER_CH_BT470_2M, + VIDEO_COLOR_XFER_CH_BT470_2BG, + VIDEO_COLOR_XFER_CH_SMPTE170M, + VIDEO_COLOR_XFER_CH_SMPTE240M, + VIDEO_COLOR_XFER_CH_LINEAR, + VIDEO_COLOR_XFER_CH_SRGB, +} video_color_transfer_characteristics_t; + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_COEF_UNDEFINED = 0x00, + VIDEO_COLOR_COEF_BT709, + VIDEO_COLOR_COEF_FCC, + VIDEO_COLOR_COEF_BT470_2BG, + VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default + VIDEO_COLOR_COEF_SMPTE240M, +} video_color_matrix_coefficients_t; + +/* 4.2.1.2 Request Error Code Control */ +typedef enum { + VIDEO_ERROR_NONE = 0, /* The request succeeded. */ + VIDEO_ERROR_NOT_READY, + VIDEO_ERROR_WRONG_STATE, + VIDEO_ERROR_POWER, + VIDEO_ERROR_OUT_OF_RANGE, + VIDEO_ERROR_INVALID_UNIT, + VIDEO_ERROR_INVALID_CONTROL, + VIDEO_ERROR_INVALID_REQUEST, + VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, + VIDEO_ERROR_UNKNOWN = 0xFF, +} video_error_code_t; + +/* A.2 Interface Subclass */ +typedef enum { + VIDEO_SUBCLASS_UNDEFINED = 0x00, + VIDEO_SUBCLASS_CONTROL, + VIDEO_SUBCLASS_STREAMING, + VIDEO_SUBCLASS_INTERFACE_COLLECTION, +} video_subclass_type_t; + +/* A.3 Interface Protocol */ +typedef enum { + VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, + VIDEO_ITF_PROTOCOL_15, +} video_interface_protocol_code_t; + +/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ +typedef enum { + VIDEO_CS_ITF_VC_UNDEFINED = 0x00, + VIDEO_CS_ITF_VC_HEADER, + VIDEO_CS_ITF_VC_INPUT_TERMINAL, + VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + VIDEO_CS_ITF_VC_SELECTOR_UNIT, + VIDEO_CS_ITF_VC_PROCESSING_UNIT, + VIDEO_CS_ITF_VC_EXTENSION_UNIT, + VIDEO_CS_ITF_VC_ENCODING_UNIT, + VIDEO_CS_ITF_VC_MAX, +} video_cs_vc_interface_subtype_t; + +/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ +typedef enum { + VIDEO_CS_ITF_VS_UNDEFINED = 0x00, + VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, + VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, + VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, + VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, + VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, + VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, + VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, + VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, + VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, + VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, + VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, + VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, + VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, + VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, + VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, + VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, + VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, + VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, + VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, +} video_cs_vs_interface_subtype_t; + +/* A.7. Class-Specific Endpoint Descriptor Subtypes */ +typedef enum { + VIDEO_CS_EP_UNDEFINED = 0x00, + VIDEO_CS_EP_GENERAL, + VIDEO_CS_EP_ENDPOINT, + VIDEO_CS_EP_INTERRUPT +} video_cs_ep_subtype_t; + +/* A.8 Class-Specific Request Codes */ +typedef enum { + VIDEO_REQUEST_UNDEFINED = 0x00, + VIDEO_REQUEST_SET_CUR = 0x01, + VIDEO_REQUEST_SET_CUR_ALL = 0x11, + VIDEO_REQUEST_GET_CUR = 0x81, + VIDEO_REQUEST_GET_MIN = 0x82, + VIDEO_REQUEST_GET_MAX = 0x83, + VIDEO_REQUEST_GET_RES = 0x84, + VIDEO_REQUEST_GET_LEN = 0x85, + VIDEO_REQUEST_GET_INFO = 0x86, + VIDEO_REQUEST_GET_DEF = 0x87, + VIDEO_REQUEST_GET_CUR_ALL = 0x91, + VIDEO_REQUEST_GET_MIN_ALL = 0x92, + VIDEO_REQUEST_GET_MAX_ALL = 0x93, + VIDEO_REQUEST_GET_RES_ALL = 0x94, + VIDEO_REQUEST_GET_DEF_ALL = 0x97 +} video_control_request_t; + +/* A.9.1 VideoControl Interface Control Selectors */ +typedef enum { + VIDEO_VC_CTL_UNDEFINED = 0x00, + VIDEO_VC_CTL_VIDEO_POWER_MODE, + VIDEO_VC_CTL_REQUEST_ERROR_CODE, +} video_interface_control_selector_t; + +/* A.9.8 VideoStreaming Interface Control Selectors */ +typedef enum { + VIDEO_VS_CTL_UNDEFINED = 0x00, + VIDEO_VS_CTL_PROBE, + VIDEO_VS_CTL_COMMIT, + VIDEO_VS_CTL_STILL_PROBE, + VIDEO_VS_CTL_STILL_COMMIT, + VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, + VIDEO_VS_CTL_STREAM_ERROR_CODE, + VIDEO_VS_CTL_GENERATE_KEY_FRAME, + VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, + VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, +} video_interface_streaming_selector_t; + +/* B. Terminal Types */ +typedef enum { + // Terminal + VIDEO_TT_VENDOR_SPECIFIC = 0x0100, + VIDEO_TT_STREAMING = 0x0101, + + // Input + VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, + VIDEO_ITT_CAMERA = 0x0201, + VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, + + // Output + VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, + VIDEO_OTT_DISPLAY = 0x0301, + VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, + + // External + VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, + VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, + VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, + VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, +} video_terminal_type_t; + +//--------------------------------------------------------------------+ +// Descriptors +//--------------------------------------------------------------------+ + +/* 2.3.4.2 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint16_t bcdUVC; + uint16_t wTotalLength; + uint32_t dwClockFrequency; + uint8_t bInCollection; + uint8_t baInterfaceNr[]; +} tusb_desc_cs_video_ctl_itf_hdr_t; + +/* 2.4.3.3 */ +typedef struct TU_ATTR_PACKED { + uint8_t bHeaderLength; + union { + uint8_t bmHeaderInfo; + struct { + uint8_t FrameID: 1; + uint8_t EndOfFrame: 1; + uint8_t PresentationTime: 1; + uint8_t SourceClockReference: 1; + uint8_t PayloadSpecific: 1; + uint8_t StillImage: 1; + uint8_t Error: 1; + uint8_t EndOfHeader: 1; + }; + }; +} tusb_video_payload_header_t; + +/* 3.9.2.1 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bmInfo; + uint8_t bTerminalLink; + uint8_t bStillCaptureMethod; + uint8_t bTriggerSupport; + uint8_t bTriggerUsage; + uint8_t bControlSize; + uint8_t bmaControls[]; +} tusb_desc_cs_video_stm_itf_in_hdr_t; + +/* 3.9.2.2 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bTerminalLink; + uint8_t bControlSize; + uint8_t bmaControls[]; +} tusb_desc_cs_video_stm_itf_out_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + union { + struct { + uint8_t bmInfo; + uint8_t bTerminalLink; + uint8_t bStillCaptureMethod; + uint8_t bTriggerSupport; + uint8_t bTriggerUsage; + uint8_t bControlSize; + uint8_t bmaControls[]; + } input; + struct { + uint8_t bEndpointAddress; + uint8_t bTerminalLink; + uint8_t bControlSize; + uint8_t bmaControls[]; + } output; + }; +} tusb_desc_cs_video_stm_itf_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bNumFrameDescriptors; + uint8_t guidFormat[16]; + uint8_t bBitsPerPixel; + uint8_t bDefaultFrameIndex; + uint8_t bAspectRatioX; + uint8_t bAspectRatioY; + uint8_t bmInterlaceFlags; + uint8_t bCopyProtect; +} tusb_desc_cs_video_fmt_uncompressed_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFrameIndex; + uint8_t bmCapabilities; + uint16_t wWidth; + uint16_t wHeight; + uint32_t dwMinBitRate; + uint32_t dwMaxBitRate; + uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ + uint32_t dwDefaultFrameInterval; + uint8_t bFrameIntervalType; + uint32_t dwFrameInterval[]; +} tusb_desc_cs_video_frm_uncompressed_t; + +//--------------------------------------------------------------------+ +// Requests +//--------------------------------------------------------------------+ + +/* 4.3.1.1 */ +typedef struct TU_ATTR_PACKED { + union { + uint8_t bmHint; + struct TU_ATTR_PACKED { + uint16_t dwFrameInterval: 1; + uint16_t wKeyFrameRatel : 1; + uint16_t wPFrameRate : 1; + uint16_t wCompQuality : 1; + uint16_t wCompWindowSize: 1; + uint16_t : 0; + } Hint; + }; + uint8_t bFormatIndex; + uint8_t bFrameIndex; + uint32_t dwFrameInterval; + uint16_t wKeyFrameRate; + uint16_t wPFrameRate; + uint16_t wCompQuality; + uint16_t wCompWindowSize; + uint16_t wDelay; + uint32_t dwMaxVideoFrameSize; + uint32_t dwMaxPayloadTransferSize; + uint32_t dwClockFrequency; + union { + uint8_t bmFramingInfo; + struct TU_ATTR_PACKED { + uint8_t FrameID : 1; + uint8_t EndOfFrame: 1; + uint8_t EndOfSlice: 1; + uint8_t : 0; + } FramingInfo; + }; + uint8_t bPreferedVersion; + uint8_t bMinVersion; + uint8_t bMaxVersion; + uint8_t bUsage; + uint8_t bBitDepthLuma; + uint8_t bmSettings; + uint8_t bMaxNumberOfRefFramesPlus1; + uint16_t bmRateControlModes; + uint64_t bmLayoutPerStream; +} video_probe_and_commit_control_t; + +TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); + +#define TUD_VIDEO_DESC_IAD_LEN 8 +#define TUD_VIDEO_DESC_STD_VC_LEN 9 +#define TUD_VIDEO_DESC_CS_VC_LEN 12 +#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 +#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 +#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 +#define TUD_VIDEO_DESC_STD_VS_LEN 9 +#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 +#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 +#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 +#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 + +/* 2.2 compression formats */ +#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 + +#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ + _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ + VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx + +#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ + TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ + _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx + +/* 3.7.2 */ +#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ + U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ + U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ + +/* 3.7.2.1 */ +#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ + TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(_tt), _at, _stridx + +/* 3.7.2.2 */ +#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx + +/* 3.7.2.3 */ +#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ + TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ + U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ + TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) + +/* 3.9.1 */ +#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ + TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ + _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx + +/* 3.9.2.1 */ +#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ + VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ + U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ + _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* 3.9.2.2 */ +#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ + VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ + U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ + _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* Uncompressed 3.1.1 */ +#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 + +#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ + _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ + _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ + _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp + +/* Uncompressed 3.1.2 Table 3-3 */ +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ + _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ + U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ + U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) + +/* Uncompressed 3.1.2 Table 3-4 */ +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ + TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ + _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ + U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* 3.9.2.6 */ +#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ + TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ + _color, _trns, _mat + +/* 3.10.1.1 */ +#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ + 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS,\ + U16_TO_U8S_LE(_epsize), _ep_interval + +/* 3.10.1.2 */ +#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ + 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval + +#endif diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c new file mode 100644 index 000000000..eeb068197 --- /dev/null +++ b/src/class/video/video_device.c @@ -0,0 +1,1149 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "video_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + tusb_desc_interface_t std; + tusb_desc_cs_video_ctl_itf_hdr_t ctl; +} tusb_desc_vc_itf_t; + +typedef struct { + tusb_desc_interface_t std; + tusb_desc_cs_video_stm_itf_hdr_t stm; +} tusb_desc_vs_itf_t; + +typedef union { + tusb_desc_cs_video_ctl_itf_hdr_t ctl; + tusb_desc_cs_video_stm_itf_hdr_t stm; +} tusb_desc_video_itf_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bEntityId; +} tusb_desc_cs_video_entity_itf_t; + +/* video streaming interface */ +typedef struct TU_ATTR_PACKED { + uint8_t index_vc; /* index of bound video control interface */ + uint8_t index_vs; /* index from the video control interface */ + struct { + uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ + uint16_t end; /* Offset of the end of video streaming interface descriptor */ + uint16_t cur; /* Offset of the current settings */ + uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ + } desc; + uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ + uint32_t bufsize; /* frame buffer size */ + uint32_t offset; /* offset for the next payload transfer */ + uint32_t max_payload_transfer_size; + uint8_t error_code;/* error code */ + /*------------- From this point, data is not cleared by bus reset -------------*/ + CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ +} videod_streaming_interface_t; + +/* video control interface */ +typedef struct TU_ATTR_PACKED { + void const *beg; /* The head of the first video control interface descriptor */ + uint16_t len; /* Byte length of the descriptors */ + uint16_t cur; /* offset for current video control interface */ + uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ + uint8_t error_code; /* error code */ + uint8_t power_mode; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ + +} videod_interface_t; + +#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; +CFG_TUSB_MEM_SECTION static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; + +static uint8_t const _cap_get = 0x1u; /* support for GET */ +static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ + +/** Get interface number from the interface descriptor + * + * @param[in] desc interface descriptor + * + * @return bInterfaceNumber */ +static inline uint8_t _desc_itfnum(void const *desc) +{ + return ((uint8_t const*)desc)[2]; +} + +/** Get endpoint address from the endpoint descriptor + * + * @param[in] desc endpoint descriptor + * + * @return bEndpointAddress */ +static inline uint8_t _desc_ep_addr(void const *desc) +{ + return ((uint8_t const*)desc)[2]; +} + +/** Get instance of streaming interface + * + * @param[in] ctl_idx instance number of video control + * @param[in] stm_idx index number of streaming interface + * + * @return instance */ +static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) +{ + videod_interface_t *ctl = &_videod_itf[ctl_idx]; + if (!ctl->beg) return NULL; + videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; + if (!stm->desc.beg) return NULL; + return stm; +} + +static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) +{ + return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); +} + +static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) +{ + if (!self->desc.cur) return NULL; + void const *desc = _videod_itf[self->index_vc].beg; + return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); +} + +/** Find the first descriptor of a given type + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] desc_type The target descriptor type. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) +{ + void const *cur = beg; + while ((cur < end) && (desc_type != tu_desc_type(cur))) { + cur = tu_desc_next(cur); + } + return cur; +} + +/** Find the first descriptor specified by the arguments + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] desc_type The target descriptor type + * @param[in] element_0 The target element following the desc_type + * @param[in] element_1 The target element following the element_0 + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc_3(void const *beg, void const *end, + uint_fast8_t desc_type, + uint_fast8_t element_0, + uint_fast8_t element_1) +{ + for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { + uint8_t const *p = (uint8_t const *)cur; + if ((p[2] == element_0) && (p[3] == element_1)) { + return cur; + } + cur = tu_desc_next(cur); + } + return end; +} + +/** Return the next interface descriptor which has another interface number. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _next_desc_itf(void const *beg, void const *end) +{ + void const *cur = beg; + uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; + while ((cur < end) && + (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { + cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); + } + return cur; +} + +/** Find the first interface descriptor with the specified interface number and alternate setting number. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] itfnum The target interface number. + * @param[in] altnum The target alternate setting number. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static inline void const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) +{ + return _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); +} + +/** Find the first endpoint descriptor belonging to the current interface descriptor. + * + * The search range is from `beg` to `end` or the next interface descriptor. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * + * @return The pointer for endpoint descriptor. + * @retval end did not found endpoint descriptor */ +static void const* _find_desc_ep(void const *beg, void const *end) +{ + for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { + uint_fast8_t desc_type = tu_desc_type(cur); + if (TUSB_DESC_ENDPOINT == desc_type) return cur; + if (TUSB_DESC_INTERFACE == desc_type) break; + } + return end; +} + +/** Find the first entity descriptor with the entity ID + * specified by the argument belonging to the current video control descriptor. + * + * @param[in] desc The video control interface descriptor. + * @param[in] entityid The target entity id. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) +{ + tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const*)desc; + void const *beg = vc; + void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength; + for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { + tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; + if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype + && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) + && itf->bEntityId == entityid) { + return itf; + } + cur = tu_desc_next(cur); + } + return end; +} + +/** Return the end of the video streaming descriptor. */ +static inline void const* _end_of_streaming_descriptor(void const *desc) +{ + tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; + return desc + vs->std.bLength + vs->stm.wTotalLength; +} + +/** Find the first format descriptor with the specified format number. */ +static inline tusb_desc_cs_video_fmt_uncompressed_t const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) +{ + return (tusb_desc_cs_video_fmt_uncompressed_t const*) + _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, fmtnum); +} + +/** Find the first frame descriptor with the specified format number. */ +static inline tusb_desc_cs_video_frm_uncompressed_t const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) +{ + return (tusb_desc_cs_video_frm_uncompressed_t const*) + _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, frmnum); +} + +/** Set uniquely determined values to variables that have not been set + * + * @param[in,out] param Target */ +static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, + video_probe_and_commit_control_t *param) +{ + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + uint_fast8_t fmtnum = param->bFormatIndex; + TU_ASSERT(fmtnum <= vs->stm.bNumFormats); + if (!fmtnum) { + if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ + fmtnum = 1; + param->bFormatIndex = 1; + } + + /* Set the parameters determined by the format */ + param->wKeyFrameRate = 1; + param->wPFrameRate = 0; + param->wCompQuality = 1; /* 1 to 10000 */ + param->wCompWindowSize = 1; /* GOP size? */ + param->wDelay = 0; /* milliseconds */ + param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ + param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ + param->bPreferedVersion = 1; + param->bMinVersion = 1; + param->bMaxVersion = 1; + param->bUsage = 0; + param->bBitDepthLuma = 8; + + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + TU_ASSERT(fmt != end); + uint_fast8_t frmnum = param->bFrameIndex; + TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); + if (!frmnum) { + if (1 < fmt->bNumFrameDescriptors) return true; + frmnum = 1; + param->bFrameIndex = 1; + } + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + TU_ASSERT(frm != end); + + /* Set the parameters determined by the frame */ + uint_fast32_t frame_size = param->dwMaxVideoFrameSize; + if (!frame_size) { + frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; + param->dwMaxVideoFrameSize = frame_size; + } + + uint_fast32_t interval = param->dwFrameInterval; + if (!interval) { + if ((1 < frm->bFrameIntervalType) || + ((0 == frm->bFrameIntervalType) && (frm->dwFrameInterval[1] != frm->dwFrameInterval[0]))) { + return true; + } + interval = frm->dwFrameInterval[0]; + param->dwFrameInterval = interval; + } + uint_fast32_t interval_ms = interval / 10000; + TU_ASSERT(interval_ms); + uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; + param->dwMaxPayloadTransferSize = payload_size; + return true; +} + +/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host + * + * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF + * @param[in,out] param Target + */ +static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, + video_probe_and_commit_control_t *param) +{ + uint_fast8_t const fmtnum = param->bFormatIndex; + if (!fmtnum) { + switch (request) { + case VIDEO_REQUEST_GET_MAX: + param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; + break; + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_DEF: + param->bFormatIndex = 1; + break; + default: return false; + } + /* Set the parameters determined by the format */ + param->wKeyFrameRate = 1; + param->wPFrameRate = 0; + param->wCompQuality = 1; /* 1 to 10000 */ + param->wCompWindowSize = 1; /* GOP size? */ + param->wDelay = 0; /* milliseconds */ + param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ + param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ + param->bPreferedVersion = 1; + param->bMinVersion = 1; + param->bMaxVersion = 1; + param->bUsage = 0; + param->bBitDepthLuma = 8; + return true; + } + + uint_fast8_t frmnum = param->bFrameIndex; + if (!frmnum) { + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + switch (request) { + case VIDEO_REQUEST_GET_MAX: + frmnum = fmt->bNumFrameDescriptors; + break; + case VIDEO_REQUEST_GET_MIN: + frmnum = 1; + break; + case VIDEO_REQUEST_GET_DEF: + frmnum = fmt->bDefaultFrameIndex; + break; + default: return false; + } + param->bFrameIndex = frmnum; + /* Set the parameters determined by the frame */ + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + param->dwMaxVideoFrameSize = frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; + return true; + } + + if (!param->dwFrameInterval) { + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + + uint_fast32_t interval, interval_ms; + switch (request) { + case VIDEO_REQUEST_GET_MAX: + { + uint_fast32_t min_interval, max_interval; + uint_fast8_t num_intervals = frm->bFrameIntervalType; + max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; + min_interval = frm->dwFrameInterval[0]; + interval = max_interval; + interval_ms = min_interval / 10000; + } + break; + case VIDEO_REQUEST_GET_MIN: + { + uint_fast32_t min_interval, max_interval; + uint_fast8_t num_intervals = frm->bFrameIntervalType; + max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; + min_interval = frm->dwFrameInterval[0]; + interval = min_interval; + interval_ms = max_interval / 10000; + } + break; + case VIDEO_REQUEST_GET_DEF: + interval = frm->dwDefaultFrameInterval; + interval_ms = interval / 10000; + break; + case VIDEO_REQUEST_GET_RES: + { + uint_fast8_t num_intervals = frm->bFrameIntervalType; + if (num_intervals) { + interval = 0; + } else { + interval = frm->dwFrameInterval[2]; + interval_ms = interval / 10000; + } + } + break; + default: return false; + } + param->dwFrameInterval = interval; + if (!interval) { + param->dwMaxPayloadTransferSize = 0; + } else { + uint_fast32_t frame_size = param->dwMaxVideoFrameSize; + if (!interval_ms) { + param->dwMaxPayloadTransferSize = frame_size + 2; + } else { + param->dwMaxPayloadTransferSize = (frame_size + interval_ms - 1) / interval_ms + 2; + } + } + return true; + } + return true; +} + +/** Close current video control interface. + * + * @param[in,out] self Video control interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) +{ + tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); + /* The next descriptor after the class-specific VC interface header descriptor. */ + void const *cur = (void const*)vc + vc->std.bLength + vc->ctl.bLength; + /* The end of the video control interface descriptor. */ + void const *end = (void const*)vc + vc->std.bLength + vc->ctl.wTotalLength; + if (vc->std.bNumEndpoints) { + /* Find the notification endpoint descriptor. */ + cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); + TU_ASSERT(cur < end); + tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; + usbd_edpt_close(rhport, notif->bEndpointAddress); + } + self->cur = 0; + return true; +} + +/** Set the alternate setting to own video control interface. + * + * @param[in,out] self Video control interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) +{ + TU_LOG2(" open VC %d\n", altnum); + void const *beg = self->beg; + void const *end = beg + self->len; + /* The first descriptor is a video control interface descriptor. */ + void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); + TU_LOG2(" cur %d\n", cur - beg); + TU_VERIFY(cur < end); + + tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; + TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); + /* Support for up to 2 streaming interfaces only. */ + TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); + + /* Update to point the end of the video control interface descriptor. */ + end = cur + vc->std.bLength + vc->ctl.wTotalLength; + /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ + cur += vc->std.bLength + vc->ctl.bLength; + TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); + /* Open the notification endpoint if it exist. */ + if (vc->std.bNumEndpoints) { + /* Support for 1 endpoint only. */ + TU_VERIFY(1 == vc->std.bNumEndpoints); + /* Find the notification endpoint descriptor. */ + cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); + TU_VERIFY(cur < end); + tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; + /* Open the notification endpoint */ + TU_ASSERT(usbd_edpt_open(rhport, notif)); + } + self->cur = (void const*)vc - beg; + return true; +} + +/** Set the alternate setting to own video streaming interface. + * + * @param[in,out] stm Streaming interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) +{ + uint_fast8_t i; + TU_LOG2(" reopen VS %d\n", altnum); + void const *desc = _videod_itf[stm->index_vc].beg; + + /* Close endpoints of previous settings. */ + for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { + uint_fast16_t ofs_ep = stm->desc.ep[i]; + if (!ofs_ep) break; + uint_fast8_t ep_adr = _desc_ep_addr(desc + ofs_ep); + usbd_edpt_close(rhport, ep_adr); + stm->desc.ep[i] = 0; + TU_LOG2(" close EP%02x\n", ep_adr); + } + /* clear transfer management information */ + stm->buffer = NULL; + stm->bufsize = 0; + stm->offset = 0; + + /* Find a alternate interface */ + void const *beg = desc + stm->desc.beg; + void const *end = desc + stm->desc.end; + void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); + TU_VERIFY(cur < end); + uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; + TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); + stm->desc.cur = cur - desc; /* Save the offset of the new settings */ + if (!altnum) { + /* initialize streaming settings */ + stm->max_payload_transfer_size = 0; + video_probe_and_commit_control_t *param = + (video_probe_and_commit_control_t *)&stm->ep_buf; + tu_memclr(param, sizeof(*param)); + return _update_streaming_parameters(stm, param); + } + /* Open endpoints of the new settings. */ + for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { + cur = _find_desc_ep(cur, end); + TU_ASSERT(cur < end); + tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; + if (!stm->max_payload_transfer_size) { + video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; + uint_fast32_t max_size = param->dwMaxPayloadTransferSize; + if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && + (tu_edpt_packet_size(ep) < max_size)) + { + /* FS must be less than or equal to max packet size */ + return false; + } + /* Set the negotiated value */ + stm->max_payload_transfer_size = max_size; + } + TU_ASSERT(usbd_edpt_open(rhport, ep)); + stm->desc.ep[i] = cur - desc; + TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); + } + /* initialize payload header */ + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->bHeaderLength = sizeof(*hdr); + hdr->bmHeaderInfo = 0; + + return true; +} + +/** Prepare the next packet payload. */ +static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) +{ + uint_fast16_t remaining = stm->bufsize - stm->offset; + uint_fast16_t hdr_len = stm->ep_buf[0]; + uint_fast16_t pkt_len = stm->max_payload_transfer_size; + if (hdr_len + remaining < pkt_len) { + pkt_len = hdr_len + remaining; + } + uint_fast16_t data_len = pkt_len - hdr_len; + memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); + stm->offset += data_len; + remaining -= data_len; + if (!remaining) { + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->EndOfFrame = 1; + } + return hdr_len + data_len; +} + +/** Handle a standard request to the video control interface. */ +static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + switch (request->bRequest) { + case TUSB_REQ_GET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); + TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); + + uint8_t alt_num = vc->std.bAlternateSetting; + + TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case TUSB_REQ_SET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); + TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); + tud_control_status(rhport, request); + } + return VIDEO_ERROR_NONE; + + default: /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + videod_interface_t *self = &_videod_itf[ctl_idx]; + + /* 4.2.1 Interface Control Request */ + switch (TU_U16_HIGH(request->wValue)) { + case VIDEO_VC_CTL_VIDEO_POWER_MODE: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VC_CTL_REQUEST_ERROR_CODE: + switch (request->bRequest) { + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + default: break; + } + + /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; +} + +static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + uint_fast8_t entity_id; + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_STANDARD: + return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); + + case TUSB_REQ_TYPE_CLASS: + entity_id = TU_U16_HIGH(request->wIndex); + if (!entity_id) { + return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); + } else { + TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); + return VIDEO_ERROR_NONE; + } + + default: + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; + switch (request->bRequest) { + case TUSB_REQ_GET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); + TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); + uint8_t alt_num = vs->std.bAlternateSetting; + + TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case TUSB_REQ_SET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); + tud_control_status(rhport, request); + } + return VIDEO_ERROR_NONE; + + default: /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + (void)rhport; + videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; + + /* 4.2.1 Interface Control Request */ + switch (TU_U16_HIGH(request->wValue)) { + case VIDEO_VS_CTL_STREAM_ERROR_CODE: + switch (request->bRequest) { + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + /* TODO */ + TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_PROBE: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), + VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), + VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_MAX: + case VIDEO_REQUEST_GET_RES: + case VIDEO_REQUEST_GET_DEF: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + video_probe_and_commit_control_t tmp; + tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; + TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_LEN: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); + uint16_t len = sizeof(video_probe_and_commit_control_t); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_COMMIT: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + if (tud_video_commit_cb) { + return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); + } + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_LEN: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); + uint16_t len = sizeof(video_probe_and_commit_control_t); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_STILL_PROBE: + case VIDEO_VS_CTL_STILL_COMMIT: + case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: + case VIDEO_VS_CTL_GENERATE_KEY_FRAME: + case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: + case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: + /* TODO */ + break; + + default: break; + } + + /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; +} + +static int handle_video_stm_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_STANDARD: + return handle_video_stm_std_req(rhport, stage, request, stm_idx); + + case TUSB_REQ_TYPE_CLASS: + if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; + return handle_video_stm_cs_req(rhport, stage, request, stm_idx); + + default: return VIDEO_ERROR_INVALID_REQUEST; + } + return VIDEO_ERROR_UNKNOWN; +} + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ + +bool tud_video_n_connected(uint_fast8_t ctl_idx) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); + if (stm) return true; + return false; +} + +bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); + if (!stm || !stm->desc.ep[0]) return false; + return true; +} + +bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); + if (!buffer || !bufsize) return false; + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); + if (!stm || !stm->desc.ep[0] || stm->buffer) return false; + + /* Find EP address */ + void const *desc = _videod_itf[stm->index_vc].beg; + uint_fast8_t ep_addr = 0; + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + uint_fast16_t ofs_ep = stm->desc.ep[i]; + if (!ofs_ep) continue; + ep_addr = _desc_ep_addr(desc + ofs_ep); + break; + } + if (!ep_addr) return false; + + TU_VERIFY( usbd_edpt_claim(0, ep_addr)); + /* update the packet header */ + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->FrameID ^= 1; + hdr->EndOfFrame = 0; + /* update the packet data */ + stm->buffer = (uint8_t*)buffer; + stm->bufsize = bufsize; + uint_fast16_t pkt_len = _prepare_in_payload(stm); + TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0); + return true; +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void videod_init(void) +{ + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { + videod_interface_t* ctl = &_videod_itf[i]; + tu_memclr(ctl, sizeof(*ctl)); + } + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; + tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); + } +} + +void videod_reset(uint8_t rhport) +{ + (void) rhport; + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { + videod_interface_t* ctl = &_videod_itf[i]; + tu_memclr(ctl, sizeof(*ctl)); + } + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; + tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); + } +} + +uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && + (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && + (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); + + /* Find available interface */ + videod_interface_t *self = NULL; + uint_fast8_t ctl_idx; + for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { + if (_videod_itf[ctl_idx].beg) continue; + self = &_videod_itf[ctl_idx]; + break; + } + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); + + void const *end = (void const*)itf_desc + max_len; + self->beg = itf_desc; + self->len = max_len; + /*------------- Video Control Interface -------------*/ + TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); + tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); + uint_fast8_t bInCollection = vc->ctl.bInCollection; + /* Find the end of the video interface descriptor */ + void const *cur = _next_desc_itf(itf_desc, end); + for (uint_fast8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { + videod_streaming_interface_t *stm = NULL; + /* find free streaming interface handle */ + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + if (_videod_streaming_itf[i].desc.beg) continue; + stm = &_videod_streaming_itf[i]; + self->stm[stm_idx] = i; + break; + } + TU_ASSERT(stm, 0); + stm->index_vc = ctl_idx; + stm->index_vs = stm_idx; + stm->desc.beg = (uintptr_t)cur - (uintptr_t)itf_desc; + cur = _next_desc_itf(cur, end); + stm->desc.end = (uintptr_t)cur - (uintptr_t)itf_desc; + } + self->len = (uintptr_t)cur - (uintptr_t)itf_desc; + return (uintptr_t)cur - (uintptr_t)itf_desc; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + int err; + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + uint_fast8_t itfnum = tu_u16_low(request->wIndex); + + /* Identify which control interface to use */ + uint_fast8_t itf; + for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { + void const *desc = _videod_itf[itf].beg; + if (!desc) continue; + if (itfnum == _desc_itfnum(desc)) break; + } + + if (itf < CFG_TUD_VIDEO) { + err = handle_video_ctl_req(rhport, stage, request, itf); + _videod_itf[itf].error_code = (uint8_t)err; + if (err) return false; + return true; + } + + /* Identify which streaming interface to use */ + for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; + if (!stm->desc.beg) continue; + void const *desc = _videod_itf[stm->index_vc].beg; + if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; + } + + if (itf < CFG_TUD_VIDEO_STREAMING) { + err = handle_video_stm_req(rhport, stage, request, itf); + _videod_streaming_itf[itf].error_code = (uint8_t)err; + if (err) return false; + return true; + } + return false; +} + +bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; (void)xferred_bytes; + + /* find streaming handle */ + uint_fast8_t itf; + videod_interface_t *ctl; + videod_streaming_interface_t *stm; + for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { + stm = &_videod_streaming_itf[itf]; + uint_fast16_t const ep_ofs = stm->desc.ep[0]; + if (!ep_ofs) continue; + ctl = &_videod_itf[stm->index_vc]; + void const *desc = ctl->beg; + if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; + } + + TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); + if (stm->offset < stm->bufsize) { + /* Claim the endpoint */ + TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); + uint_fast16_t pkt_len = _prepare_in_payload(stm); + TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, pkt_len), 0); + } else { + stm->buffer = NULL; + stm->bufsize = 0; + stm->offset = 0; + if (tud_video_frame_xfer_complete_cb) { + tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); + } + } + return true; +} + +#endif diff --git a/src/class/video/video_device.h b/src/class/video/video_device.h new file mode 100644 index 000000000..ee2fcb9d5 --- /dev/null +++ b/src/class/video/video_device.h @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2021 Koji KITAYAMA + * + * 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_VIDEO_DEVICE_H_ +#define TUSB_VIDEO_DEVICE_H_ + +#include "common/tusb_common.h" +#include "video.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API (Multiple Ports) +// CFG_TUD_VIDEO > 1 +//--------------------------------------------------------------------+ + +/** Return true if streaming + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index */ +bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); + +/** Transfer a frame + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. + * @param[in] bufsize Byte size of the frame buffer */ +bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); + +/*------------- Optional callbacks -------------*/ +/** Invoked when compeletion of a frame transfer + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index */ +TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +/** Invoked when SET_POWER_MODE request received + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @return video_error_code_t */ +TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); + +/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @param[in] parameters Video streaming parameters + * @return video_error_code_t */ +TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const *parameters); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void videod_init (void); +void videod_reset (uint8_t rhport); +uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c2356ffee..9b9e2b007 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -38,20 +38,21 @@ #define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) -#define TU_U16_HIGH(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) -#define TU_U16_LOW(u16) ((uint8_t) ((u16) & 0x00ff)) -#define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) -#define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) +#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) +#define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) +#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) +#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) -#define TU_U32_BYTE3(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB -#define TU_U32_BYTE2(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) -#define TU_U32_BYTE1(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) -#define TU_U32_BYTE0(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB +#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB +#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) +#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) +#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB -#define U32_TO_U8S_BE(u32) TU_U32_BYTE3(u32), TU_U32_BYTE2(u32), TU_U32_BYTE1(u32), TU_U32_BYTE0(u32) -#define U32_TO_U8S_LE(u32) TU_U32_BYTE0(u32), TU_U32_BYTE1(u32), TU_U32_BYTE2(u32), TU_U32_BYTE3(u32) +#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) +#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) #define TU_BIT(n) (1UL << (n)) +#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) //--------------------------------------------------------------------+ // Includes @@ -105,13 +106,16 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) return (uint16_t) ((((uint16_t) high) << 8) | low); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t u32) { return TU_U32_BYTE3(u32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t u32) { return TU_U32_BYTE2(u32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t u32) { return TU_U32_BYTE1(u32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t u32) { return TU_U32_BYTE0(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t ui32) { return TU_U32_BYTE3(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return TU_U32_BYTE2(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return TU_U16_HIGH(u16); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return TU_U16_LOW(u16); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); } + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); } //------------- Bits -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } @@ -161,7 +165,6 @@ static inline uint8_t tu_log2(uint32_t value) #if TUP_ARCH_STRICT_ALIGN // Rely on compiler to generate correct code for unaligned access - typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; @@ -227,45 +230,14 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_ #else // MCU that could access unaligned memory natively -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem ) { return *((uint32_t*) mem); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem ) { return *((uint16_t*) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } #endif -/*------------------------------------------------------------------*/ -/* Count number of arguments of __VA_ARGS__ - * - reference https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s - * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) - * - _RSEQ_N() is reverse sequential to N to add padding to have - * Nth position is the same as the number of arguments - * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) - *------------------------------------------------------------------*/ -#ifndef TU_ARGS_NUM - -#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) - -#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) -#define _GET_NTH_ARG( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ - _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ - _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ - _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ - _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ - _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ - _61,_62,_63,N,...) N -#define _RSEQ_N() \ - 62,61,60, \ - 59,58,57,56,55,54,53,52,51,50, \ - 49,48,47,46,45,44,43,42,41,40, \ - 39,38,37,36,35,34,33,32,31,30, \ - 29,28,27,26,25,24,23,22,21,20, \ - 19,18,17,16,15,14,13,12,11,10, \ - 9,8,7,6,5,4,3,2,1,0 -#endif - // To be removed //------------- Binary constant -------------// #if defined(__GNUC__) && !defined(__CC_ARM) @@ -334,8 +306,8 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem #define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x))) -#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (uint32_t) (_x) ) -#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (uint32_t) (_x) ) +#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) ) +#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) ) // Log Level 2: Warn #if CFG_TUSB_DEBUG >= 2 @@ -369,12 +341,17 @@ typedef struct static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { + static char not_found[11]; + for(uint16_t i=0; icount; i++) { if (p_table->items[i].key == key) return p_table->items[i].data; } - return NULL; + // not found return the key value in hex + sprintf(not_found, "0x%08lX", (unsigned long) key); + + return not_found; } #endif // CFG_TUSB_DEBUG diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index d3adbbc2d..d3284c62a 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -32,6 +32,7 @@ #ifndef _TUSB_COMPILER_H_ #define _TUSB_COMPILER_H_ +#define TU_TOKEN(x) x #define TU_STRING(x) #x ///< stringify without expand #define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify @@ -41,6 +42,8 @@ #define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat #define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens +#define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) + #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ #define _TU_COUNTER_ __COUNTER__ #else @@ -64,6 +67,46 @@ #define TU_LITTLE_ENDIAN (0x12u) #define TU_BIG_ENDIAN (0x21u) +/*------------------------------------------------------------------*/ +/* Count number of arguments of __VA_ARGS__ + * - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments + * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) + * - _RSEQ_N() is reverse sequential to N to add padding to have + * Nth position is the same as the number of arguments + * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) + *------------------------------------------------------------------*/ +#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) + +#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) +#define _GET_NTH_ARG( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define _RSEQ_N() \ + 62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + +// Apply an macro X to each of the arguments with an separated of choice +#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) + +#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) +#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) +#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3) +#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) +#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) +#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) +#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) +#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) + //--------------------------------------------------------------------+ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 11b8fc5f3..564687e02 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -102,7 +102,7 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // TODO generalize with configurable 1 byte or 4 byte each read static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) { - volatile uint32_t * rx_fifo = (volatile uint32_t *) app_buf; + volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; // Reading full available 32 bit words from const app address uint16_t full_words = len >> 2; @@ -201,7 +201,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t ff_buf += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary - volatile uint32_t * rx_fifo = (volatile uint32_t *) app_buf; + volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; uint8_t rem = nLin_bytes & 0x03; if (rem > 0) { diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d23c6b2dd..5b26f5aec 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -47,8 +47,8 @@ typedef enum { TUSB_SPEED_FULL = 0, - TUSB_SPEED_LOW , - TUSB_SPEED_HIGH, + TUSB_SPEED_LOW = 1, + TUSB_SPEED_HIGH = 2, TUSB_SPEED_INVALID = 0xff, }tusb_speed_t; @@ -69,6 +69,18 @@ typedef enum TUSB_DIR_IN_MASK = 0x80 }tusb_dir_t; +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_NO_SYNC = 0x00, + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point + TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback +}tusb_iso_ep_attribute_t; + /// USB Descriptor Types typedef enum { @@ -337,32 +349,24 @@ TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); /// USB Endpoint Descriptor typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< ENDPOINT Descriptor Type + uint8_t bLength ; // Size of this descriptor in bytes + uint8_t bDescriptorType ; // ENDPOINT Descriptor Type - uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + uint8_t bEndpointAddress ; // The address of the endpoint struct TU_ATTR_PACKED { - uint8_t xfer : 2; - uint8_t sync : 2; - uint8_t usage : 2; + uint8_t xfer : 2; // Control, ISO, Bulk, Interrupt + uint8_t sync : 2; // None, Asynchronous, Adaptive, Synchronous + uint8_t usage : 2; // Data, Feedback, Implicit feedback uint8_t : 2; - } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + } bmAttributes; - struct TU_ATTR_PACKED { -#if defined(__CCRX__) - //FIXME the original defined bit field has a problem with the CCRX toolchain, so only a size field is defined - uint16_t size; -#else - uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. - uint16_t hs_period_mult : 2; - uint16_t TU_RESERVED : 3; -#endif - }wMaxPacketSize; - - uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. + uint16_t wMaxPacketSize ; // Bit 10..0 : max packet size, bit 12..11 additional transaction per highspeed micro-frame + uint8_t bInterval ; // Polling interval, in frames or microframes depending on the operating speed } tusb_desc_endpoint_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); + /// USB Other Speed Configuration Descriptor typedef struct TU_ATTR_PACKED { @@ -372,7 +376,7 @@ typedef struct TU_ATTR_PACKED uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration uint8_t bConfigurationValue ; ///< Value to use to select configuration - uint8_t IConfiguration ; ///< Index of string descriptor + uint8_t iConfiguration ; ///< Index of string descriptor uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; @@ -387,11 +391,14 @@ typedef struct TU_ATTR_PACKED uint8_t bDeviceClass ; ///< Class Code uint8_t bDeviceSubClass ; ///< SubClass Code uint8_t bDeviceProtocol ; ///< Protocol Code + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); + /// USB Interface Association Descriptor (IAD ECN) typedef struct TU_ATTR_PACKED { @@ -506,6 +513,11 @@ static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); } +static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) +{ + return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); +} + //--------------------------------------------------------------------+ // Descriptor helper //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index 66767c1fe..c042cc708 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,7 +106,14 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler +#if __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif void dcd_int_handler(uint8_t rhport); +#if __GNUC__ +#pragma GCC diagnostic pop +#endif // Enable device interrupt void dcd_int_enable (uint8_t rhport); @@ -137,6 +144,11 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); +// Close all non-control endpoints, cancel all pending transfers if any. +// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore +// required for multiple configuration support. +void dcd_edpt_close_all (uint8_t rhport); + // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; @@ -148,7 +160,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -// Stall endpoint +// Stall endpoint, any queuing transfer should be removed from endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 638a17814..c51940573 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -36,121 +36,167 @@ // - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. //------------- NXP -------------// -#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) +#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) #define DCD_ATTR_ENDPOINT_MAX 16 -#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) // TODO USB0 has 6, USB1 has 4 + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(LPC51UXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC54XXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(MIMXRT10XX) +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(MKL25ZXX) || TU_CHECK_MCU(K32L2BXX) +#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Nordic -------------// -#elif TU_CHECK_MCU(NRF5X) +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) // 8 CBI + 1 ISO #define DCD_ATTR_ENDPOINT_MAX 9 //------------- Microchip -------------// -#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \ - TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22) +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(SAMG) +#elif TU_CHECK_MCU(OPT_MCU_SAMG) #define DCD_ATTR_ENDPOINT_MAX 6 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER -#elif TU_CHECK_MCU(SAMX7X) +#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) #define DCD_ATTR_ENDPOINT_MAX 10 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER //------------- ST -------------// -#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ - TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) - // F1: F102, F103 - // L4: L4x2, L4x3 +#elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) - // F1: F105, F107 only has 4 - // L4: L4x5, L4x6 has 6 - // For most mcu, FS has 4, HS has 6 - #define DCD_ATTR_ENDPOINT_MAX 6 +#elif TU_CHECK_MCU(OPT_MCU_STM32F1) + #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) + #define DCD_ATTR_ENDPOINT_MAX 4 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif -#elif TU_CHECK_MCU(STM32F7) +#elif TU_CHECK_MCU(OPT_MCU_STM32F2) + // FS has 4 ep, HS has 5 ep + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F3) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F4) + // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F7) // FS has 6, HS has 9 #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 -#elif TU_CHECK_MCU(STM32H7) +#elif TU_CHECK_MCU(OPT_MCU_STM32H7) #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32G4) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L4) + #if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif //------------- Sony -------------// -#elif TU_CHECK_MCU(CXD56) +#elif TU_CHECK_MCU(OPT_MCU_CXD56) #define DCD_ATTR_ENDPOINT_MAX 7 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER //------------- TI -------------// -#elif TU_CHECK_MCU(MSP430x5xx) +#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) #define DCD_ATTR_ENDPOINT_MAX 8 //------------- ValentyUSB -------------// -#elif TU_CHECK_MCU(VALENTYUSB_EPTRI) +#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Nuvoton -------------// -#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126) +#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(NUC120) +#elif TU_CHECK_MCU(OPT_MCU_NUC120) #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(NUC505) +#elif TU_CHECK_MCU(OPT_MCU_NUC505) #define DCD_ATTR_ENDPOINT_MAX 12 //------------- Espressif -------------// -#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) #define DCD_ATTR_ENDPOINT_MAX 6 //------------- Dialog -------------// -#elif TU_CHECK_MCU(DA1469X) +#elif TU_CHECK_MCU(OPT_MCU_DA1469X) #define DCD_ATTR_ENDPOINT_MAX 4 //------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(RP2040) +#elif TU_CHECK_MCU(OPT_MCU_RP2040) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) +#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) #define DCD_ATTR_ENDPOINT_MAX 10 -//#elif TU_CHECK_MCU(MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not known yet - //------------- GigaDevice -------------// -#elif TU_CHECK_MCU(GD32VF103) +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #define DCD_ATTR_ENDPOINT_MAX 4 +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_BCM2711) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_XMC4000) + #define DCD_ATTR_ENDPOINT_MAX 8 + //------------- BridgeTek -------------// #elif TU_CHECK_MCU(FT90X) #define DCD_ATTR_ENDPOINT_MAX 8 diff --git a/src/device/usbd.c b/src/device/usbd.c index e12dafcfd..6a5210b34 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ // Debug level of USBD -#define USBD_DBG_LVL 2 +#define USBD_DBG 2 #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 @@ -143,6 +143,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_VIDEO + { + DRIVER_NAME("VIDEO") + .init = videod_init, + .reset = videod_reset, + .open = videod_open, + .control_xfer_cb = videod_control_xfer_cb, + .xfer_cb = videod_xfer_cb, + .sof = NULL + }, + #endif + #if CFG_TUD_MIDI { DRIVER_NAME("MIDI") @@ -203,7 +215,7 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_NET + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM { DRIVER_NAME("NET") .init = netd_init, @@ -432,19 +444,22 @@ bool tud_init (uint8_t rhport) return true; } -static void usbd_reset(uint8_t rhport) +static void configuration_reset(uint8_t rhport) { - tu_varclr(&_usbd_dev); - - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping - - usbd_control_reset(); - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { get_driver(i)->reset(rhport); } + + tu_varclr(&_usbd_dev); + memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping +} + +static void usbd_reset(uint8_t rhport) +{ + configuration_reset(rhport); + usbd_control_reset(); } bool tud_task_event_ready(void) @@ -686,9 +701,29 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.cfg_num = cfg_num; + // Only process if new configure is different + if (_usbd_dev.cfg_num != cfg_num) + { + if ( _usbd_dev.cfg_num ) + { + // already configured: need to clear all endpoints and driver first + TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); + // close all non-control endpoints, cancel all pending transfers if any + dcd_edpt_close_all(rhport); + + // close all drivers and current configured state except bus speed + uint8_t const speed = _usbd_dev.speed; + configuration_reset(rhport); + + _usbd_dev.speed = speed; // restore speed + } + + // switch to new configuration if not zero + if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + } + + _usbd_dev.cfg_num = cfg_num; tud_control_status(rhport, p_request); } break; @@ -701,7 +736,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG_LVL, " Enable Remote Wakeup\r\n"); + TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; @@ -712,7 +747,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG_LVL, " Disable Remote Wakeup\r\n"); + TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; @@ -751,16 +786,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + switch(p_request->bRequest) { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest) - { - tud_control_status(rhport, p_request); - } else - { - return false; + case TUSB_REQ_GET_INTERFACE: + case TUSB_REQ_SET_INTERFACE: + // Clear complete callback if driver set since it can also stall the request. + usbd_control_set_complete_callback(NULL); + + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else + { + tud_control_status(rhport, p_request); + } + break; + + default: return false; } } } @@ -843,12 +886,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // This function parse configuration descriptor & open drivers accordingly static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { - tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 + // index is cfg_num-1 + tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; - _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; + _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED ) ? 1 : 0; // Parse interface descriptor uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); @@ -856,66 +900,75 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - tusb_desc_interface_assoc_t const * desc_iad = NULL; + uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); } TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; - uint16_t const remaining_len = desc_end-p_desc; - - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - - // TODO usbd can calculate the total length used for driver --> driver open() does not need to calculate it - // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); // Find driver for this interface + uint16_t const remaining_len = desc_end-p_desc; uint8_t drv_id; for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = get_driver(drv_id); uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); - if ( drv_len > 0 ) + if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) { - // Open successfully, check if length is correct - TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); - + // Open successfully TU_LOG2(" %s opened\r\n", driver->name); - // bind interface to found driver - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - // If using IAD, bind all interfaces to the same driver - if (desc_iad) + // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or + // BTH (even CDC) with class in device descriptor (single interface) + if ( assoc_itf_count == 1) { - // IAD's first interface number and class should match with opened interface - TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + #if CFG_TUD_CDC + if ( driver->open == cdcd_open ) assoc_itf_count = 2; + #endif - for(uint8_t i=1; ibInterfaceCount; i++) - { - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; - } + #if CFG_TUD_MIDI + if ( driver->open == midid_open ) assoc_itf_count = 2; + #endif + + #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT + if ( driver->open == btd_open ) assoc_itf_count = 2; + #endif + } + + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibInterfaceNumber+i; + + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[itf_num]); + _usbd_dev.itf2drv[itf_num] = drv_id; } // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); - p_desc += drv_len; // next interface + // next Interface + p_desc += drv_len; break; // exit driver find loop } } - // Failed if cannot find supported driver + // Failed if there is no supported drivers TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); } @@ -937,19 +990,23 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { TU_LOG2(" Device\r\n"); - uint16_t len = sizeof(tusb_desc_device_t); + void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); - // Only send up to EP0 Packet Size if not addressed + // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. // This only happens with the very first get device descriptor and EP0 size = 8 or 16. - if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && + ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) { - len = CFG_TUD_ENDPOINT0_SIZE; - // Hack here: we modify the request length to prevent usbd_control response with zlp - ((tusb_control_request_t*) p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE; - } + // since we are responding with 1 packet & less data than wLength. + tusb_control_request_t mod_request = *p_request; + mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; - return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); + return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); + }else + { + return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); + } } break; @@ -960,24 +1017,37 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); + TU_ASSERT(desc_bos); // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength)) ); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } break; case TUSB_DESC_CONFIGURATION: + case TUSB_DESC_OTHER_SPEED_CONFIG: { - TU_LOG2(" Configuration[%u]\r\n", desc_index); + uintptr_t desc_config; + + if ( desc_type == TUSB_DESC_CONFIGURATION ) + { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); + }else + { + // Host only request this after getting Device Qualifier descriptor + TU_LOG2(" Other Speed Configuration\r\n"); + TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); + desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); + } - tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -988,38 +1058,26 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); TU_VERIFY(desc_str); // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); } break; case TUSB_DESC_DEVICE_QUALIFIER: + { TU_LOG2(" Device Qualifier\r\n"); - // Host sends this request to ask why our device with USB BCD from 2.0 - // but is running at Full/Low Speed. If not highspeed capable stall this request, - // otherwise return the descriptor that could work in highspeed mode - if ( tud_descriptor_device_qualifier_cb ) - { - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); - TU_ASSERT(desc_qualifier); + TU_VERIFY( tud_descriptor_device_qualifier_cb ); - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]); - }else - { - return false; - } - break; + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + TU_VERIFY(desc_qualifier); - case TUSB_DESC_OTHER_SPEED_CONFIG: - TU_LOG2(" Other Speed Configuration\r\n"); - - // After Device Qualifier descriptor is received host will ask for this descriptor - return false; // not supported + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); + } break; default: return false; @@ -1034,15 +1092,11 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - // UNPLUGGED event can be bouncing, only processing if we are currently connected - if ( _usbd_dev.connected ) - { - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - } + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); break; case DCD_EVENT_SUSPEND: @@ -1301,27 +1355,33 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - TU_LOG(USBD_DBG_LVL, " Stall EP %02X", ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; + // only stalled if currently cleared + if ( !_usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); + dcd_edpt_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = true; + _usbd_dev.ep_status[epnum][dir].busy = true; + } } void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - TU_LOG(USBD_DBG_LVL, " Clear Stall EP %02X", ep_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; + // only clear if currently stalled + if ( _usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + } } bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) @@ -1345,7 +1405,13 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_close(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = false; return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 9becf2d0d..ec34817fa 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -113,9 +113,16 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// 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. TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); +// 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 +TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); + // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); @@ -171,17 +178,18 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ -// Configuration & Interface Descriptor Templates +// Configuration Descriptor Templates //--------------------------------------------------------------------+ -//------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 -//------------- CDC -------------// +//--------------------------------------------------------------------+ +// CDC Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 66 bytes #define TUD_CDC_DESC_LEN (8+9+5+5+4+5+7+9+7+7) @@ -210,7 +218,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- MSC -------------// +//--------------------------------------------------------------------+ +// MSC Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 23 bytes #define TUD_MSC_DESC_LEN (9 + 7 + 7) @@ -224,7 +234,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- HID -------------// + +//--------------------------------------------------------------------+ +// HID Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 25 bytes #define TUD_HID_DESC_LEN (9 + 9 + 7) @@ -254,8 +267,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval -//------------- MIDI -------------// -// MIDI v1.0 is based on Audio v1.0 +//--------------------------------------------------------------------+ +// MIDI Descriptor Templates +// Note: MIDI v1.0 is based on Audio v1.0 +//--------------------------------------------------------------------+ #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ @@ -312,7 +327,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ TUD_MIDI_JACKID_OUT_EMB(1) -//------------- AUDIO -------------// +//--------------------------------------------------------------------+ +// Audio v2.0 Descriptor Templates +//--------------------------------------------------------------------+ /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 @@ -544,7 +561,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) -//------------- TUD_USBTMC/USB488 -------------// +//--------------------------------------------------------------------+ +// USBTMC/USB488 Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u @@ -574,8 +594,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) +//--------------------------------------------------------------------+ +// Vendor Descriptor Templates +//--------------------------------------------------------------------+ -//------------- Vendor -------------// #define TUD_VENDOR_DESC_LEN (9+7+7) // Interface number, string index, EP Out & IN address, EP size @@ -587,7 +609,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- DFU Runtime -------------// +//--------------------------------------------------------------------+ +// DFU Runtime Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) @@ -602,6 +627,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//--------------------------------------------------------------------+ +// DFU Descriptor Templates +//--------------------------------------------------------------------+ + // Length of template descriptor: 9 bytes + number of alternatives * 9 #define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) @@ -647,8 +676,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) - -//------------- CDC-ECM -------------// +//--------------------------------------------------------------------+ +// CDC-ECM Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 71 bytes #define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) @@ -677,8 +707,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//------------- RNDIS -------------// +//--------------------------------------------------------------------+ +// RNDIS Descriptor Templates +//--------------------------------------------------------------------+ #if 0 /* Windows XP */ @@ -719,7 +750,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- BT Radio -------------// +//--------------------------------------------------------------------+ +// Bluetooth Radio Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) #define TUD_BT_APP_SUBCLASS 0x01 #define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 @@ -729,8 +763,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define CFG_TUD_BTH_ISO_ALT_COUNT 0 #endif -// Length of template descriptor: 30 bytes + number of ISO alternatives * 23 -#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) +// Length of template descriptor: 38 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ @@ -770,10 +804,46 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +// TODO BTH should also use IAD like CDC for composite device #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0,\ TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) +//--------------------------------------------------------------------+ +// CDC-NCM Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor +#define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-NCM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC-NCM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-NCM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0, \ + /* CDC-NCM Functional Descriptor */\ + 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0, \ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + #ifdef __cplusplus } #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 6a4b30956..7607b9895 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -81,7 +81,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); // Release an endpoint without submitting a transfer bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); -// Check if endpoint transferring is complete +// Check if endpoint is busy transferring bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); // Stall endpoint @@ -93,6 +93,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); // Check if endpoint is stalled bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); +// Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { diff --git a/src/host/hcd_attr.h b/src/host/hcd_attr.h index 729fc407b..06011c63c 100644 --- a/src/host/hcd_attr.h +++ b/src/host/hcd_attr.h @@ -34,64 +34,64 @@ // - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. //------------- NXP -------------// -#if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) #define HCD_ATTR_OHCI -#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #define HCD_ATTR_EHCI_TRANSDIMENSION -#elif TU_CHECK_MCU(LPC54XXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) // #define HCD_ATTR_EHCI_NXP_PTD -#elif TU_CHECK_MCU(LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) // #define HCD_ATTR_EHCI_NXP_PTD -#elif TU_CHECK_MCU(MIMXRT10XX) +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) #define HCD_ATTR_EHCI_TRANSDIMENSION -#elif TU_CHECK_MCU(MKL25ZXX) +#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX) //------------- Microchip -------------// -#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \ - TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22) +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) -#elif TU_CHECK_MCU(SAMG) +#elif TU_CHECK_MCU(OPT_MCU_SAMG) -#elif TU_CHECK_MCU(SAMX7X) +#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) //------------- ST -------------// -#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ - TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) +#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1, OPT_MCU_STM32F3) || \ + TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32L4) -#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) +#elif TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F3, OPT_MCU_STM32F4) -#elif TU_CHECK_MCU(STM32F7) +#elif TU_CHECK_MCU(OPT_MCU_STM32F7) -#elif TU_CHECK_MCU(STM32H7) +#elif TU_CHECK_MCU(OPT_MCU_STM32H7) //------------- Sony -------------// -#elif TU_CHECK_MCU(CXD56) +#elif TU_CHECK_MCU(OPT_MCU_CXD56) //------------- Nuvoton -------------// -#elif TU_CHECK_MCU(NUC505) +#elif TU_CHECK_MCU(OPT_MCU_NUC505) //------------- Espressif -------------// -#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) //------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(RP2040) +#elif TU_CHECK_MCU(OPT_MCU_RP2040) //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) //------------- Renesas -------------// -#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) +#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) -//#elif TU_CHECK_MCU(MM32F327X) +//#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) // #define DCD_ATTR_ENDPOINT_MAX not known yet //------------- GigaDevice -------------// -#elif TU_CHECK_MCU(GD32VF103) +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #else // #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" diff --git a/src/host/usbh.c b/src/host/usbh.c index 51b8f85b6..b8439addc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -53,13 +53,39 @@ // USBH-HCD common data structure //--------------------------------------------------------------------+ -typedef struct { - //------------- port -------------// +// device0 struct must be strictly a subset of normal device struct +typedef struct +{ + // port uint8_t rhport; uint8_t hub_addr; uint8_t hub_port; uint8_t speed; + volatile struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; +} usbh_dev0_t; + +typedef struct { + // port + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + + volatile struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; + //------------- device descriptor -------------// uint16_t vid; uint16_t pid; @@ -73,14 +99,6 @@ typedef struct { // uint8_t interface_count; // bNumInterfaces alias //------------- device -------------// - struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; - volatile uint8_t state; // device state, value from enum tusbh_device_state_t uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) @@ -103,16 +121,6 @@ typedef struct { } usbh_device_t; -typedef struct -{ - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - volatile uint8_t connected; -} usbh_dev0_t; - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -533,10 +541,12 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port usbh_class_drivers[drv_id].close(dev_addr); } + hcd_device_close(rhport, dev_addr); + + // release all endpoints associated with the device memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - - hcd_device_close(rhport, dev_addr); + tu_memclr(dev->ep_status, sizeof(dev->ep_status)); dev->state = TUSB_DEVICE_STATE_UNPLUG; } @@ -894,11 +904,10 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT(XFER_RESULT_SUCCESS == result); // TODO not enough buffer to hold configuration descriptor - tusb_desc_configuration_t const * desc_config = (tusb_desc_configuration_t const*) _usbh_ctrl_buf; - uint16_t total_len; + uint8_t const * desc_config = _usbh_ctrl_buf; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); @@ -982,25 +991,38 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // parse each interfaces while( p_desc < desc_end ) { - // TODO Do we need to use IAD - tusb_desc_interface_assoc_t const * desc_iad = NULL; + uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - p_desc = tu_desc_next(p_desc); + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); } TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - // Interface number must not be used already - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == DRVID_INVALID ); +#if CFG_TUH_MIDI + // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD + // manually increase the associated count + if (1 == assoc_itf_count && + TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) + { + assoc_itf_count = 2; + } +#endif - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); - TU_ASSERT(drv_len); + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); + TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { @@ -1019,22 +1041,16 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { // open successfully - TU_LOG2(" Opened successfully\r\n"); + TU_LOG2(" %s opened\r\n", driver->name); - // bind interface to found driver - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - // If using IAD, bind all interfaces to the same driver - if (desc_iad) + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibFirstInterface == desc_itf->bInterfaceNumber && - desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + uint8_t const itf_num = desc_itf->bInterfaceNumber+i; - for(uint8_t i=1; ibInterfaceCount; i++) - { - dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; - } + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == dev->itf2drv[itf_num] ); + dev->itf2drv[itf_num] = drv_id; } // bind all endpoints to found driver @@ -1158,7 +1174,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) .bDescriptorType = TUSB_DESC_ENDPOINT, .bEndpointAddress = 0, .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = max_packet_size }, + .wMaxPacketSize = max_packet_size, .bInterval = 0 }; diff --git a/src/osal/osal.h b/src/osal/osal.h index 28bdf479c..c8131d19d 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -67,6 +67,10 @@ typedef void (*osal_task_func_t)( void * ); // OSAL Porting API //--------------------------------------------------------------------+ +#if __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif //------------- Semaphore -------------// static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); @@ -84,6 +88,9 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); static inline bool osal_queue_empty(osal_queue_t qhdl); +#if __GNUC__ +#pragma GCC diagnostic pop +#endif #if 0 // TODO remove subtask related macros later // Sub Task diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 66070c273..4573e01f5 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -28,10 +28,10 @@ #define _TUSB_OSAL_FREERTOS_H_ // FreeRTOS Headers -#include "FreeRTOS.h" -#include "semphr.h" -#include "queue.h" -#include "task.h" +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) #ifdef __cplusplus extern "C" { diff --git a/src/portable/broadcom/synopsys/dcd_synopsys.c b/src/portable/broadcom/synopsys/dcd_synopsys.c new file mode 100644 index 000000000..494bb70ee --- /dev/null +++ b/src/portable/broadcom/synopsys/dcd_synopsys.c @@ -0,0 +1,1267 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Jan Duempelmann + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_BCM2711 ) \ + + +#include "synopsys_common.h" + +#include "broadcom/interrupts.h" + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + +// EP_MAX : Max number of bi-directional endpoints including EP0 +// EP_FIFO_SIZE : Size of dedicated USB SRAM +#if CFG_TUSB_MCU == OPT_MCU_BCM2711 +// #include "bcm2711.h" +#define EP_MAX_FS 8 +#define EP_FIFO_SIZE_FS 4096 +#define EP_MAX_HS 8 +#define EP_FIFO_SIZE_HS 4096 +#else +#error "Unsupported MCUs" +#endif + +#define EP_MAX 8 +#define EP_FIFO_SIZE 4096 + +// Info on values here: https://github.com/torvalds/linux/blob/79160a603bdb51916226caf4a6616cc4e1c58a58/Documentation/devicetree/bindings/usb/dwc2.yaml + +// From: https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/bcm283x.dtsi +// usb: usb@7e980000 { +// compatible = "brcm,bcm2835-usb"; +// reg = <0x7e980000 0x10000>; +// interrupts = <1 9>; +// #address-cells = <1>; +// #size-cells = <0>; +// clocks = <&clk_usb>; +// clock-names = "otg"; +// phys = <&usbphy>; +// phy-names = "usb2-phy"; +// }; + +// From: https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/bcm283x-rpi-usb-otg.dtsi +// SPDX-License-Identifier: GPL-2.0 +// &usb { +// dr_mode = "otg"; +// g-rx-fifo-size = <256>; +// g-np-tx-fifo-size = <32>; + +// * According to dwc2 the sum of all device EP +// * fifo sizes shouldn't exceed 3776 bytes. + +// g-tx-fifo-size = <256 256 512 512 512 768 768>; +// }; + +// From: https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/bcm2711-rpi.dtsi +// &usb { +// /* Enable the FIQ support */ +// reg = <0x7e980000 0x10000>, +// <0x7e00b200 0x200>; +// interrupts = , +// ; +// status = "disabled"; +// }; + +// From: https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/bcm2711.dtsi +// &usb { +// interrupts = ; +// }; + +// From: https://github.com/torvalds/linux/blob/1d597682d3e669ec7021aa33d088ed3d136a5149/drivers/usb/dwc2/params.c +// static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg) +// { +// struct dwc2_core_params *p = &hsotg->params; + +// p->host_rx_fifo_size = 774; +// p->max_transfer_size = 65535; +// p->max_packet_count = 511; +// p->ahbcfg = 0x10; +// } + +#include "device/dcd.h" + +TU_VERIFY_STATIC(sizeof(USB_OTG_GlobalTypeDef) == 0x140, "size is incorrect"); + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +#define RHPORT_REGS_BASE USB_OTG_GLOBAL_BASE + +#define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) +#define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (USB_OTG_DEVICE_BASE) +#define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_OUT_ENDPOINT_BASE) +#define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_IN_ENDPOINT_BASE) +#define FIFO_BASE(_port, _x) ((volatile uint32_t *) (RHPORT_REGS_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) + +enum +{ + DCD_HIGH_SPEED = 0, // Highspeed mode + DCD_FULL_SPEED_USE_HS = 1, // Full speed in Highspeed port (probably with internal PHY) + DCD_FULL_SPEED = 3, // Full speed with internal PHY +}; + +static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; + +typedef struct { + uint8_t * buffer; + tu_fifo_t * ff; + uint16_t total_len; + uint16_t max_size; + uint8_t interval; +} xfer_ctl_t; + +typedef volatile uint32_t * usb_fifo_t; + +xfer_ctl_t xfer_status[EP_MAX][2]; +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] + +// EP0 transfers are limited to 1 packet - larger sizes has to be split +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type + +// TX FIFO RAM allocation so far in words - RX FIFO size is readily available from usb_otg->GRXFSIZ +static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) +static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) + +// Calculate the RX FIFO size according to recommendations from reference manual +static inline uint16_t calc_rx_ff_size(uint16_t ep_size) +{ + return 15 + 2*(ep_size/4) + 2*EP_MAX; +} + +static void update_grxfsiz(uint8_t rhport) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + // Determine largest EP size for RX FIFO + uint16_t max_epsize = 0; + for (uint8_t epnum = 0; epnum < EP_MAX; epnum++) + { + max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size); + } + + // Update size of RX FIFO + usb_otg->GRXFSIZ = calc_rx_ff_size(max_epsize); +} + +// Setup the control endpoint 0. +static void bus_reset(uint8_t rhport) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + tu_memclr(xfer_status, sizeof(xfer_status)); + _out_ep_closed = false; + + // clear device address + dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; + + // 1. NAK for all OUT endpoints + for(uint8_t n = 0; n < EP_MAX; n++) { + out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + } + + // 2. Un-mask interrupt bits + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + dev->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + dev->DIEPMSK = USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start. + // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located + // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard + // configuration done below. + // + // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed. + // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a + // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually + // opened when the host sends an additional command: setInterface. At this point in time + // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size + // an additional memory + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // - 13 for setup packets + control words (up to 3 setup packets). + // - 1 for global NAK (not required/used here). + // - Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1" + // - 2 for each used OUT endpoint + // + // Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum + // - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x EP_MAX = 47 + 2 x EP_MAX + // - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x EP_MAX = 271 + 2 x EP_MAX + // + // NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge + // of the overall picture yet. We will use the worst scenario: largest possible + EP_MAX + // + // For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO + // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to + // overwrite this. + + #if TUD_OPT_HIGH_SPEED + usb_otg->GRXFSIZ = calc_rx_ff_size(512); + #else + usb_otg->GRXFSIZ = calc_rx_ff_size(64); + #endif + + _allocated_fifo_words_tx = 16; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); + + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); + + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; +} + +// Set turn-around timeout according to link speed +extern uint32_t SystemCoreClock; +static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) +{ + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + + if ( speed == TUSB_SPEED_HIGH ) + { + // Use fixed 0x09 for Highspeed + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + } + else + { + // Turnaround timeout depends on the MCU clock + uint32_t turnaround; + + if ( SystemCoreClock >= 32000000U ) + turnaround = 0x6U; + else if ( SystemCoreClock >= 27500000U ) + turnaround = 0x7U; + else if ( SystemCoreClock >= 24000000U ) + turnaround = 0x8U; + else if ( SystemCoreClock >= 21800000U ) + turnaround = 0x9U; + else if ( SystemCoreClock >= 20000000U ) + turnaround = 0xAU; + else if ( SystemCoreClock >= 18500000U ) + turnaround = 0xBU; + else if ( SystemCoreClock >= 17200000U ) + turnaround = 0xCU; + else if ( SystemCoreClock >= 16000000U ) + turnaround = 0xDU; + else if ( SystemCoreClock >= 15000000U ) + turnaround = 0xEU; + else + turnaround = 0xFU; + + // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz + usb_otg->GUSBCFG |= (turnaround << USB_OTG_GUSBCFG_TRDT_Pos); + } +} + +static tusb_speed_t get_speed(uint8_t rhport) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; +} + +static void set_speed(uint8_t rhport, tusb_speed_t speed) +{ + uint32_t bitvalue; + + if ( rhport == 1 ) + { + bitvalue = ((TUSB_SPEED_HIGH == speed) ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS); + } + else + { + bitvalue = DCD_FULL_SPEED; + } + + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + // Clear and set speed bits + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos); +} + +#if 0 +// From CM4IO xtal to usb hub, may not be correct +#define HSE_VALUE 24000000 + +static bool USB_HS_PHYCInit(void) +{ + USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE; + + // Enable LDO + usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; + + // Wait until LDO ready + while ( 0 == (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} + + uint32_t phyc_pll = 0; + + // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS + switch ( HSE_VALUE ) + { + case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; + case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break; + case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break; + case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break; + case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break; + case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header + default: + TU_ASSERT(0); + } + usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; + + // Control the tuning interface of the High Speed PHY + // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver + usb_hs_phyc->USB_HS_PHYC_TUNE |= 0x00000F13U; + + // Enable PLL internal PHY + usb_hs_phyc->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; + + // Original ST code has 2 ms delay for PLL stabilization. + // Primitive test shows that more than 10 USB un/replug cycle showed no error with enumeration + + return true; +} +#endif + +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) +{ + (void) rhport; + + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // EP0 is limited to one packet each xfer + // We use multiple transaction of xfer->max_size length to get a whole transfer done + if(epnum == 0) { + xfer_ctl_t * const xfer = XFER_CTL_BASE(epnum, dir); + total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); + ep0_pending[dir] -= total_bytes; + } + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. + if(dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); + + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // For ISO endpoint set correct odd/even bit for next frame. + if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); + in_ep[epnum].DIEPCTL |= (odd_frame_now ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DIEPCTL_SODDFRM_Msk); + } + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + dev->DIEPEMPMSK |= (1 << epnum); + } + } else { + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); + out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); + + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + if ((out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP) == USB_OTG_DOEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); + out_ep[epnum].DOEPCTL |= (odd_frame_now ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DOEPCTL_SODDFRM_Msk); + } + } +} + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ + +TU_ATTR_UNUSED +static void reset_core(USB_OTG_GlobalTypeDef * usb_otg) { + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0) {} + + TU_LOG(2, " resetting\r\n"); + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + TU_LOG(2, " waiting\r\n"); + while ((usb_otg->GRSTCTL & (USB_OTG_GRSTCTL_AHBIDL | USB_OTG_GRSTCTL_CSRST)) != USB_OTG_GRSTCTL_AHBIDL) {} + TU_LOG(2, " reset done\r\n"); +} + +void dcd_init (uint8_t rhport) +{ + printf("test done\r\n"); + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. + TU_LOG(2, " dcd_init\r\n"); + + TU_LOG2("Test 123\r\n"); + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + +#if 1 + // No VBUS sense + usb_otg->GCCFG &= ~(1UL << 21); // USB_OTG_GCCFG_VBDEN + + // B-peripheral session valid override enable + usb_otg->GOTGCTL |= (1UL << 6); // USB_OTG_GOTGCTL_BVALOEN + usb_otg->GOTGCTL |= (1UL << 7); // USB_OTG_GOTGCTL_BVALOVAL + + // Force device mode + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_FHMOD; + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + // deactivate internal PHY + usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; + + // Init The UTMI Interface + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); + + // Select default internal VBUS Indicator and Drive for ULPI + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + + // Select UTMI Interface + usb_otg->GUSBCFG &= ~(1UL << 4); // USB_OTG_GUSBCFG_ULPI_UTMI_SEL + usb_otg->GCCFG |= (1UL << 32); // USB_OTG_GCCFG_PHYHSEN + + // Enables control of a High Speed USB PHY + //USB_HS_PHYCInit(); + + // Reset core after selecting PHY + // Wait AHB IDLE, reset then wait until it is cleared +// while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {} +// usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; +// while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} + + reset_core(usb_otg); + + // Restart PHY clock + *((volatile uint32_t *)(RHPORT_REGS_BASE + USB_OTG_PCGCCTL_BASE)) = 0; + +#else + + // ReadBackReg(&Core->Usb); + // Core->Usb.UlpiDriveExternalVbus = 0; + // Core->Usb.TsDlinePulseEnable = 0; + // WriteThroughReg(&Core->Usb); + + // This sequence is modeled after: https://github.com/Chadderz121/csud/blob/e13b9355d043a9cdd384b335060f1bc0416df61e/source/hcd/dwc/designware20.c#L689 + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIEVBUSD); + reset_core(usb_otg); + + // Core->Usb.ModeSelect = UTMI; + // LOG_DEBUG("HCD: Interface: UTMI+.\n"); + // Core->Usb.PhyInterface = false; + + // HcdReset(); + TU_LOG2("init phy\r\n"); + usb_otg->GUSBCFG |= (1 << 4); // bit four sets UTMI+ mode + usb_otg->GUSBCFG &= ~(1 << 3); // bit three disables phy interface + reset_core(usb_otg); + + // LOG_DEBUG("HCD: ULPI FSLS configuration: disabled.\n"); + // Core->Usb.UlpiFsls = false; + // Core->Usb.ulpi_clk_sus_m = false; + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_ULPICSM); + + // LOG_DEBUG("HCD: DMA configuration: enabled.\n"); + // Core->Ahb.DmaEnable = true; + // Core->Ahb.DmaRemainderMode = Incremental; + usb_otg->GAHBCFG &= ~(1 << 23); // Remainder mode + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN; + + // LOG_DEBUG("HCD: HNP/SRP configuration: HNP, SRP.\n"); + // Core->Usb.HnpCapable = true; + // Core->Usb.SrpCapable = true; + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_SRPCAP | USB_OTG_GUSBCFG_HNPCAP; + +#endif + + // Clear all interrupts + usb_otg->GINTSTS |= usb_otg->GINTSTS; + + // Required as part of core initialization. + // TODO: How should mode mismatch be handled? It will cause + // the core to stop working/require reset. + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; + + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + // If USB host misbehaves during status portion of control xfer + // (non zero-length packet), send STALL back and discard. + dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; + + set_speed(rhport, TUSB_SPEED_HIGH); + + // TODO internal phy (full speed) + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + + // Enable global interrupt + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + + dcd_connect(rhport); +} + +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + BP_EnableIRQ(USB_IRQn); +} + +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + BP_DisableIRQ(USB_IRQn); +} + +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + dev->DCFG = (dev->DCFG & ~USB_OTG_DCFG_DAD_Msk) | (dev_addr << USB_OTG_DCFG_DAD_Pos); + + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +static void remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while ( count-- ) + { + // __NOP(); + } +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + // set remote wakeup + dev->DCTL |= USB_OTG_DCTL_RWUSIG; + + // enable SOF to detect bus resume + usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_SOFM; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + remote_wakeup_delay(); + + dev->DCTL &= ~USB_OTG_DCTL_RWUSIG; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + dev->DCTL &= ~USB_OTG_DCTL_SDIS; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + dev->DCTL |= USB_OTG_DCTL_SDIS; +} + + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(epnum < EP_MAX); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + xfer->interval = desc_edpt->bInterval; + + uint16_t const fifo_size = (xfer->max_size + 3) / 4; // Round up to next full word + + if(dir == TUSB_DIR_OUT) + { + // Calculate required size of RX FIFO + uint16_t const sz = calc_rx_ff_size(4*fifo_size); + + // If size_rx needs to be extended check if possible and if so enlarge it + if (usb_otg->GRXFSIZ < sz) + { + TU_ASSERT(sz + _allocated_fifo_words_tx <= EP_FIFO_SIZE/4); + + // Enlarge RX FIFO + usb_otg->GRXFSIZ = sz; + } + + out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << USB_OTG_DOEPCTL_MPSIZ_Pos); + + dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); + } + else + { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // In FIFO is allocated by following rules: + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + // Check if free space is available + TU_ASSERT(_allocated_fifo_words_tx + fifo_size + usb_otg->GRXFSIZ <= EP_FIFO_SIZE/4); + + _allocated_fifo_words_tx += fifo_size; + + TU_LOG(2, " Allocated %u bytes at offset %u", fifo_size*4, EP_FIFO_SIZE-_allocated_fifo_words_tx*4); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); + + in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | + (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << USB_OTG_DIEPCTL_MPSIZ_Pos); + + dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); + } + + return true; +} + +// Close all non-control endpoints, cancel all pending transfers if any. +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + +// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // Disable non-control interrupt + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].DOEPCTL = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].DIEPCTL = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + // reset allocated fifo IN + _allocated_fifo_words_tx = 16; +} + +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; + + // EP0 can only handle one packet + if(epnum == 0) { + ep0_pending[dir] = total_bytes; + // Schedule the first transaction for EP0 transfer + edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); + return true; + } + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint16_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint16_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) num_packets++; + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + +static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if(dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ( (epnum == 0) || !(in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPENA) ){ + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK | (stall ? USB_OTG_DIEPCTL_STALL : 0); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK; + while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0); + + // Disable the endpoint. + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPDIS | (stall ? USB_OTG_DIEPCTL_STALL : 0); + while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_EPDISD_Msk) == 0); + in_ep[epnum].DIEPINT = USB_OTG_DIEPINT_EPDISD; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + usb_otg->GRSTCTL |= (epnum << USB_OTG_GRSTCTL_TXFNUM_Pos); + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH; + while((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH_Msk) != 0); + } else { + // Only disable currently enabled non-control endpoint + if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){ + out_ep[epnum].DOEPCTL |= stall ? USB_OTG_DOEPCTL_STALL : 0; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + dev->DCTL |= USB_OTG_DCTL_SGONAK; + while((usb_otg->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0); + + // Ditto here- disable the endpoint. + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPDIS | (stall ? USB_OTG_DOEPCTL_STALL : 0); + while((out_ep[epnum].DOEPINT & USB_OTG_DOEPINT_EPDISD_Msk) == 0); + out_ep[epnum].DOEPINT = USB_OTG_DOEPINT_EPDISD; + + // Allow other OUT endpoints to keep receiving. + dev->DCTL |= USB_OTG_DCTL_CGONAK; + } + } +} + +/** + * Close an endpoint. + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_edpt_disable(rhport, ep_addr, false); + + // Update max_size + xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation + + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; + // For now only the last opened endpoint can be closed without fuss. + TU_ASSERT(fifo_start == EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,); + _allocated_fifo_words_tx -= fifo_size; + } + else + { + _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty + } +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + dcd_edpt_disable(rhport, ep_addr, true); +} + +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // Clear stall and reset data toggle + if(dir == TUSB_DIR_IN) { + in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; + } else { + out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; + } +} + +/*------------------------------------------------------------------*/ + +// Read a single data packet from receive FIFO +static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len) +{ + (void) rhport; + + usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); + + // Reading full available 32 bit words from fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + dst[1] = (tmp & 0x0000FF00) >> 8; + dst[2] = (tmp & 0x00FF0000) >> 16; + dst[3] = (tmp & 0xFF000000) >> 24; + dst += 4; + } + + // Read the remaining 1-3 bytes from fifo + uint8_t bytes_rem = len & 0x03; + if(bytes_rem != 0) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + if(bytes_rem > 1) { + dst[1] = (tmp & 0x0000FF00) >> 8; + } + if(bytes_rem > 2) { + dst[2] = (tmp & 0x00FF0000) >> 16; + } + } +} + +// Write a single data packet to EPIN FIFO +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, uint16_t len) +{ + (void) rhport; + + usb_fifo_t tx_fifo = FIFO_BASE(rhport, fifo_num); + + // Pushing full available 32 bit words to fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++){ + *tx_fifo = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; + src += 4; + } + + // Write the remaining 1-3 bytes into fifo + uint8_t bytes_rem = len & 0x03; + if(bytes_rem){ + uint32_t tmp_word = 0; + tmp_word |= src[0]; + if(bytes_rem > 1){ + tmp_word |= src[1] << 8; + } + if(bytes_rem > 2){ + tmp_word |= src[2] << 16; + } + *tx_fifo = tmp_word; + } +} + +static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); + + // Pop control word off FIFO + uint32_t ctl_word = usb_otg->GRXSTSP; + uint8_t pktsts = (ctl_word & USB_OTG_GRXSTSP_PKTSTS_Msk) >> USB_OTG_GRXSTSP_PKTSTS_Pos; + uint8_t epnum = (ctl_word & USB_OTG_GRXSTSP_EPNUM_Msk) >> USB_OTG_GRXSTSP_EPNUM_Pos; + uint16_t bcnt = (ctl_word & USB_OTG_GRXSTSP_BCNT_Msk) >> USB_OTG_GRXSTSP_BCNT_Pos; + + switch(pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + break; + + case 0x02: // Out packet recvd + { + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + + // Read packet off RxFIFO + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *)(uintptr_t) rx_fifo, bcnt); + } + else + { + // Linear buffer + read_fifo_packet(rhport, xfer->buffer, bcnt); + + // Increment pointer to xfer data + xfer->buffer += bcnt; + } + + // Truncate transfer length in case of short packet + if(bcnt < xfer->max_size) { + xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; + if(epnum == 0) { + xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + ep0_pending[TUSB_DIR_OUT] = 0; + } + } + } + break; + + case 0x03: // Out packet done (Interrupt) + break; + + case 0x04: // Setup packet done (Interrupt) + out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); + break; + + case 0x06: // Setup packet recvd + // We can receive up to three setup packets in succession, but + // only the last one is valid. + _setup_packet[0] = (* rx_fifo); + _setup_packet[1] = (* rx_fifo); + break; + + default: // Invalid + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) { + // DAINT for a given EP clears when DOEPINTx is cleared. + // OEPINT will be cleared when DAINT's out bits are cleared. + for(uint8_t n = 0; n < EP_MAX; n++) { + xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if(dev->DAINT & (1 << (USB_OTG_DAINT_OEPINT_Pos + n))) { + // SETUP packet Setup Phase done. + if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) { + out_ep[n].DOEPINT = USB_OTG_DOEPINT_STUP; + dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[0], true); + } + + // OUT XFER complete + if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) { + out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC; + + // EP0 can only handle one packet + if((n == 0) && ep0_pending[TUSB_DIR_OUT]) { + // Schedule another packet to be received. + edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); + } else { + dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + } +} + +static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) { + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for ( uint8_t n = 0; n < EP_MAX; n++ ) + { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + + if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) ) + { + // IN XFER complete (entire xfer). + if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) + { + in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC; + + // EP0 can only handle one packet + if((n == 0) && ep0_pending[TUSB_DIR_IN]) { + // Schedule another packet to be transmitted. + edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); + } else { + dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + + // XFER FIFO empty + if ( (in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) && (dev->DIEPEMPMSK & (1 << n)) ) + { + // DIEPINT's TXFE bit is read-only, software cannot clear it. + // It will only be cleared by hardware when written bytes is more than + // - 64 bytes or + // - Half of TX FIFO size (configured by DIEPTXF) + + uint16_t remaining_packets = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; + + // Process every single packet (only whole packets can be written to fifo) + for(uint16_t i = 0; i < remaining_packets; i++) + { + uint16_t const remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + + // Packet can not be larger than ep max size + uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size); + + // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current + // EP has to be checked if the buffer can take another WHOLE packet + if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)) break; + + // Push packet to Tx-FIFO + if (xfer->ff) + { + usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *)(uintptr_t) tx_fifo, packet_size); + } + else + { + write_fifo_packet(rhport, n, xfer->buffer, packet_size); + + // Increment pointer to xfer data + xfer->buffer += packet_size; + } + } + + // Turn off TXFE if all bytes are written. + if (((in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos) == 0) + { + dev->DIEPEMPMSK &= ~(1 << n); + } + } + } + } +} + +void dcd_int_handler(uint8_t rhport) +{ + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + uint32_t const int_status = usb_otg->GINTSTS & usb_otg->GINTMSK; + + if(int_status & USB_OTG_GINTSTS_USBRST) + { + // USBRST is start of reset. + usb_otg->GINTSTS = USB_OTG_GINTSTS_USBRST; + bus_reset(rhport); + } + + if(int_status & USB_OTG_GINTSTS_ENUMDNE) + { + // ENUMDNE is the end of reset where speed of the link is detected + + usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; + + tusb_speed_t const speed = get_speed(rhport); + + set_turnaround(usb_otg, speed); + dcd_event_bus_reset(rhport, speed, true); + } + + if(int_status & USB_OTG_GINTSTS_USBSUSP) + { + usb_otg->GINTSTS = USB_OTG_GINTSTS_USBSUSP; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + if(int_status & USB_OTG_GINTSTS_WKUINT) + { + usb_otg->GINTSTS = USB_OTG_GINTSTS_WKUINT; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + + // TODO check USB_OTG_GINTSTS_DISCINT for disconnect detection + // if(int_status & USB_OTG_GINTSTS_DISCINT) + + if(int_status & USB_OTG_GINTSTS_OTGINT) + { + // OTG INT bit is read-only + uint32_t const otg_int = usb_otg->GOTGINT; + + if (otg_int & USB_OTG_GOTGINT_SEDET) + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + + usb_otg->GOTGINT = otg_int; + } + + if(int_status & USB_OTG_GINTSTS_SOF) + { + usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + + // Disable SOF interrupt since currently only used for remote wakeup detection + usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; + + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + + // RxFIFO non-empty interrupt handling. + if(int_status & USB_OTG_GINTSTS_RXFLVL) + { + // RXFLVL bit is read-only + + // Mask out RXFLVL while reading data from FIFO + usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; + + // Loop until all available packets were handled + do + { + handle_rxflvl_ints(rhport, out_ep); + } while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL); + + // Manage RX FIFO size + if (_out_ep_closed) + { + update_grxfsiz(rhport); + + // Disable flag + _out_ep_closed = false; + } + + usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + } + + // OUT endpoint interrupt handling. + if(int_status & USB_OTG_GINTSTS_OEPINT) + { + // OEPINT is read-only + handle_epout_ints(rhport, dev, out_ep); + } + + // IN endpoint interrupt handling. + if(int_status & USB_OTG_GINTSTS_IEPINT) + { + // IEPINT bit read-only + handle_epin_ints(rhport, dev, in_ep); + } + + // // Check for Incomplete isochronous IN transfer + // if(int_status & USB_OTG_GINTSTS_IISOIXFR) { + // printf(" IISOIXFR!\r\n"); + //// TU_LOG2(" IISOIXFR!\r\n"); + // } +} + +#endif diff --git a/src/portable/broadcom/synopsys/synopsys_common.h b/src/portable/broadcom/synopsys/synopsys_common.h new file mode 100644 index 000000000..81ce3b4a9 --- /dev/null +++ b/src/portable/broadcom/synopsys/synopsys_common.h @@ -0,0 +1,1476 @@ +/** + ****************************************************************************** + * @file synopsys_common.h + * @author MCD Application Team + * @brief CMSIS Cortex-M3 Device USB OTG peripheral Header File. + * This file contains the USB OTG peripheral register's definitions, bits + * definitions and memory mapping for STM32F1xx devices. + * + * This file contains: + * - Data structures and the address mapping for the USB OTG peripheral + * - The Peripheral's registers declarations and bits definition + * - Macros to access the peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#include "stdint.h" + +#pragma once + +#ifdef __cplusplus + #define __I volatile +#else + #define __I volatile const +#endif +#define __O volatile +#define __IO volatile +#define __IM volatile const +#define __OM volatile +#define __IOM volatile + +/** + * @brief __USB_OTG_Core_register + */ + +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register Address offset: 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register Address offset: 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register Address offset: 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register Address offset: 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register Address offset: 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register Address offset: 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register Address offset: 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register Address offset: 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register Address offset: 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register Address offset: 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register Address offset: 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg Address offset: 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h*/ + __IO uint32_t GCCFG; /*!< General Purpose IO Register Address offset: 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */ + uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg Address offset: 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO Address offset: 0x104 */ +} USB_OTG_GlobalTypeDef; + + + +/** + * @brief __device_Registers + */ + +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register Address offset: 800h*/ + __IO uint32_t DCTL; /*!< dev Control Register Address offset: 804h*/ + __IO uint32_t DSTS; /*!< dev Status Register (RO) Address offset: 808h*/ + uint32_t Reserved0C; /*!< Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask Address offset: 810h*/ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask Address offset: 814h*/ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg Address offset: 818h*/ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask Address offset: 81Ch*/ + uint32_t Reserved20; /*!< Reserved 820h*/ + uint32_t Reserved9; /*!< Reserved 824h*/ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register Address offset: 828h*/ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register Address offset: 82Ch*/ + __IO uint32_t DTHRCTL; /*!< dev thr Address offset: 830h*/ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk Address offset: 834h*/ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt Address offset: 838h*/ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk Address offset: 83Ch*/ + uint32_t Reserved40; /*!< dedicated EP mask Address offset: 840h*/ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask Address offset: 844h*/ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch*/ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk Address offset: 884h*/ +} USB_OTG_DeviceTypeDef; + +/** + * @brief __IN_Endpoint-Specific_Register + */ + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief __OUT_Endpoint-Specific_Registers + */ + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief __Host_Mode_Register_Structures + */ + +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h*/ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /*!< Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h*/ +} USB_OTG_HostTypeDef; + +/** + * @brief __Host_Channel_Specific_Registers + */ + +typedef struct +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} USB_OTG_HostChannelTypeDef; + +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE 0x50000000UL + +// #define USB_OTG_GLOBAL_BASE 0x00000000UL +// #define USB_OTG_DEVICE_BASE 0x00000800UL +#define USB_OTG_IN_ENDPOINT_BASE 0x00000900UL +#define USB_OTG_OUT_ENDPOINT_BASE 0x00000B00UL +#define USB_OTG_EP_REG_SIZE 0x00000020UL +// #define USB_OTG_HOST_BASE 0x00000400UL +#define USB_OTG_HOST_PORT_BASE 0x00000440UL +#define USB_OTG_HOST_CHANNEL_BASE 0x00000500UL +#define USB_OTG_HOST_CHANNEL_SIZE 0x00000020UL +#define USB_OTG_PCGCCTL_BASE 0x00000E00UL +#define USB_OTG_FIFO_BASE 0x00001000UL +#define USB_OTG_FIFO_SIZE 0x00001000UL + +/******************************************************************************/ +/* */ +/* USB_OTG */ +/* */ +/******************************************************************************/ +/******************** Bit definition for USB_OTG_GOTGCTL register ***********/ +#define USB_OTG_GOTGCTL_SRQSCS_Pos (0U) +#define USB_OTG_GOTGCTL_SRQSCS_Msk (0x1UL << USB_OTG_GOTGCTL_SRQSCS_Pos) /*!< 0x00000001 */ +#define USB_OTG_GOTGCTL_SRQSCS USB_OTG_GOTGCTL_SRQSCS_Msk /*!< Session request success */ +#define USB_OTG_GOTGCTL_SRQ_Pos (1U) +#define USB_OTG_GOTGCTL_SRQ_Msk (0x1UL << USB_OTG_GOTGCTL_SRQ_Pos) /*!< 0x00000002 */ +#define USB_OTG_GOTGCTL_SRQ USB_OTG_GOTGCTL_SRQ_Msk /*!< Session request */ +#define USB_OTG_GOTGCTL_HNGSCS_Pos (8U) +#define USB_OTG_GOTGCTL_HNGSCS_Msk (0x1UL << USB_OTG_GOTGCTL_HNGSCS_Pos) /*!< 0x00000100 */ +#define USB_OTG_GOTGCTL_HNGSCS USB_OTG_GOTGCTL_HNGSCS_Msk /*!< Host set HNP enable */ +#define USB_OTG_GOTGCTL_HNPRQ_Pos (9U) +#define USB_OTG_GOTGCTL_HNPRQ_Msk (0x1UL << USB_OTG_GOTGCTL_HNPRQ_Pos) /*!< 0x00000200 */ +#define USB_OTG_GOTGCTL_HNPRQ USB_OTG_GOTGCTL_HNPRQ_Msk /*!< HNP request */ +#define USB_OTG_GOTGCTL_HSHNPEN_Pos (10U) +#define USB_OTG_GOTGCTL_HSHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_HSHNPEN_Pos) /*!< 0x00000400 */ +#define USB_OTG_GOTGCTL_HSHNPEN USB_OTG_GOTGCTL_HSHNPEN_Msk /*!< Host set HNP enable */ +#define USB_OTG_GOTGCTL_DHNPEN_Pos (11U) +#define USB_OTG_GOTGCTL_DHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_DHNPEN_Pos) /*!< 0x00000800 */ +#define USB_OTG_GOTGCTL_DHNPEN USB_OTG_GOTGCTL_DHNPEN_Msk /*!< Device HNP enabled */ +#define USB_OTG_GOTGCTL_CIDSTS_Pos (16U) +#define USB_OTG_GOTGCTL_CIDSTS_Msk (0x1UL << USB_OTG_GOTGCTL_CIDSTS_Pos) /*!< 0x00010000 */ +#define USB_OTG_GOTGCTL_CIDSTS USB_OTG_GOTGCTL_CIDSTS_Msk /*!< Connector ID status */ +#define USB_OTG_GOTGCTL_DBCT_Pos (17U) +#define USB_OTG_GOTGCTL_DBCT_Msk (0x1UL << USB_OTG_GOTGCTL_DBCT_Pos) /*!< 0x00020000 */ +#define USB_OTG_GOTGCTL_DBCT USB_OTG_GOTGCTL_DBCT_Msk /*!< Long/short debounce time */ +#define USB_OTG_GOTGCTL_ASVLD_Pos (18U) +#define USB_OTG_GOTGCTL_ASVLD_Msk (0x1UL << USB_OTG_GOTGCTL_ASVLD_Pos) /*!< 0x00040000 */ +#define USB_OTG_GOTGCTL_ASVLD USB_OTG_GOTGCTL_ASVLD_Msk /*!< A-session valid */ +#define USB_OTG_GOTGCTL_BSVLD_Pos (19U) +#define USB_OTG_GOTGCTL_BSVLD_Msk (0x1UL << USB_OTG_GOTGCTL_BSVLD_Pos) /*!< 0x00080000 */ +#define USB_OTG_GOTGCTL_BSVLD USB_OTG_GOTGCTL_BSVLD_Msk /*!< B-session valid */ + +/******************** Bit definition for USB_OTG_HCFG register ********************/ + +#define USB_OTG_HCFG_FSLSPCS_Pos (0U) +#define USB_OTG_HCFG_FSLSPCS_Msk (0x3UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000003 */ +#define USB_OTG_HCFG_FSLSPCS USB_OTG_HCFG_FSLSPCS_Msk /*!< FS/LS PHY clock select */ +#define USB_OTG_HCFG_FSLSPCS_0 (0x1UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCFG_FSLSPCS_1 (0x2UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCFG_FSLSS_Pos (2U) +#define USB_OTG_HCFG_FSLSS_Msk (0x1UL << USB_OTG_HCFG_FSLSS_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCFG_FSLSS USB_OTG_HCFG_FSLSS_Msk /*!< FS- and LS-only support */ + +/******************** Bit definition for USB_OTG_DCFG register ********************/ + +#define USB_OTG_DCFG_DSPD_Pos (0U) +#define USB_OTG_DCFG_DSPD_Msk (0x3UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000003 */ +#define USB_OTG_DCFG_DSPD USB_OTG_DCFG_DSPD_Msk /*!< Device speed */ +#define USB_OTG_DCFG_DSPD_0 (0x1UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000001 */ +#define USB_OTG_DCFG_DSPD_1 (0x2UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DCFG_NZLSOHSK_Pos (2U) +#define USB_OTG_DCFG_NZLSOHSK_Msk (0x1UL << USB_OTG_DCFG_NZLSOHSK_Pos) /*!< 0x00000004 */ +#define USB_OTG_DCFG_NZLSOHSK USB_OTG_DCFG_NZLSOHSK_Msk /*!< Nonzero-length status OUT handshake */ + +#define USB_OTG_DCFG_DAD_Pos (4U) +#define USB_OTG_DCFG_DAD_Msk (0x7FUL << USB_OTG_DCFG_DAD_Pos) /*!< 0x000007F0 */ +#define USB_OTG_DCFG_DAD USB_OTG_DCFG_DAD_Msk /*!< Device address */ +#define USB_OTG_DCFG_DAD_0 (0x01UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000010 */ +#define USB_OTG_DCFG_DAD_1 (0x02UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000020 */ +#define USB_OTG_DCFG_DAD_2 (0x04UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000040 */ +#define USB_OTG_DCFG_DAD_3 (0x08UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000080 */ +#define USB_OTG_DCFG_DAD_4 (0x10UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000100 */ +#define USB_OTG_DCFG_DAD_5 (0x20UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000200 */ +#define USB_OTG_DCFG_DAD_6 (0x40UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000400 */ + +#define USB_OTG_DCFG_PFIVL_Pos (11U) +#define USB_OTG_DCFG_PFIVL_Msk (0x3UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001800 */ +#define USB_OTG_DCFG_PFIVL USB_OTG_DCFG_PFIVL_Msk /*!< Periodic (micro)frame interval */ +#define USB_OTG_DCFG_PFIVL_0 (0x1UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00000800 */ +#define USB_OTG_DCFG_PFIVL_1 (0x2UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001000 */ + +#define USB_OTG_DCFG_PERSCHIVL_Pos (24U) +#define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */ +#define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */ +#define USB_OTG_DCFG_PERSCHIVL_0 (0x1UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x01000000 */ +#define USB_OTG_DCFG_PERSCHIVL_1 (0x2UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x02000000 */ + +/******************** Bit definition for USB_OTG_PCGCR register ********************/ +#define USB_OTG_PCGCR_STPPCLK_Pos (0U) +#define USB_OTG_PCGCR_STPPCLK_Msk (0x1UL << USB_OTG_PCGCR_STPPCLK_Pos) /*!< 0x00000001 */ +#define USB_OTG_PCGCR_STPPCLK USB_OTG_PCGCR_STPPCLK_Msk /*!< Stop PHY clock */ +#define USB_OTG_PCGCR_GATEHCLK_Pos (1U) +#define USB_OTG_PCGCR_GATEHCLK_Msk (0x1UL << USB_OTG_PCGCR_GATEHCLK_Pos) /*!< 0x00000002 */ +#define USB_OTG_PCGCR_GATEHCLK USB_OTG_PCGCR_GATEHCLK_Msk /*!< Gate HCLK */ +#define USB_OTG_PCGCR_PHYSUSP_Pos (4U) +#define USB_OTG_PCGCR_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCR_PHYSUSP_Pos) /*!< 0x00000010 */ +#define USB_OTG_PCGCR_PHYSUSP USB_OTG_PCGCR_PHYSUSP_Msk /*!< PHY suspended */ + +/******************** Bit definition for USB_OTG_GOTGINT register ********************/ +#define USB_OTG_GOTGINT_SEDET_Pos (2U) +#define USB_OTG_GOTGINT_SEDET_Msk (0x1UL << USB_OTG_GOTGINT_SEDET_Pos) /*!< 0x00000004 */ +#define USB_OTG_GOTGINT_SEDET USB_OTG_GOTGINT_SEDET_Msk /*!< Session end detected */ +#define USB_OTG_GOTGINT_SRSSCHG_Pos (8U) +#define USB_OTG_GOTGINT_SRSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_SRSSCHG_Pos) /*!< 0x00000100 */ +#define USB_OTG_GOTGINT_SRSSCHG USB_OTG_GOTGINT_SRSSCHG_Msk /*!< Session request success status change */ +#define USB_OTG_GOTGINT_HNSSCHG_Pos (9U) +#define USB_OTG_GOTGINT_HNSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_HNSSCHG_Pos) /*!< 0x00000200 */ +#define USB_OTG_GOTGINT_HNSSCHG USB_OTG_GOTGINT_HNSSCHG_Msk /*!< Host negotiation success status change */ +#define USB_OTG_GOTGINT_HNGDET_Pos (17U) +#define USB_OTG_GOTGINT_HNGDET_Msk (0x1UL << USB_OTG_GOTGINT_HNGDET_Pos) /*!< 0x00020000 */ +#define USB_OTG_GOTGINT_HNGDET USB_OTG_GOTGINT_HNGDET_Msk /*!< Host negotiation detected */ +#define USB_OTG_GOTGINT_ADTOCHG_Pos (18U) +#define USB_OTG_GOTGINT_ADTOCHG_Msk (0x1UL << USB_OTG_GOTGINT_ADTOCHG_Pos) /*!< 0x00040000 */ +#define USB_OTG_GOTGINT_ADTOCHG USB_OTG_GOTGINT_ADTOCHG_Msk /*!< A-device timeout change */ +#define USB_OTG_GOTGINT_DBCDNE_Pos (19U) +#define USB_OTG_GOTGINT_DBCDNE_Msk (0x1UL << USB_OTG_GOTGINT_DBCDNE_Pos) /*!< 0x00080000 */ +#define USB_OTG_GOTGINT_DBCDNE USB_OTG_GOTGINT_DBCDNE_Msk /*!< Debounce done */ + +/******************** Bit definition for USB_OTG_DCTL register ********************/ +#define USB_OTG_DCTL_RWUSIG_Pos (0U) +#define USB_OTG_DCTL_RWUSIG_Msk (0x1UL << USB_OTG_DCTL_RWUSIG_Pos) /*!< 0x00000001 */ +#define USB_OTG_DCTL_RWUSIG USB_OTG_DCTL_RWUSIG_Msk /*!< Remote wakeup signaling */ +#define USB_OTG_DCTL_SDIS_Pos (1U) +#define USB_OTG_DCTL_SDIS_Msk (0x1UL << USB_OTG_DCTL_SDIS_Pos) /*!< 0x00000002 */ +#define USB_OTG_DCTL_SDIS USB_OTG_DCTL_SDIS_Msk /*!< Soft disconnect */ +#define USB_OTG_DCTL_GINSTS_Pos (2U) +#define USB_OTG_DCTL_GINSTS_Msk (0x1UL << USB_OTG_DCTL_GINSTS_Pos) /*!< 0x00000004 */ +#define USB_OTG_DCTL_GINSTS USB_OTG_DCTL_GINSTS_Msk /*!< Global IN NAK status */ +#define USB_OTG_DCTL_GONSTS_Pos (3U) +#define USB_OTG_DCTL_GONSTS_Msk (0x1UL << USB_OTG_DCTL_GONSTS_Pos) /*!< 0x00000008 */ +#define USB_OTG_DCTL_GONSTS USB_OTG_DCTL_GONSTS_Msk /*!< Global OUT NAK status */ + +#define USB_OTG_DCTL_TCTL_Pos (4U) +#define USB_OTG_DCTL_TCTL_Msk (0x7UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000070 */ +#define USB_OTG_DCTL_TCTL USB_OTG_DCTL_TCTL_Msk /*!< Test control */ +#define USB_OTG_DCTL_TCTL_0 (0x1UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000010 */ +#define USB_OTG_DCTL_TCTL_1 (0x2UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000020 */ +#define USB_OTG_DCTL_TCTL_2 (0x4UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000040 */ +#define USB_OTG_DCTL_SGINAK_Pos (7U) +#define USB_OTG_DCTL_SGINAK_Msk (0x1UL << USB_OTG_DCTL_SGINAK_Pos) /*!< 0x00000080 */ +#define USB_OTG_DCTL_SGINAK USB_OTG_DCTL_SGINAK_Msk /*!< Set global IN NAK */ +#define USB_OTG_DCTL_CGINAK_Pos (8U) +#define USB_OTG_DCTL_CGINAK_Msk (0x1UL << USB_OTG_DCTL_CGINAK_Pos) /*!< 0x00000100 */ +#define USB_OTG_DCTL_CGINAK USB_OTG_DCTL_CGINAK_Msk /*!< Clear global IN NAK */ +#define USB_OTG_DCTL_SGONAK_Pos (9U) +#define USB_OTG_DCTL_SGONAK_Msk (0x1UL << USB_OTG_DCTL_SGONAK_Pos) /*!< 0x00000200 */ +#define USB_OTG_DCTL_SGONAK USB_OTG_DCTL_SGONAK_Msk /*!< Set global OUT NAK */ +#define USB_OTG_DCTL_CGONAK_Pos (10U) +#define USB_OTG_DCTL_CGONAK_Msk (0x1UL << USB_OTG_DCTL_CGONAK_Pos) /*!< 0x00000400 */ +#define USB_OTG_DCTL_CGONAK USB_OTG_DCTL_CGONAK_Msk /*!< Clear global OUT NAK */ +#define USB_OTG_DCTL_POPRGDNE_Pos (11U) +#define USB_OTG_DCTL_POPRGDNE_Msk (0x1UL << USB_OTG_DCTL_POPRGDNE_Pos) /*!< 0x00000800 */ +#define USB_OTG_DCTL_POPRGDNE USB_OTG_DCTL_POPRGDNE_Msk /*!< Power-on programming done */ + +/******************** Bit definition for USB_OTG_HFIR register ********************/ +#define USB_OTG_HFIR_FRIVL_Pos (0U) +#define USB_OTG_HFIR_FRIVL_Msk (0xFFFFUL << USB_OTG_HFIR_FRIVL_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HFIR_FRIVL USB_OTG_HFIR_FRIVL_Msk /*!< Frame interval */ + +/******************** Bit definition for USB_OTG_HFNUM register ********************/ +#define USB_OTG_HFNUM_FRNUM_Pos (0U) +#define USB_OTG_HFNUM_FRNUM_Msk (0xFFFFUL << USB_OTG_HFNUM_FRNUM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HFNUM_FRNUM USB_OTG_HFNUM_FRNUM_Msk /*!< Frame number */ +#define USB_OTG_HFNUM_FTREM_Pos (16U) +#define USB_OTG_HFNUM_FTREM_Msk (0xFFFFUL << USB_OTG_HFNUM_FTREM_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_HFNUM_FTREM USB_OTG_HFNUM_FTREM_Msk /*!< Frame time remaining */ + +/******************** Bit definition for USB_OTG_DSTS register ********************/ +#define USB_OTG_DSTS_SUSPSTS_Pos (0U) +#define USB_OTG_DSTS_SUSPSTS_Msk (0x1UL << USB_OTG_DSTS_SUSPSTS_Pos) /*!< 0x00000001 */ +#define USB_OTG_DSTS_SUSPSTS USB_OTG_DSTS_SUSPSTS_Msk /*!< Suspend status */ + +#define USB_OTG_DSTS_ENUMSPD_Pos (1U) +#define USB_OTG_DSTS_ENUMSPD_Msk (0x3UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000006 */ +#define USB_OTG_DSTS_ENUMSPD USB_OTG_DSTS_ENUMSPD_Msk /*!< Enumerated speed */ +#define USB_OTG_DSTS_ENUMSPD_0 (0x1UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DSTS_ENUMSPD_1 (0x2UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000004 */ +#define USB_OTG_DSTS_EERR_Pos (3U) +#define USB_OTG_DSTS_EERR_Msk (0x1UL << USB_OTG_DSTS_EERR_Pos) /*!< 0x00000008 */ +#define USB_OTG_DSTS_EERR USB_OTG_DSTS_EERR_Msk /*!< Erratic error */ +#define USB_OTG_DSTS_FNSOF_Pos (8U) +#define USB_OTG_DSTS_FNSOF_Msk (0x3FFFUL << USB_OTG_DSTS_FNSOF_Pos) /*!< 0x003FFF00 */ +#define USB_OTG_DSTS_FNSOF USB_OTG_DSTS_FNSOF_Msk /*!< Frame number of the received SOF */ + +/******************** Bit definition for USB_OTG_GAHBCFG register ********************/ +#define USB_OTG_GAHBCFG_GINT_Pos (0U) +#define USB_OTG_GAHBCFG_GINT_Msk (0x1UL << USB_OTG_GAHBCFG_GINT_Pos) /*!< 0x00000001 */ +#define USB_OTG_GAHBCFG_GINT USB_OTG_GAHBCFG_GINT_Msk /*!< Global interrupt mask */ +#define USB_OTG_GAHBCFG_HBSTLEN_Pos (1U) +#define USB_OTG_GAHBCFG_HBSTLEN_Msk (0xFUL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< 0x0000001E */ +#define USB_OTG_GAHBCFG_HBSTLEN USB_OTG_GAHBCFG_HBSTLEN_Msk /*!< Burst length/type */ +#define USB_OTG_GAHBCFG_HBSTLEN_0 (0x0UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< Single */ +#define USB_OTG_GAHBCFG_HBSTLEN_1 (0x1UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR */ +#define USB_OTG_GAHBCFG_HBSTLEN_2 (0x3UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR4 */ +#define USB_OTG_GAHBCFG_HBSTLEN_3 (0x5UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR8 */ +#define USB_OTG_GAHBCFG_HBSTLEN_4 (0x7UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR16 */ +#define USB_OTG_GAHBCFG_DMAEN_Pos (5U) +#define USB_OTG_GAHBCFG_DMAEN_Msk (0x1UL << USB_OTG_GAHBCFG_DMAEN_Pos) /*!< 0x00000020 */ +#define USB_OTG_GAHBCFG_DMAEN USB_OTG_GAHBCFG_DMAEN_Msk /*!< DMA enable */ +#define USB_OTG_GAHBCFG_TXFELVL_Pos (7U) +#define USB_OTG_GAHBCFG_TXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_TXFELVL_Pos) /*!< 0x00000080 */ +#define USB_OTG_GAHBCFG_TXFELVL USB_OTG_GAHBCFG_TXFELVL_Msk /*!< TxFIFO empty level */ +#define USB_OTG_GAHBCFG_PTXFELVL_Pos (8U) +#define USB_OTG_GAHBCFG_PTXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_PTXFELVL_Pos) /*!< 0x00000100 */ +#define USB_OTG_GAHBCFG_PTXFELVL USB_OTG_GAHBCFG_PTXFELVL_Msk /*!< Periodic TxFIFO empty level */ + +/******************** Bit definition for USB_OTG_GUSBCFG register ********************/ + +#define USB_OTG_GUSBCFG_TOCAL_Pos (0U) +#define USB_OTG_GUSBCFG_TOCAL_Msk (0x7UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000007 */ +#define USB_OTG_GUSBCFG_TOCAL USB_OTG_GUSBCFG_TOCAL_Msk /*!< FS timeout calibration */ +#define USB_OTG_GUSBCFG_TOCAL_0 (0x1UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000001 */ +#define USB_OTG_GUSBCFG_TOCAL_1 (0x2UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000002 */ +#define USB_OTG_GUSBCFG_TOCAL_2 (0x4UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000004 */ +#define USB_OTG_GUSBCFG_PHYSEL_Pos (6U) +#define USB_OTG_GUSBCFG_PHYSEL_Msk (0x1UL << USB_OTG_GUSBCFG_PHYSEL_Pos) /*!< 0x00000040 */ +#define USB_OTG_GUSBCFG_PHYSEL USB_OTG_GUSBCFG_PHYSEL_Msk /*!< USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ +#define USB_OTG_GUSBCFG_SRPCAP_Pos (8U) +#define USB_OTG_GUSBCFG_SRPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_SRPCAP_Pos) /*!< 0x00000100 */ +#define USB_OTG_GUSBCFG_SRPCAP USB_OTG_GUSBCFG_SRPCAP_Msk /*!< SRP-capable */ +#define USB_OTG_GUSBCFG_HNPCAP_Pos (9U) +#define USB_OTG_GUSBCFG_HNPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_HNPCAP_Pos) /*!< 0x00000200 */ +#define USB_OTG_GUSBCFG_HNPCAP USB_OTG_GUSBCFG_HNPCAP_Msk /*!< HNP-capable */ +#define USB_OTG_GUSBCFG_TRDT_Pos (10U) +#define USB_OTG_GUSBCFG_TRDT_Msk (0xFUL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00003C00 */ +#define USB_OTG_GUSBCFG_TRDT USB_OTG_GUSBCFG_TRDT_Msk /*!< USB turnaround time */ +#define USB_OTG_GUSBCFG_TRDT_0 (0x1UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000400 */ +#define USB_OTG_GUSBCFG_TRDT_1 (0x2UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000800 */ +#define USB_OTG_GUSBCFG_TRDT_2 (0x4UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00001000 */ +#define USB_OTG_GUSBCFG_TRDT_3 (0x8UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00002000 */ +#define USB_OTG_GUSBCFG_PHYLPCS_Pos (15U) +#define USB_OTG_GUSBCFG_PHYLPCS_Msk (0x1UL << USB_OTG_GUSBCFG_PHYLPCS_Pos) /*!< 0x00008000 */ +#define USB_OTG_GUSBCFG_PHYLPCS USB_OTG_GUSBCFG_PHYLPCS_Msk /*!< PHY Low-power clock select */ +#define USB_OTG_GUSBCFG_ULPIFSLS_Pos (17U) +#define USB_OTG_GUSBCFG_ULPIFSLS_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIFSLS_Pos) /*!< 0x00020000 */ +#define USB_OTG_GUSBCFG_ULPIFSLS USB_OTG_GUSBCFG_ULPIFSLS_Msk /*!< ULPI FS/LS select */ +#define USB_OTG_GUSBCFG_ULPIAR_Pos (18U) +#define USB_OTG_GUSBCFG_ULPIAR_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIAR_Pos) /*!< 0x00040000 */ +#define USB_OTG_GUSBCFG_ULPIAR USB_OTG_GUSBCFG_ULPIAR_Msk /*!< ULPI Auto-resume */ +#define USB_OTG_GUSBCFG_ULPICSM_Pos (19U) +#define USB_OTG_GUSBCFG_ULPICSM_Msk (0x1UL << USB_OTG_GUSBCFG_ULPICSM_Pos) /*!< 0x00080000 */ +#define USB_OTG_GUSBCFG_ULPICSM USB_OTG_GUSBCFG_ULPICSM_Msk /*!< ULPI Clock SuspendM */ +#define USB_OTG_GUSBCFG_ULPIEVBUSD_Pos (20U) +#define USB_OTG_GUSBCFG_ULPIEVBUSD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSD_Pos) /*!< 0x00100000 */ +#define USB_OTG_GUSBCFG_ULPIEVBUSD USB_OTG_GUSBCFG_ULPIEVBUSD_Msk /*!< ULPI External VBUS Drive */ +#define USB_OTG_GUSBCFG_ULPIEVBUSI_Pos (21U) +#define USB_OTG_GUSBCFG_ULPIEVBUSI_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSI_Pos) /*!< 0x00200000 */ +#define USB_OTG_GUSBCFG_ULPIEVBUSI USB_OTG_GUSBCFG_ULPIEVBUSI_Msk /*!< ULPI external VBUS indicator */ +#define USB_OTG_GUSBCFG_TSDPS_Pos (22U) +#define USB_OTG_GUSBCFG_TSDPS_Msk (0x1UL << USB_OTG_GUSBCFG_TSDPS_Pos) /*!< 0x00400000 */ +#define USB_OTG_GUSBCFG_TSDPS USB_OTG_GUSBCFG_TSDPS_Msk /*!< TermSel DLine pulsing selection */ +#define USB_OTG_GUSBCFG_PCCI_Pos (23U) +#define USB_OTG_GUSBCFG_PCCI_Msk (0x1UL << USB_OTG_GUSBCFG_PCCI_Pos) /*!< 0x00800000 */ +#define USB_OTG_GUSBCFG_PCCI USB_OTG_GUSBCFG_PCCI_Msk /*!< Indicator complement */ +#define USB_OTG_GUSBCFG_PTCI_Pos (24U) +#define USB_OTG_GUSBCFG_PTCI_Msk (0x1UL << USB_OTG_GUSBCFG_PTCI_Pos) /*!< 0x01000000 */ +#define USB_OTG_GUSBCFG_PTCI USB_OTG_GUSBCFG_PTCI_Msk /*!< Indicator pass through */ +#define USB_OTG_GUSBCFG_ULPIIPD_Pos (25U) +#define USB_OTG_GUSBCFG_ULPIIPD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIIPD_Pos) /*!< 0x02000000 */ +#define USB_OTG_GUSBCFG_ULPIIPD USB_OTG_GUSBCFG_ULPIIPD_Msk /*!< ULPI interface protect disable */ +#define USB_OTG_GUSBCFG_FHMOD_Pos (29U) +#define USB_OTG_GUSBCFG_FHMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FHMOD_Pos) /*!< 0x20000000 */ +#define USB_OTG_GUSBCFG_FHMOD USB_OTG_GUSBCFG_FHMOD_Msk /*!< Forced host mode */ +#define USB_OTG_GUSBCFG_FDMOD_Pos (30U) +#define USB_OTG_GUSBCFG_FDMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FDMOD_Pos) /*!< 0x40000000 */ +#define USB_OTG_GUSBCFG_FDMOD USB_OTG_GUSBCFG_FDMOD_Msk /*!< Forced peripheral mode */ +#define USB_OTG_GUSBCFG_CTXPKT_Pos (31U) +#define USB_OTG_GUSBCFG_CTXPKT_Msk (0x1UL << USB_OTG_GUSBCFG_CTXPKT_Pos) /*!< 0x80000000 */ +#define USB_OTG_GUSBCFG_CTXPKT USB_OTG_GUSBCFG_CTXPKT_Msk /*!< Corrupt Tx packet */ + +/******************** Bit definition for USB_OTG_GRSTCTL register ********************/ +#define USB_OTG_GRSTCTL_CSRST_Pos (0U) +#define USB_OTG_GRSTCTL_CSRST_Msk (0x1UL << USB_OTG_GRSTCTL_CSRST_Pos) /*!< 0x00000001 */ +#define USB_OTG_GRSTCTL_CSRST USB_OTG_GRSTCTL_CSRST_Msk /*!< Core soft reset */ +#define USB_OTG_GRSTCTL_HSRST_Pos (1U) +#define USB_OTG_GRSTCTL_HSRST_Msk (0x1UL << USB_OTG_GRSTCTL_HSRST_Pos) /*!< 0x00000002 */ +#define USB_OTG_GRSTCTL_HSRST USB_OTG_GRSTCTL_HSRST_Msk /*!< HCLK soft reset */ +#define USB_OTG_GRSTCTL_FCRST_Pos (2U) +#define USB_OTG_GRSTCTL_FCRST_Msk (0x1UL << USB_OTG_GRSTCTL_FCRST_Pos) /*!< 0x00000004 */ +#define USB_OTG_GRSTCTL_FCRST USB_OTG_GRSTCTL_FCRST_Msk /*!< Host frame counter reset */ +#define USB_OTG_GRSTCTL_RXFFLSH_Pos (4U) +#define USB_OTG_GRSTCTL_RXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_RXFFLSH_Pos) /*!< 0x00000010 */ +#define USB_OTG_GRSTCTL_RXFFLSH USB_OTG_GRSTCTL_RXFFLSH_Msk /*!< RxFIFO flush */ +#define USB_OTG_GRSTCTL_TXFFLSH_Pos (5U) +#define USB_OTG_GRSTCTL_TXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_TXFFLSH_Pos) /*!< 0x00000020 */ +#define USB_OTG_GRSTCTL_TXFFLSH USB_OTG_GRSTCTL_TXFFLSH_Msk /*!< TxFIFO flush */ + + +#define USB_OTG_GRSTCTL_TXFNUM_Pos (6U) +#define USB_OTG_GRSTCTL_TXFNUM_Msk (0x1FUL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x000007C0 */ +#define USB_OTG_GRSTCTL_TXFNUM USB_OTG_GRSTCTL_TXFNUM_Msk /*!< TxFIFO number */ +#define USB_OTG_GRSTCTL_TXFNUM_0 (0x01UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000040 */ +#define USB_OTG_GRSTCTL_TXFNUM_1 (0x02UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000080 */ +#define USB_OTG_GRSTCTL_TXFNUM_2 (0x04UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000100 */ +#define USB_OTG_GRSTCTL_TXFNUM_3 (0x08UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000200 */ +#define USB_OTG_GRSTCTL_TXFNUM_4 (0x10UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000400 */ +#define USB_OTG_GRSTCTL_DMAREQ_Pos (30U) +#define USB_OTG_GRSTCTL_DMAREQ_Msk (0x1UL << USB_OTG_GRSTCTL_DMAREQ_Pos) /*!< 0x40000000 */ +#define USB_OTG_GRSTCTL_DMAREQ USB_OTG_GRSTCTL_DMAREQ_Msk /*!< DMA request signal */ +#define USB_OTG_GRSTCTL_AHBIDL_Pos (31U) +#define USB_OTG_GRSTCTL_AHBIDL_Msk (0x1UL << USB_OTG_GRSTCTL_AHBIDL_Pos) /*!< 0x80000000 */ +#define USB_OTG_GRSTCTL_AHBIDL USB_OTG_GRSTCTL_AHBIDL_Msk /*!< AHB master idle */ + +/******************** Bit definition for USB_OTG_DIEPMSK register ********************/ +#define USB_OTG_DIEPMSK_XFRCM_Pos (0U) +#define USB_OTG_DIEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DIEPMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPMSK_XFRCM USB_OTG_DIEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DIEPMSK_EPDM_Pos (1U) +#define USB_OTG_DIEPMSK_EPDM_Msk (0x1UL << USB_OTG_DIEPMSK_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPMSK_EPDM USB_OTG_DIEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DIEPMSK_TOM_Pos (3U) +#define USB_OTG_DIEPMSK_TOM_Msk (0x1UL << USB_OTG_DIEPMSK_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPMSK_TOM USB_OTG_DIEPMSK_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */ +#define USB_OTG_DIEPMSK_ITTXFEMSK_Pos (4U) +#define USB_OTG_DIEPMSK_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPMSK_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPMSK_ITTXFEMSK USB_OTG_DIEPMSK_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DIEPMSK_INEPNMM_Pos (5U) +#define USB_OTG_DIEPMSK_INEPNMM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DIEPMSK_INEPNMM USB_OTG_DIEPMSK_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DIEPMSK_INEPNEM_Pos (6U) +#define USB_OTG_DIEPMSK_INEPNEM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPMSK_INEPNEM USB_OTG_DIEPMSK_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DIEPMSK_TXFURM_Pos (8U) +#define USB_OTG_DIEPMSK_TXFURM_Msk (0x1UL << USB_OTG_DIEPMSK_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPMSK_TXFURM USB_OTG_DIEPMSK_TXFURM_Msk /*!< FIFO underrun mask */ +#define USB_OTG_DIEPMSK_BIM_Pos (9U) +#define USB_OTG_DIEPMSK_BIM_Msk (0x1UL << USB_OTG_DIEPMSK_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPMSK_BIM USB_OTG_DIEPMSK_BIM_Msk /*!< BNA interrupt mask */ + +/******************** Bit definition for USB_OTG_HPTXSTS register ********************/ +#define USB_OTG_HPTXSTS_PTXFSAVL_Pos (0U) +#define USB_OTG_HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << USB_OTG_HPTXSTS_PTXFSAVL_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HPTXSTS_PTXFSAVL USB_OTG_HPTXSTS_PTXFSAVL_Msk /*!< Periodic transmit data FIFO space available */ +#define USB_OTG_HPTXSTS_PTXQSAV_Pos (16U) +#define USB_OTG_HPTXSTS_PTXQSAV_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00FF0000 */ +#define USB_OTG_HPTXSTS_PTXQSAV USB_OTG_HPTXSTS_PTXQSAV_Msk /*!< Periodic transmit request queue space available */ +#define USB_OTG_HPTXSTS_PTXQSAV_0 (0x01UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00010000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_1 (0x02UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00020000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_2 (0x04UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00040000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_3 (0x08UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00080000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_4 (0x10UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00100000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_5 (0x20UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00200000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_6 (0x40UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00400000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_7 (0x80UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00800000 */ + +#define USB_OTG_HPTXSTS_PTXQTOP_Pos (24U) +#define USB_OTG_HPTXSTS_PTXQTOP_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0xFF000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP USB_OTG_HPTXSTS_PTXQTOP_Msk /*!< Top of the periodic transmit request queue */ +#define USB_OTG_HPTXSTS_PTXQTOP_0 (0x01UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x01000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_1 (0x02UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x02000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_2 (0x04UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x04000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_3 (0x08UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x08000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_4 (0x10UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x10000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_5 (0x20UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x20000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_6 (0x40UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x40000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_7 (0x80UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for USB_OTG_HAINT register ********************/ +#define USB_OTG_HAINT_HAINT_Pos (0U) +#define USB_OTG_HAINT_HAINT_Msk (0xFFFFUL << USB_OTG_HAINT_HAINT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HAINT_HAINT USB_OTG_HAINT_HAINT_Msk /*!< Channel interrupts */ + +/******************** Bit definition for USB_OTG_DOEPMSK register ********************/ +#define USB_OTG_DOEPMSK_XFRCM_Pos (0U) +#define USB_OTG_DOEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DOEPMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DOEPMSK_XFRCM USB_OTG_DOEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DOEPMSK_EPDM_Pos (1U) +#define USB_OTG_DOEPMSK_EPDM_Msk (0x1UL << USB_OTG_DOEPMSK_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DOEPMSK_EPDM USB_OTG_DOEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DOEPMSK_AHBERRM_Pos (2U) +#define USB_OTG_DOEPMSK_AHBERRM_Msk (0x1UL << USB_OTG_DOEPMSK_AHBERRM_Pos) /*!< 0x00000004 */ +#define USB_OTG_DOEPMSK_AHBERRM USB_OTG_DOEPMSK_AHBERRM_Msk /*!< OUT transaction AHB Error interrupt mask */ +#define USB_OTG_DOEPMSK_STUPM_Pos (3U) +#define USB_OTG_DOEPMSK_STUPM_Msk (0x1UL << USB_OTG_DOEPMSK_STUPM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DOEPMSK_STUPM USB_OTG_DOEPMSK_STUPM_Msk /*!< SETUP phase done mask */ +#define USB_OTG_DOEPMSK_OTEPDM_Pos (4U) +#define USB_OTG_DOEPMSK_OTEPDM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPDM_Pos) /*!< 0x00000010 */ +#define USB_OTG_DOEPMSK_OTEPDM USB_OTG_DOEPMSK_OTEPDM_Msk /*!< OUT token received when endpoint disabled mask */ +#define USB_OTG_DOEPMSK_OTEPSPRM_Pos (5U) +#define USB_OTG_DOEPMSK_OTEPSPRM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPSPRM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DOEPMSK_OTEPSPRM USB_OTG_DOEPMSK_OTEPSPRM_Msk /*!< Status Phase Received mask */ +#define USB_OTG_DOEPMSK_B2BSTUP_Pos (6U) +#define USB_OTG_DOEPMSK_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPMSK_B2BSTUP_Pos) /*!< 0x00000040 */ +#define USB_OTG_DOEPMSK_B2BSTUP USB_OTG_DOEPMSK_B2BSTUP_Msk /*!< Back-to-back SETUP packets received mask */ +#define USB_OTG_DOEPMSK_OPEM_Pos (8U) +#define USB_OTG_DOEPMSK_OPEM_Msk (0x1UL << USB_OTG_DOEPMSK_OPEM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DOEPMSK_OPEM USB_OTG_DOEPMSK_OPEM_Msk /*!< OUT packet error mask */ +#define USB_OTG_DOEPMSK_BOIM_Pos (9U) +#define USB_OTG_DOEPMSK_BOIM_Msk (0x1UL << USB_OTG_DOEPMSK_BOIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DOEPMSK_BOIM USB_OTG_DOEPMSK_BOIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DOEPMSK_BERRM_Pos (12U) +#define USB_OTG_DOEPMSK_BERRM_Msk (0x1UL << USB_OTG_DOEPMSK_BERRM_Pos) /*!< 0x00001000 */ +#define USB_OTG_DOEPMSK_BERRM USB_OTG_DOEPMSK_BERRM_Msk /*!< Babble error interrupt mask */ +#define USB_OTG_DOEPMSK_NAKM_Pos (13U) +#define USB_OTG_DOEPMSK_NAKM_Msk (0x1UL << USB_OTG_DOEPMSK_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DOEPMSK_NAKM USB_OTG_DOEPMSK_NAKM_Msk /*!< OUT Packet NAK interrupt mask */ +#define USB_OTG_DOEPMSK_NYETM_Pos (14U) +#define USB_OTG_DOEPMSK_NYETM_Msk (0x1UL << USB_OTG_DOEPMSK_NYETM_Pos) /*!< 0x00004000 */ +#define USB_OTG_DOEPMSK_NYETM USB_OTG_DOEPMSK_NYETM_Msk /*!< NYET interrupt mask */ +/******************** Bit definition for USB_OTG_GINTSTS register ********************/ +#define USB_OTG_GINTSTS_CMOD_Pos (0U) +#define USB_OTG_GINTSTS_CMOD_Msk (0x1UL << USB_OTG_GINTSTS_CMOD_Pos) /*!< 0x00000001 */ +#define USB_OTG_GINTSTS_CMOD USB_OTG_GINTSTS_CMOD_Msk /*!< Current mode of operation */ +#define USB_OTG_GINTSTS_MMIS_Pos (1U) +#define USB_OTG_GINTSTS_MMIS_Msk (0x1UL << USB_OTG_GINTSTS_MMIS_Pos) /*!< 0x00000002 */ +#define USB_OTG_GINTSTS_MMIS USB_OTG_GINTSTS_MMIS_Msk /*!< Mode mismatch interrupt */ +#define USB_OTG_GINTSTS_OTGINT_Pos (2U) +#define USB_OTG_GINTSTS_OTGINT_Msk (0x1UL << USB_OTG_GINTSTS_OTGINT_Pos) /*!< 0x00000004 */ +#define USB_OTG_GINTSTS_OTGINT USB_OTG_GINTSTS_OTGINT_Msk /*!< OTG interrupt */ +#define USB_OTG_GINTSTS_SOF_Pos (3U) +#define USB_OTG_GINTSTS_SOF_Msk (0x1UL << USB_OTG_GINTSTS_SOF_Pos) /*!< 0x00000008 */ +#define USB_OTG_GINTSTS_SOF USB_OTG_GINTSTS_SOF_Msk /*!< Start of frame */ +#define USB_OTG_GINTSTS_RXFLVL_Pos (4U) +#define USB_OTG_GINTSTS_RXFLVL_Msk (0x1UL << USB_OTG_GINTSTS_RXFLVL_Pos) /*!< 0x00000010 */ +#define USB_OTG_GINTSTS_RXFLVL USB_OTG_GINTSTS_RXFLVL_Msk /*!< RxFIFO nonempty */ +#define USB_OTG_GINTSTS_NPTXFE_Pos (5U) +#define USB_OTG_GINTSTS_NPTXFE_Msk (0x1UL << USB_OTG_GINTSTS_NPTXFE_Pos) /*!< 0x00000020 */ +#define USB_OTG_GINTSTS_NPTXFE USB_OTG_GINTSTS_NPTXFE_Msk /*!< Nonperiodic TxFIFO empty */ +#define USB_OTG_GINTSTS_GINAKEFF_Pos (6U) +#define USB_OTG_GINTSTS_GINAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_GINAKEFF_Pos) /*!< 0x00000040 */ +#define USB_OTG_GINTSTS_GINAKEFF USB_OTG_GINTSTS_GINAKEFF_Msk /*!< Global IN nonperiodic NAK effective */ +#define USB_OTG_GINTSTS_BOUTNAKEFF_Pos (7U) +#define USB_OTG_GINTSTS_BOUTNAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_BOUTNAKEFF_Pos) /*!< 0x00000080 */ +#define USB_OTG_GINTSTS_BOUTNAKEFF USB_OTG_GINTSTS_BOUTNAKEFF_Msk /*!< Global OUT NAK effective */ +#define USB_OTG_GINTSTS_ESUSP_Pos (10U) +#define USB_OTG_GINTSTS_ESUSP_Msk (0x1UL << USB_OTG_GINTSTS_ESUSP_Pos) /*!< 0x00000400 */ +#define USB_OTG_GINTSTS_ESUSP USB_OTG_GINTSTS_ESUSP_Msk /*!< Early suspend */ +#define USB_OTG_GINTSTS_USBSUSP_Pos (11U) +#define USB_OTG_GINTSTS_USBSUSP_Msk (0x1UL << USB_OTG_GINTSTS_USBSUSP_Pos) /*!< 0x00000800 */ +#define USB_OTG_GINTSTS_USBSUSP USB_OTG_GINTSTS_USBSUSP_Msk /*!< USB suspend */ +#define USB_OTG_GINTSTS_USBRST_Pos (12U) +#define USB_OTG_GINTSTS_USBRST_Msk (0x1UL << USB_OTG_GINTSTS_USBRST_Pos) /*!< 0x00001000 */ +#define USB_OTG_GINTSTS_USBRST USB_OTG_GINTSTS_USBRST_Msk /*!< USB reset */ +#define USB_OTG_GINTSTS_ENUMDNE_Pos (13U) +#define USB_OTG_GINTSTS_ENUMDNE_Msk (0x1UL << USB_OTG_GINTSTS_ENUMDNE_Pos) /*!< 0x00002000 */ +#define USB_OTG_GINTSTS_ENUMDNE USB_OTG_GINTSTS_ENUMDNE_Msk /*!< Enumeration done */ +#define USB_OTG_GINTSTS_ISOODRP_Pos (14U) +#define USB_OTG_GINTSTS_ISOODRP_Msk (0x1UL << USB_OTG_GINTSTS_ISOODRP_Pos) /*!< 0x00004000 */ +#define USB_OTG_GINTSTS_ISOODRP USB_OTG_GINTSTS_ISOODRP_Msk /*!< Isochronous OUT packet dropped interrupt */ +#define USB_OTG_GINTSTS_EOPF_Pos (15U) +#define USB_OTG_GINTSTS_EOPF_Msk (0x1UL << USB_OTG_GINTSTS_EOPF_Pos) /*!< 0x00008000 */ +#define USB_OTG_GINTSTS_EOPF USB_OTG_GINTSTS_EOPF_Msk /*!< End of periodic frame interrupt */ +#define USB_OTG_GINTSTS_IEPINT_Pos (18U) +#define USB_OTG_GINTSTS_IEPINT_Msk (0x1UL << USB_OTG_GINTSTS_IEPINT_Pos) /*!< 0x00040000 */ +#define USB_OTG_GINTSTS_IEPINT USB_OTG_GINTSTS_IEPINT_Msk /*!< IN endpoint interrupt */ +#define USB_OTG_GINTSTS_OEPINT_Pos (19U) +#define USB_OTG_GINTSTS_OEPINT_Msk (0x1UL << USB_OTG_GINTSTS_OEPINT_Pos) /*!< 0x00080000 */ +#define USB_OTG_GINTSTS_OEPINT USB_OTG_GINTSTS_OEPINT_Msk /*!< OUT endpoint interrupt */ +#define USB_OTG_GINTSTS_IISOIXFR_Pos (20U) +#define USB_OTG_GINTSTS_IISOIXFR_Msk (0x1UL << USB_OTG_GINTSTS_IISOIXFR_Pos) /*!< 0x00100000 */ +#define USB_OTG_GINTSTS_IISOIXFR USB_OTG_GINTSTS_IISOIXFR_Msk /*!< Incomplete isochronous IN transfer */ +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos (21U) +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos) /*!< 0x00200000 */ +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk /*!< Incomplete periodic transfer */ +#define USB_OTG_GINTSTS_DATAFSUSP_Pos (22U) +#define USB_OTG_GINTSTS_DATAFSUSP_Msk (0x1UL << USB_OTG_GINTSTS_DATAFSUSP_Pos) /*!< 0x00400000 */ +#define USB_OTG_GINTSTS_DATAFSUSP USB_OTG_GINTSTS_DATAFSUSP_Msk /*!< Data fetch suspended */ +#define USB_OTG_GINTSTS_HPRTINT_Pos (24U) +#define USB_OTG_GINTSTS_HPRTINT_Msk (0x1UL << USB_OTG_GINTSTS_HPRTINT_Pos) /*!< 0x01000000 */ +#define USB_OTG_GINTSTS_HPRTINT USB_OTG_GINTSTS_HPRTINT_Msk /*!< Host port interrupt */ +#define USB_OTG_GINTSTS_HCINT_Pos (25U) +#define USB_OTG_GINTSTS_HCINT_Msk (0x1UL << USB_OTG_GINTSTS_HCINT_Pos) /*!< 0x02000000 */ +#define USB_OTG_GINTSTS_HCINT USB_OTG_GINTSTS_HCINT_Msk /*!< Host channels interrupt */ +#define USB_OTG_GINTSTS_PTXFE_Pos (26U) +#define USB_OTG_GINTSTS_PTXFE_Msk (0x1UL << USB_OTG_GINTSTS_PTXFE_Pos) /*!< 0x04000000 */ +#define USB_OTG_GINTSTS_PTXFE USB_OTG_GINTSTS_PTXFE_Msk /*!< Periodic TxFIFO empty */ +#define USB_OTG_GINTSTS_CIDSCHG_Pos (28U) +#define USB_OTG_GINTSTS_CIDSCHG_Msk (0x1UL << USB_OTG_GINTSTS_CIDSCHG_Pos) /*!< 0x10000000 */ +#define USB_OTG_GINTSTS_CIDSCHG USB_OTG_GINTSTS_CIDSCHG_Msk /*!< Connector ID status change */ +#define USB_OTG_GINTSTS_DISCINT_Pos (29U) +#define USB_OTG_GINTSTS_DISCINT_Msk (0x1UL << USB_OTG_GINTSTS_DISCINT_Pos) /*!< 0x20000000 */ +#define USB_OTG_GINTSTS_DISCINT USB_OTG_GINTSTS_DISCINT_Msk /*!< Disconnect detected interrupt */ +#define USB_OTG_GINTSTS_SRQINT_Pos (30U) +#define USB_OTG_GINTSTS_SRQINT_Msk (0x1UL << USB_OTG_GINTSTS_SRQINT_Pos) /*!< 0x40000000 */ +#define USB_OTG_GINTSTS_SRQINT USB_OTG_GINTSTS_SRQINT_Msk /*!< Session request/new session detected interrupt */ +#define USB_OTG_GINTSTS_WKUINT_Pos (31U) +#define USB_OTG_GINTSTS_WKUINT_Msk (0x1UL << USB_OTG_GINTSTS_WKUINT_Pos) /*!< 0x80000000 */ +#define USB_OTG_GINTSTS_WKUINT USB_OTG_GINTSTS_WKUINT_Msk /*!< Resume/remote wakeup detected interrupt */ + +/******************** Bit definition for USB_OTG_GINTMSK register ********************/ +#define USB_OTG_GINTMSK_MMISM_Pos (1U) +#define USB_OTG_GINTMSK_MMISM_Msk (0x1UL << USB_OTG_GINTMSK_MMISM_Pos) /*!< 0x00000002 */ +#define USB_OTG_GINTMSK_MMISM USB_OTG_GINTMSK_MMISM_Msk /*!< Mode mismatch interrupt mask */ +#define USB_OTG_GINTMSK_OTGINT_Pos (2U) +#define USB_OTG_GINTMSK_OTGINT_Msk (0x1UL << USB_OTG_GINTMSK_OTGINT_Pos) /*!< 0x00000004 */ +#define USB_OTG_GINTMSK_OTGINT USB_OTG_GINTMSK_OTGINT_Msk /*!< OTG interrupt mask */ +#define USB_OTG_GINTMSK_SOFM_Pos (3U) +#define USB_OTG_GINTMSK_SOFM_Msk (0x1UL << USB_OTG_GINTMSK_SOFM_Pos) /*!< 0x00000008 */ +#define USB_OTG_GINTMSK_SOFM USB_OTG_GINTMSK_SOFM_Msk /*!< Start of frame mask */ +#define USB_OTG_GINTMSK_RXFLVLM_Pos (4U) +#define USB_OTG_GINTMSK_RXFLVLM_Msk (0x1UL << USB_OTG_GINTMSK_RXFLVLM_Pos) /*!< 0x00000010 */ +#define USB_OTG_GINTMSK_RXFLVLM USB_OTG_GINTMSK_RXFLVLM_Msk /*!< Receive FIFO nonempty mask */ +#define USB_OTG_GINTMSK_NPTXFEM_Pos (5U) +#define USB_OTG_GINTMSK_NPTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_NPTXFEM_Pos) /*!< 0x00000020 */ +#define USB_OTG_GINTMSK_NPTXFEM USB_OTG_GINTMSK_NPTXFEM_Msk /*!< Nonperiodic TxFIFO empty mask */ +#define USB_OTG_GINTMSK_GINAKEFFM_Pos (6U) +#define USB_OTG_GINTMSK_GINAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GINAKEFFM_Pos) /*!< 0x00000040 */ +#define USB_OTG_GINTMSK_GINAKEFFM USB_OTG_GINTMSK_GINAKEFFM_Msk /*!< Global nonperiodic IN NAK effective mask */ +#define USB_OTG_GINTMSK_GONAKEFFM_Pos (7U) +#define USB_OTG_GINTMSK_GONAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GONAKEFFM_Pos) /*!< 0x00000080 */ +#define USB_OTG_GINTMSK_GONAKEFFM USB_OTG_GINTMSK_GONAKEFFM_Msk /*!< Global OUT NAK effective mask */ +#define USB_OTG_GINTMSK_ESUSPM_Pos (10U) +#define USB_OTG_GINTMSK_ESUSPM_Msk (0x1UL << USB_OTG_GINTMSK_ESUSPM_Pos) /*!< 0x00000400 */ +#define USB_OTG_GINTMSK_ESUSPM USB_OTG_GINTMSK_ESUSPM_Msk /*!< Early suspend mask */ +#define USB_OTG_GINTMSK_USBSUSPM_Pos (11U) +#define USB_OTG_GINTMSK_USBSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_USBSUSPM_Pos) /*!< 0x00000800 */ +#define USB_OTG_GINTMSK_USBSUSPM USB_OTG_GINTMSK_USBSUSPM_Msk /*!< USB suspend mask */ +#define USB_OTG_GINTMSK_USBRST_Pos (12U) +#define USB_OTG_GINTMSK_USBRST_Msk (0x1UL << USB_OTG_GINTMSK_USBRST_Pos) /*!< 0x00001000 */ +#define USB_OTG_GINTMSK_USBRST USB_OTG_GINTMSK_USBRST_Msk /*!< USB reset mask */ +#define USB_OTG_GINTMSK_ENUMDNEM_Pos (13U) +#define USB_OTG_GINTMSK_ENUMDNEM_Msk (0x1UL << USB_OTG_GINTMSK_ENUMDNEM_Pos) /*!< 0x00002000 */ +#define USB_OTG_GINTMSK_ENUMDNEM USB_OTG_GINTMSK_ENUMDNEM_Msk /*!< Enumeration done mask */ +#define USB_OTG_GINTMSK_ISOODRPM_Pos (14U) +#define USB_OTG_GINTMSK_ISOODRPM_Msk (0x1UL << USB_OTG_GINTMSK_ISOODRPM_Pos) /*!< 0x00004000 */ +#define USB_OTG_GINTMSK_ISOODRPM USB_OTG_GINTMSK_ISOODRPM_Msk /*!< Isochronous OUT packet dropped interrupt mask */ +#define USB_OTG_GINTMSK_EOPFM_Pos (15U) +#define USB_OTG_GINTMSK_EOPFM_Msk (0x1UL << USB_OTG_GINTMSK_EOPFM_Pos) /*!< 0x00008000 */ +#define USB_OTG_GINTMSK_EOPFM USB_OTG_GINTMSK_EOPFM_Msk /*!< End of periodic frame interrupt mask */ +#define USB_OTG_GINTMSK_EPMISM_Pos (17U) +#define USB_OTG_GINTMSK_EPMISM_Msk (0x1UL << USB_OTG_GINTMSK_EPMISM_Pos) /*!< 0x00020000 */ +#define USB_OTG_GINTMSK_EPMISM USB_OTG_GINTMSK_EPMISM_Msk /*!< Endpoint mismatch interrupt mask */ +#define USB_OTG_GINTMSK_IEPINT_Pos (18U) +#define USB_OTG_GINTMSK_IEPINT_Msk (0x1UL << USB_OTG_GINTMSK_IEPINT_Pos) /*!< 0x00040000 */ +#define USB_OTG_GINTMSK_IEPINT USB_OTG_GINTMSK_IEPINT_Msk /*!< IN endpoints interrupt mask */ +#define USB_OTG_GINTMSK_OEPINT_Pos (19U) +#define USB_OTG_GINTMSK_OEPINT_Msk (0x1UL << USB_OTG_GINTMSK_OEPINT_Pos) /*!< 0x00080000 */ +#define USB_OTG_GINTMSK_OEPINT USB_OTG_GINTMSK_OEPINT_Msk /*!< OUT endpoints interrupt mask */ +#define USB_OTG_GINTMSK_IISOIXFRM_Pos (20U) +#define USB_OTG_GINTMSK_IISOIXFRM_Msk (0x1UL << USB_OTG_GINTMSK_IISOIXFRM_Pos) /*!< 0x00100000 */ +#define USB_OTG_GINTMSK_IISOIXFRM USB_OTG_GINTMSK_IISOIXFRM_Msk /*!< Incomplete isochronous IN transfer mask */ +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos (21U) +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos) /*!< 0x00200000 */ +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk /*!< Incomplete periodic transfer mask */ +#define USB_OTG_GINTMSK_FSUSPM_Pos (22U) +#define USB_OTG_GINTMSK_FSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_FSUSPM_Pos) /*!< 0x00400000 */ +#define USB_OTG_GINTMSK_FSUSPM USB_OTG_GINTMSK_FSUSPM_Msk /*!< Data fetch suspended mask */ +#define USB_OTG_GINTMSK_PRTIM_Pos (24U) +#define USB_OTG_GINTMSK_PRTIM_Msk (0x1UL << USB_OTG_GINTMSK_PRTIM_Pos) /*!< 0x01000000 */ +#define USB_OTG_GINTMSK_PRTIM USB_OTG_GINTMSK_PRTIM_Msk /*!< Host port interrupt mask */ +#define USB_OTG_GINTMSK_HCIM_Pos (25U) +#define USB_OTG_GINTMSK_HCIM_Msk (0x1UL << USB_OTG_GINTMSK_HCIM_Pos) /*!< 0x02000000 */ +#define USB_OTG_GINTMSK_HCIM USB_OTG_GINTMSK_HCIM_Msk /*!< Host channels interrupt mask */ +#define USB_OTG_GINTMSK_PTXFEM_Pos (26U) +#define USB_OTG_GINTMSK_PTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_PTXFEM_Pos) /*!< 0x04000000 */ +#define USB_OTG_GINTMSK_PTXFEM USB_OTG_GINTMSK_PTXFEM_Msk /*!< Periodic TxFIFO empty mask */ +#define USB_OTG_GINTMSK_CIDSCHGM_Pos (28U) +#define USB_OTG_GINTMSK_CIDSCHGM_Msk (0x1UL << USB_OTG_GINTMSK_CIDSCHGM_Pos) /*!< 0x10000000 */ +#define USB_OTG_GINTMSK_CIDSCHGM USB_OTG_GINTMSK_CIDSCHGM_Msk /*!< Connector ID status change mask */ +#define USB_OTG_GINTMSK_DISCINT_Pos (29U) +#define USB_OTG_GINTMSK_DISCINT_Msk (0x1UL << USB_OTG_GINTMSK_DISCINT_Pos) /*!< 0x20000000 */ +#define USB_OTG_GINTMSK_DISCINT USB_OTG_GINTMSK_DISCINT_Msk /*!< Disconnect detected interrupt mask */ +#define USB_OTG_GINTMSK_SRQIM_Pos (30U) +#define USB_OTG_GINTMSK_SRQIM_Msk (0x1UL << USB_OTG_GINTMSK_SRQIM_Pos) /*!< 0x40000000 */ +#define USB_OTG_GINTMSK_SRQIM USB_OTG_GINTMSK_SRQIM_Msk /*!< Session request/new session detected interrupt mask */ +#define USB_OTG_GINTMSK_WUIM_Pos (31U) +#define USB_OTG_GINTMSK_WUIM_Msk (0x1UL << USB_OTG_GINTMSK_WUIM_Pos) /*!< 0x80000000 */ +#define USB_OTG_GINTMSK_WUIM USB_OTG_GINTMSK_WUIM_Msk /*!< Resume/remote wakeup detected interrupt mask */ + +/******************** Bit definition for USB_OTG_DAINT register ********************/ +#define USB_OTG_DAINT_IEPINT_Pos (0U) +#define USB_OTG_DAINT_IEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_IEPINT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DAINT_IEPINT USB_OTG_DAINT_IEPINT_Msk /*!< IN endpoint interrupt bits */ +#define USB_OTG_DAINT_OEPINT_Pos (16U) +#define USB_OTG_DAINT_OEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_OEPINT_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DAINT_OEPINT USB_OTG_DAINT_OEPINT_Msk /*!< OUT endpoint interrupt bits */ + +/******************** Bit definition for USB_OTG_HAINTMSK register ********************/ +#define USB_OTG_HAINTMSK_HAINTM_Pos (0U) +#define USB_OTG_HAINTMSK_HAINTM_Msk (0xFFFFUL << USB_OTG_HAINTMSK_HAINTM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HAINTMSK_HAINTM USB_OTG_HAINTMSK_HAINTM_Msk /*!< Channel interrupt mask */ + +/******************** Bit definition for USB_OTG_GRXSTSP register ********************/ +#define USB_OTG_GRXSTSP_EPNUM_Pos (0U) +#define USB_OTG_GRXSTSP_EPNUM_Msk (0xFUL << USB_OTG_GRXSTSP_EPNUM_Pos) /*!< 0x0000000F */ +#define USB_OTG_GRXSTSP_EPNUM USB_OTG_GRXSTSP_EPNUM_Msk /*!< IN EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_BCNT_Pos (4U) +#define USB_OTG_GRXSTSP_BCNT_Msk (0x7FFUL << USB_OTG_GRXSTSP_BCNT_Pos) /*!< 0x00007FF0 */ +#define USB_OTG_GRXSTSP_BCNT USB_OTG_GRXSTSP_BCNT_Msk /*!< OUT EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_DPID_Pos (15U) +#define USB_OTG_GRXSTSP_DPID_Msk (0x3UL << USB_OTG_GRXSTSP_DPID_Pos) /*!< 0x00018000 */ +#define USB_OTG_GRXSTSP_DPID USB_OTG_GRXSTSP_DPID_Msk /*!< OUT EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_PKTSTS_Pos (17U) +#define USB_OTG_GRXSTSP_PKTSTS_Msk (0xFUL << USB_OTG_GRXSTSP_PKTSTS_Pos) /*!< 0x001E0000 */ +#define USB_OTG_GRXSTSP_PKTSTS USB_OTG_GRXSTSP_PKTSTS_Msk /*!< OUT EP interrupt mask bits */ + +/******************** Bit definition for USB_OTG_DAINTMSK register ********************/ +#define USB_OTG_DAINTMSK_IEPM_Pos (0U) +#define USB_OTG_DAINTMSK_IEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_IEPM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DAINTMSK_IEPM USB_OTG_DAINTMSK_IEPM_Msk /*!< IN EP interrupt mask bits */ +#define USB_OTG_DAINTMSK_OEPM_Pos (16U) +#define USB_OTG_DAINTMSK_OEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_OEPM_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DAINTMSK_OEPM USB_OTG_DAINTMSK_OEPM_Msk /*!< OUT EP interrupt mask bits */ + +/******************** Bit definition for USB_OTG_GRXFSIZ register ********************/ +#define USB_OTG_GRXFSIZ_RXFD_Pos (0U) +#define USB_OTG_GRXFSIZ_RXFD_Msk (0xFFFFUL << USB_OTG_GRXFSIZ_RXFD_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_GRXFSIZ_RXFD USB_OTG_GRXFSIZ_RXFD_Msk /*!< RxFIFO depth */ + +/******************** Bit definition for USB_OTG_DVBUSDIS register ********************/ +#define USB_OTG_DVBUSDIS_VBUSDT_Pos (0U) +#define USB_OTG_DVBUSDIS_VBUSDT_Msk (0xFFFFUL << USB_OTG_DVBUSDIS_VBUSDT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DVBUSDIS_VBUSDT USB_OTG_DVBUSDIS_VBUSDT_Msk /*!< Device VBUS discharge time */ + +/******************** Bit definition for OTG register ********************/ +#define USB_OTG_NPTXFSA_Pos (0U) +#define USB_OTG_NPTXFSA_Msk (0xFFFFUL << USB_OTG_NPTXFSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_NPTXFSA USB_OTG_NPTXFSA_Msk /*!< Nonperiodic transmit RAM start address */ +#define USB_OTG_NPTXFD_Pos (16U) +#define USB_OTG_NPTXFD_Msk (0xFFFFUL << USB_OTG_NPTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_NPTXFD USB_OTG_NPTXFD_Msk /*!< Nonperiodic TxFIFO depth */ +#define USB_OTG_TX0FSA_Pos (0U) +#define USB_OTG_TX0FSA_Msk (0xFFFFUL << USB_OTG_TX0FSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_TX0FSA USB_OTG_TX0FSA_Msk /*!< Endpoint 0 transmit RAM start address */ +#define USB_OTG_TX0FD_Pos (16U) +#define USB_OTG_TX0FD_Msk (0xFFFFUL << USB_OTG_TX0FD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_TX0FD USB_OTG_TX0FD_Msk /*!< Endpoint 0 TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DVBUSPULSE register ********************/ +#define USB_OTG_DVBUSPULSE_DVBUSP_Pos (0U) +#define USB_OTG_DVBUSPULSE_DVBUSP_Msk (0xFFFUL << USB_OTG_DVBUSPULSE_DVBUSP_Pos) /*!< 0x00000FFF */ +#define USB_OTG_DVBUSPULSE_DVBUSP USB_OTG_DVBUSPULSE_DVBUSP_Msk /*!< Device VBUS pulsing time */ + +/******************** Bit definition for USB_OTG_GNPTXSTS register ********************/ +#define USB_OTG_GNPTXSTS_NPTXFSAV_Pos (0U) +#define USB_OTG_GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << USB_OTG_GNPTXSTS_NPTXFSAV_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_GNPTXSTS_NPTXFSAV USB_OTG_GNPTXSTS_NPTXFSAV_Msk /*!< Nonperiodic TxFIFO space available */ + +#define USB_OTG_GNPTXSTS_NPTQXSAV_Pos (16U) +#define USB_OTG_GNPTXSTS_NPTQXSAV_Msk (0xFFUL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00FF0000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV USB_OTG_GNPTXSTS_NPTQXSAV_Msk /*!< Nonperiodic transmit request queue space available */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_0 (0x01UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00010000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_1 (0x02UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00020000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_2 (0x04UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00040000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_3 (0x08UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00080000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_4 (0x10UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00100000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_5 (0x20UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00200000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_6 (0x40UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00400000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_7 (0x80UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00800000 */ + +#define USB_OTG_GNPTXSTS_NPTXQTOP_Pos (24U) +#define USB_OTG_GNPTXSTS_NPTXQTOP_Msk (0x7FUL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x7F000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP USB_OTG_GNPTXSTS_NPTXQTOP_Msk /*!< Top of the nonperiodic transmit request queue */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_0 (0x01UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x01000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_1 (0x02UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x02000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_2 (0x04UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x04000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_3 (0x08UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x08000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_4 (0x10UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x10000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_5 (0x20UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x20000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_6 (0x40UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for USB_OTG_DTHRCTL register ********************/ +#define USB_OTG_DTHRCTL_NONISOTHREN_Pos (0U) +#define USB_OTG_DTHRCTL_NONISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_NONISOTHREN_Pos) /*!< 0x00000001 */ +#define USB_OTG_DTHRCTL_NONISOTHREN USB_OTG_DTHRCTL_NONISOTHREN_Msk /*!< Nonisochronous IN endpoints threshold enable */ +#define USB_OTG_DTHRCTL_ISOTHREN_Pos (1U) +#define USB_OTG_DTHRCTL_ISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_ISOTHREN_Pos) /*!< 0x00000002 */ +#define USB_OTG_DTHRCTL_ISOTHREN USB_OTG_DTHRCTL_ISOTHREN_Msk /*!< ISO IN endpoint threshold enable */ + +#define USB_OTG_DTHRCTL_TXTHRLEN_Pos (2U) +#define USB_OTG_DTHRCTL_TXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x000007FC */ +#define USB_OTG_DTHRCTL_TXTHRLEN USB_OTG_DTHRCTL_TXTHRLEN_Msk /*!< Transmit threshold length */ +#define USB_OTG_DTHRCTL_TXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000004 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000008 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000010 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000020 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000040 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000080 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000100 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000200 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000400 */ +#define USB_OTG_DTHRCTL_RXTHREN_Pos (16U) +#define USB_OTG_DTHRCTL_RXTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_RXTHREN_Pos) /*!< 0x00010000 */ +#define USB_OTG_DTHRCTL_RXTHREN USB_OTG_DTHRCTL_RXTHREN_Msk /*!< Receive threshold enable */ + +#define USB_OTG_DTHRCTL_RXTHRLEN_Pos (17U) +#define USB_OTG_DTHRCTL_RXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x03FE0000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN USB_OTG_DTHRCTL_RXTHRLEN_Msk /*!< Receive threshold length */ +#define USB_OTG_DTHRCTL_RXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00020000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00040000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00080000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00100000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00200000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00400000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00800000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x01000000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x02000000 */ +#define USB_OTG_DTHRCTL_ARPEN_Pos (27U) +#define USB_OTG_DTHRCTL_ARPEN_Msk (0x1UL << USB_OTG_DTHRCTL_ARPEN_Pos) /*!< 0x08000000 */ +#define USB_OTG_DTHRCTL_ARPEN USB_OTG_DTHRCTL_ARPEN_Msk /*!< Arbiter parking enable */ + +/******************** Bit definition for USB_OTG_DIEPEMPMSK register ********************/ +#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos (0U) +#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DIEPEMPMSK_INEPTXFEM USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk /*!< IN EP Tx FIFO empty interrupt mask bits */ + +/******************** Bit definition for USB_OTG_DEACHINT register ********************/ +#define USB_OTG_DEACHINT_IEP1INT_Pos (1U) +#define USB_OTG_DEACHINT_IEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_IEP1INT_Pos) /*!< 0x00000002 */ +#define USB_OTG_DEACHINT_IEP1INT USB_OTG_DEACHINT_IEP1INT_Msk /*!< IN endpoint 1interrupt bit */ +#define USB_OTG_DEACHINT_OEP1INT_Pos (17U) +#define USB_OTG_DEACHINT_OEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_OEP1INT_Pos) /*!< 0x00020000 */ +#define USB_OTG_DEACHINT_OEP1INT USB_OTG_DEACHINT_OEP1INT_Msk /*!< OUT endpoint 1 interrupt bit */ + +/******************** Bit definition for USB_OTG_GCCFG register ********************/ +#define USB_OTG_GCCFG_PWRDWN_Pos (16U) +#define USB_OTG_GCCFG_PWRDWN_Msk (0x1UL << USB_OTG_GCCFG_PWRDWN_Pos) /*!< 0x00010000 */ +#define USB_OTG_GCCFG_PWRDWN USB_OTG_GCCFG_PWRDWN_Msk /*!< Power down */ +#define USB_OTG_GCCFG_VBUSASEN_Pos (18U) +#define USB_OTG_GCCFG_VBUSASEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSASEN_Pos) /*!< 0x00040000 */ +#define USB_OTG_GCCFG_VBUSASEN USB_OTG_GCCFG_VBUSASEN_Msk /*!< Enable the VBUS sensing device */ +#define USB_OTG_GCCFG_VBUSBSEN_Pos (19U) +#define USB_OTG_GCCFG_VBUSBSEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSBSEN_Pos) /*!< 0x00080000 */ +#define USB_OTG_GCCFG_VBUSBSEN USB_OTG_GCCFG_VBUSBSEN_Msk /*!< Enable the VBUS sensing device */ +#define USB_OTG_GCCFG_SOFOUTEN_Pos (20U) +#define USB_OTG_GCCFG_SOFOUTEN_Msk (0x1UL << USB_OTG_GCCFG_SOFOUTEN_Pos) /*!< 0x00100000 */ +#define USB_OTG_GCCFG_SOFOUTEN USB_OTG_GCCFG_SOFOUTEN_Msk /*!< SOF output enable */ + +/******************** Bit definition for USB_OTG_DEACHINTMSK register ********************/ +#define USB_OTG_DEACHINTMSK_IEP1INTM_Pos (1U) +#define USB_OTG_DEACHINTMSK_IEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_IEP1INTM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DEACHINTMSK_IEP1INTM USB_OTG_DEACHINTMSK_IEP1INTM_Msk /*!< IN Endpoint 1 interrupt mask bit */ +#define USB_OTG_DEACHINTMSK_OEP1INTM_Pos (17U) +#define USB_OTG_DEACHINTMSK_OEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_OEP1INTM_Pos) /*!< 0x00020000 */ +#define USB_OTG_DEACHINTMSK_OEP1INTM USB_OTG_DEACHINTMSK_OEP1INTM_Msk /*!< OUT Endpoint 1 interrupt mask bit */ + +/******************** Bit definition for USB_OTG_CID register ********************/ +#define USB_OTG_CID_PRODUCT_ID_Pos (0U) +#define USB_OTG_CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << USB_OTG_CID_PRODUCT_ID_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_CID_PRODUCT_ID USB_OTG_CID_PRODUCT_ID_Msk /*!< Product ID field */ + +/******************** Bit definition for USB_OTG_DIEPEACHMSK1 register ********************/ +#define USB_OTG_DIEPEACHMSK1_XFRCM_Pos (0U) +#define USB_OTG_DIEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPEACHMSK1_XFRCM USB_OTG_DIEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_EPDM_Pos (1U) +#define USB_OTG_DIEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPEACHMSK1_EPDM USB_OTG_DIEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_TOM_Pos (3U) +#define USB_OTG_DIEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPEACHMSK1_TOM USB_OTG_DIEPEACHMSK1_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */ +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DIEPEACHMSK1_INEPNMM_Pos (5U) +#define USB_OTG_DIEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DIEPEACHMSK1_INEPNMM USB_OTG_DIEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DIEPEACHMSK1_INEPNEM_Pos (6U) +#define USB_OTG_DIEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPEACHMSK1_INEPNEM USB_OTG_DIEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DIEPEACHMSK1_TXFURM_Pos (8U) +#define USB_OTG_DIEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPEACHMSK1_TXFURM USB_OTG_DIEPEACHMSK1_TXFURM_Msk /*!< FIFO underrun mask */ +#define USB_OTG_DIEPEACHMSK1_BIM_Pos (9U) +#define USB_OTG_DIEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPEACHMSK1_BIM USB_OTG_DIEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_NAKM_Pos (13U) +#define USB_OTG_DIEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DIEPEACHMSK1_NAKM USB_OTG_DIEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */ + +/******************** Bit definition for USB_OTG_HPRT register ********************/ +#define USB_OTG_HPRT_PCSTS_Pos (0U) +#define USB_OTG_HPRT_PCSTS_Msk (0x1UL << USB_OTG_HPRT_PCSTS_Pos) /*!< 0x00000001 */ +#define USB_OTG_HPRT_PCSTS USB_OTG_HPRT_PCSTS_Msk /*!< Port connect status */ +#define USB_OTG_HPRT_PCDET_Pos (1U) +#define USB_OTG_HPRT_PCDET_Msk (0x1UL << USB_OTG_HPRT_PCDET_Pos) /*!< 0x00000002 */ +#define USB_OTG_HPRT_PCDET USB_OTG_HPRT_PCDET_Msk /*!< Port connect detected */ +#define USB_OTG_HPRT_PENA_Pos (2U) +#define USB_OTG_HPRT_PENA_Msk (0x1UL << USB_OTG_HPRT_PENA_Pos) /*!< 0x00000004 */ +#define USB_OTG_HPRT_PENA USB_OTG_HPRT_PENA_Msk /*!< Port enable */ +#define USB_OTG_HPRT_PENCHNG_Pos (3U) +#define USB_OTG_HPRT_PENCHNG_Msk (0x1UL << USB_OTG_HPRT_PENCHNG_Pos) /*!< 0x00000008 */ +#define USB_OTG_HPRT_PENCHNG USB_OTG_HPRT_PENCHNG_Msk /*!< Port enable/disable change */ +#define USB_OTG_HPRT_POCA_Pos (4U) +#define USB_OTG_HPRT_POCA_Msk (0x1UL << USB_OTG_HPRT_POCA_Pos) /*!< 0x00000010 */ +#define USB_OTG_HPRT_POCA USB_OTG_HPRT_POCA_Msk /*!< Port overcurrent active */ +#define USB_OTG_HPRT_POCCHNG_Pos (5U) +#define USB_OTG_HPRT_POCCHNG_Msk (0x1UL << USB_OTG_HPRT_POCCHNG_Pos) /*!< 0x00000020 */ +#define USB_OTG_HPRT_POCCHNG USB_OTG_HPRT_POCCHNG_Msk /*!< Port overcurrent change */ +#define USB_OTG_HPRT_PRES_Pos (6U) +#define USB_OTG_HPRT_PRES_Msk (0x1UL << USB_OTG_HPRT_PRES_Pos) /*!< 0x00000040 */ +#define USB_OTG_HPRT_PRES USB_OTG_HPRT_PRES_Msk /*!< Port resume */ +#define USB_OTG_HPRT_PSUSP_Pos (7U) +#define USB_OTG_HPRT_PSUSP_Msk (0x1UL << USB_OTG_HPRT_PSUSP_Pos) /*!< 0x00000080 */ +#define USB_OTG_HPRT_PSUSP USB_OTG_HPRT_PSUSP_Msk /*!< Port suspend */ +#define USB_OTG_HPRT_PRST_Pos (8U) +#define USB_OTG_HPRT_PRST_Msk (0x1UL << USB_OTG_HPRT_PRST_Pos) /*!< 0x00000100 */ +#define USB_OTG_HPRT_PRST USB_OTG_HPRT_PRST_Msk /*!< Port reset */ + +#define USB_OTG_HPRT_PLSTS_Pos (10U) +#define USB_OTG_HPRT_PLSTS_Msk (0x3UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000C00 */ +#define USB_OTG_HPRT_PLSTS USB_OTG_HPRT_PLSTS_Msk /*!< Port line status */ +#define USB_OTG_HPRT_PLSTS_0 (0x1UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000400 */ +#define USB_OTG_HPRT_PLSTS_1 (0x2UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000800 */ +#define USB_OTG_HPRT_PPWR_Pos (12U) +#define USB_OTG_HPRT_PPWR_Msk (0x1UL << USB_OTG_HPRT_PPWR_Pos) /*!< 0x00001000 */ +#define USB_OTG_HPRT_PPWR USB_OTG_HPRT_PPWR_Msk /*!< Port power */ + +#define USB_OTG_HPRT_PTCTL_Pos (13U) +#define USB_OTG_HPRT_PTCTL_Msk (0xFUL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x0001E000 */ +#define USB_OTG_HPRT_PTCTL USB_OTG_HPRT_PTCTL_Msk /*!< Port test control */ +#define USB_OTG_HPRT_PTCTL_0 (0x1UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00002000 */ +#define USB_OTG_HPRT_PTCTL_1 (0x2UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00004000 */ +#define USB_OTG_HPRT_PTCTL_2 (0x4UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00008000 */ +#define USB_OTG_HPRT_PTCTL_3 (0x8UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00010000 */ + +#define USB_OTG_HPRT_PSPD_Pos (17U) +#define USB_OTG_HPRT_PSPD_Msk (0x3UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00060000 */ +#define USB_OTG_HPRT_PSPD USB_OTG_HPRT_PSPD_Msk /*!< Port speed */ +#define USB_OTG_HPRT_PSPD_0 (0x1UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00020000 */ +#define USB_OTG_HPRT_PSPD_1 (0x2UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for USB_OTG_DOEPEACHMSK1 register ********************/ +#define USB_OTG_DOEPEACHMSK1_XFRCM_Pos (0U) +#define USB_OTG_DOEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DOEPEACHMSK1_XFRCM USB_OTG_DOEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_EPDM_Pos (1U) +#define USB_OTG_DOEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DOEPEACHMSK1_EPDM USB_OTG_DOEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_TOM_Pos (3U) +#define USB_OTG_DOEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DOEPEACHMSK1_TOM USB_OTG_DOEPEACHMSK1_TOM_Msk /*!< Timeout condition mask */ +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DOEPEACHMSK1_INEPNMM_Pos (5U) +#define USB_OTG_DOEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DOEPEACHMSK1_INEPNMM USB_OTG_DOEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DOEPEACHMSK1_INEPNEM_Pos (6U) +#define USB_OTG_DOEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DOEPEACHMSK1_INEPNEM USB_OTG_DOEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DOEPEACHMSK1_TXFURM_Pos (8U) +#define USB_OTG_DOEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DOEPEACHMSK1_TXFURM USB_OTG_DOEPEACHMSK1_TXFURM_Msk /*!< OUT packet error mask */ +#define USB_OTG_DOEPEACHMSK1_BIM_Pos (9U) +#define USB_OTG_DOEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DOEPEACHMSK1_BIM USB_OTG_DOEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_BERRM_Pos (12U) +#define USB_OTG_DOEPEACHMSK1_BERRM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BERRM_Pos) /*!< 0x00001000 */ +#define USB_OTG_DOEPEACHMSK1_BERRM USB_OTG_DOEPEACHMSK1_BERRM_Msk /*!< Bubble error interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_NAKM_Pos (13U) +#define USB_OTG_DOEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DOEPEACHMSK1_NAKM USB_OTG_DOEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_NYETM_Pos (14U) +#define USB_OTG_DOEPEACHMSK1_NYETM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NYETM_Pos) /*!< 0x00004000 */ +#define USB_OTG_DOEPEACHMSK1_NYETM USB_OTG_DOEPEACHMSK1_NYETM_Msk /*!< NYET interrupt mask */ + +/******************** Bit definition for USB_OTG_HPTXFSIZ register ********************/ +#define USB_OTG_HPTXFSIZ_PTXSA_Pos (0U) +#define USB_OTG_HPTXFSIZ_PTXSA_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HPTXFSIZ_PTXSA USB_OTG_HPTXFSIZ_PTXSA_Msk /*!< Host periodic TxFIFO start address */ +#define USB_OTG_HPTXFSIZ_PTXFD_Pos (16U) +#define USB_OTG_HPTXFSIZ_PTXFD_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_HPTXFSIZ_PTXFD USB_OTG_HPTXFSIZ_PTXFD_Msk /*!< Host periodic TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DIEPCTL register ********************/ +#define USB_OTG_DIEPCTL_MPSIZ_Pos (0U) +#define USB_OTG_DIEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DIEPCTL_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_DIEPCTL_MPSIZ USB_OTG_DIEPCTL_MPSIZ_Msk /*!< Maximum packet size */ +#define USB_OTG_DIEPCTL_USBAEP_Pos (15U) +#define USB_OTG_DIEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DIEPCTL_USBAEP_Pos) /*!< 0x00008000 */ +#define USB_OTG_DIEPCTL_USBAEP USB_OTG_DIEPCTL_USBAEP_Msk /*!< USB active endpoint */ +#define USB_OTG_DIEPCTL_EONUM_DPID_Pos (16U) +#define USB_OTG_DIEPCTL_EONUM_DPID_Msk (0x1UL << USB_OTG_DIEPCTL_EONUM_DPID_Pos) /*!< 0x00010000 */ +#define USB_OTG_DIEPCTL_EONUM_DPID USB_OTG_DIEPCTL_EONUM_DPID_Msk /*!< Even/odd frame */ +#define USB_OTG_DIEPCTL_NAKSTS_Pos (17U) +#define USB_OTG_DIEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DIEPCTL_NAKSTS_Pos) /*!< 0x00020000 */ +#define USB_OTG_DIEPCTL_NAKSTS USB_OTG_DIEPCTL_NAKSTS_Msk /*!< NAK status */ + +#define USB_OTG_DIEPCTL_EPTYP_Pos (18U) +#define USB_OTG_DIEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x000C0000 */ +#define USB_OTG_DIEPCTL_EPTYP USB_OTG_DIEPCTL_EPTYP_Msk /*!< Endpoint type */ +#define USB_OTG_DIEPCTL_EPTYP_0 (0x1UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00040000 */ +#define USB_OTG_DIEPCTL_EPTYP_1 (0x2UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00080000 */ +#define USB_OTG_DIEPCTL_STALL_Pos (21U) +#define USB_OTG_DIEPCTL_STALL_Msk (0x1UL << USB_OTG_DIEPCTL_STALL_Pos) /*!< 0x00200000 */ +#define USB_OTG_DIEPCTL_STALL USB_OTG_DIEPCTL_STALL_Msk /*!< STALL handshake */ + +#define USB_OTG_DIEPCTL_TXFNUM_Pos (22U) +#define USB_OTG_DIEPCTL_TXFNUM_Msk (0xFUL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x03C00000 */ +#define USB_OTG_DIEPCTL_TXFNUM USB_OTG_DIEPCTL_TXFNUM_Msk /*!< TxFIFO number */ +#define USB_OTG_DIEPCTL_TXFNUM_0 (0x1UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00400000 */ +#define USB_OTG_DIEPCTL_TXFNUM_1 (0x2UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00800000 */ +#define USB_OTG_DIEPCTL_TXFNUM_2 (0x4UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x01000000 */ +#define USB_OTG_DIEPCTL_TXFNUM_3 (0x8UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x02000000 */ +#define USB_OTG_DIEPCTL_CNAK_Pos (26U) +#define USB_OTG_DIEPCTL_CNAK_Msk (0x1UL << USB_OTG_DIEPCTL_CNAK_Pos) /*!< 0x04000000 */ +#define USB_OTG_DIEPCTL_CNAK USB_OTG_DIEPCTL_CNAK_Msk /*!< Clear NAK */ +#define USB_OTG_DIEPCTL_SNAK_Pos (27U) +#define USB_OTG_DIEPCTL_SNAK_Msk (0x1UL << USB_OTG_DIEPCTL_SNAK_Pos) /*!< 0x08000000 */ +#define USB_OTG_DIEPCTL_SNAK USB_OTG_DIEPCTL_SNAK_Msk /*!< Set NAK */ +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos (28U) +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */ +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */ +#define USB_OTG_DIEPCTL_SODDFRM_Pos (29U) +#define USB_OTG_DIEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SODDFRM_Pos) /*!< 0x20000000 */ +#define USB_OTG_DIEPCTL_SODDFRM USB_OTG_DIEPCTL_SODDFRM_Msk /*!< Set odd frame */ +#define USB_OTG_DIEPCTL_EPDIS_Pos (30U) +#define USB_OTG_DIEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DIEPCTL_EPDIS_Pos) /*!< 0x40000000 */ +#define USB_OTG_DIEPCTL_EPDIS USB_OTG_DIEPCTL_EPDIS_Msk /*!< Endpoint disable */ +#define USB_OTG_DIEPCTL_EPENA_Pos (31U) +#define USB_OTG_DIEPCTL_EPENA_Msk (0x1UL << USB_OTG_DIEPCTL_EPENA_Pos) /*!< 0x80000000 */ +#define USB_OTG_DIEPCTL_EPENA USB_OTG_DIEPCTL_EPENA_Msk /*!< Endpoint enable */ + +/******************** Bit definition for USB_OTG_HCCHAR register ********************/ +#define USB_OTG_HCCHAR_MPSIZ_Pos (0U) +#define USB_OTG_HCCHAR_MPSIZ_Msk (0x7FFUL << USB_OTG_HCCHAR_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_HCCHAR_MPSIZ USB_OTG_HCCHAR_MPSIZ_Msk /*!< Maximum packet size */ + +#define USB_OTG_HCCHAR_EPNUM_Pos (11U) +#define USB_OTG_HCCHAR_EPNUM_Msk (0xFUL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00007800 */ +#define USB_OTG_HCCHAR_EPNUM USB_OTG_HCCHAR_EPNUM_Msk /*!< Endpoint number */ +#define USB_OTG_HCCHAR_EPNUM_0 (0x1UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00000800 */ +#define USB_OTG_HCCHAR_EPNUM_1 (0x2UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00001000 */ +#define USB_OTG_HCCHAR_EPNUM_2 (0x4UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00002000 */ +#define USB_OTG_HCCHAR_EPNUM_3 (0x8UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00004000 */ +#define USB_OTG_HCCHAR_EPDIR_Pos (15U) +#define USB_OTG_HCCHAR_EPDIR_Msk (0x1UL << USB_OTG_HCCHAR_EPDIR_Pos) /*!< 0x00008000 */ +#define USB_OTG_HCCHAR_EPDIR USB_OTG_HCCHAR_EPDIR_Msk /*!< Endpoint direction */ +#define USB_OTG_HCCHAR_LSDEV_Pos (17U) +#define USB_OTG_HCCHAR_LSDEV_Msk (0x1UL << USB_OTG_HCCHAR_LSDEV_Pos) /*!< 0x00020000 */ +#define USB_OTG_HCCHAR_LSDEV USB_OTG_HCCHAR_LSDEV_Msk /*!< Low-speed device */ + +#define USB_OTG_HCCHAR_EPTYP_Pos (18U) +#define USB_OTG_HCCHAR_EPTYP_Msk (0x3UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x000C0000 */ +#define USB_OTG_HCCHAR_EPTYP USB_OTG_HCCHAR_EPTYP_Msk /*!< Endpoint type */ +#define USB_OTG_HCCHAR_EPTYP_0 (0x1UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00040000 */ +#define USB_OTG_HCCHAR_EPTYP_1 (0x2UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00080000 */ + +#define USB_OTG_HCCHAR_MC_Pos (20U) +#define USB_OTG_HCCHAR_MC_Msk (0x3UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00300000 */ +#define USB_OTG_HCCHAR_MC USB_OTG_HCCHAR_MC_Msk /*!< Multi Count (MC) / Error Count (EC) */ +#define USB_OTG_HCCHAR_MC_0 (0x1UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00100000 */ +#define USB_OTG_HCCHAR_MC_1 (0x2UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00200000 */ + +#define USB_OTG_HCCHAR_DAD_Pos (22U) +#define USB_OTG_HCCHAR_DAD_Msk (0x7FUL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x1FC00000 */ +#define USB_OTG_HCCHAR_DAD USB_OTG_HCCHAR_DAD_Msk /*!< Device address */ +#define USB_OTG_HCCHAR_DAD_0 (0x01UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00400000 */ +#define USB_OTG_HCCHAR_DAD_1 (0x02UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00800000 */ +#define USB_OTG_HCCHAR_DAD_2 (0x04UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x01000000 */ +#define USB_OTG_HCCHAR_DAD_3 (0x08UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x02000000 */ +#define USB_OTG_HCCHAR_DAD_4 (0x10UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x04000000 */ +#define USB_OTG_HCCHAR_DAD_5 (0x20UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x08000000 */ +#define USB_OTG_HCCHAR_DAD_6 (0x40UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x10000000 */ +#define USB_OTG_HCCHAR_ODDFRM_Pos (29U) +#define USB_OTG_HCCHAR_ODDFRM_Msk (0x1UL << USB_OTG_HCCHAR_ODDFRM_Pos) /*!< 0x20000000 */ +#define USB_OTG_HCCHAR_ODDFRM USB_OTG_HCCHAR_ODDFRM_Msk /*!< Odd frame */ +#define USB_OTG_HCCHAR_CHDIS_Pos (30U) +#define USB_OTG_HCCHAR_CHDIS_Msk (0x1UL << USB_OTG_HCCHAR_CHDIS_Pos) /*!< 0x40000000 */ +#define USB_OTG_HCCHAR_CHDIS USB_OTG_HCCHAR_CHDIS_Msk /*!< Channel disable */ +#define USB_OTG_HCCHAR_CHENA_Pos (31U) +#define USB_OTG_HCCHAR_CHENA_Msk (0x1UL << USB_OTG_HCCHAR_CHENA_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCCHAR_CHENA USB_OTG_HCCHAR_CHENA_Msk /*!< Channel enable */ + +/******************** Bit definition for USB_OTG_HCSPLT register ********************/ + +#define USB_OTG_HCSPLT_PRTADDR_Pos (0U) +#define USB_OTG_HCSPLT_PRTADDR_Msk (0x7FUL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x0000007F */ +#define USB_OTG_HCSPLT_PRTADDR USB_OTG_HCSPLT_PRTADDR_Msk /*!< Port address */ +#define USB_OTG_HCSPLT_PRTADDR_0 (0x01UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCSPLT_PRTADDR_1 (0x02UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCSPLT_PRTADDR_2 (0x04UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCSPLT_PRTADDR_3 (0x08UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCSPLT_PRTADDR_4 (0x10UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCSPLT_PRTADDR_5 (0x20UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCSPLT_PRTADDR_6 (0x40UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000040 */ + +#define USB_OTG_HCSPLT_HUBADDR_Pos (7U) +#define USB_OTG_HCSPLT_HUBADDR_Msk (0x7FUL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00003F80 */ +#define USB_OTG_HCSPLT_HUBADDR USB_OTG_HCSPLT_HUBADDR_Msk /*!< Hub address */ +#define USB_OTG_HCSPLT_HUBADDR_0 (0x01UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCSPLT_HUBADDR_1 (0x02UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCSPLT_HUBADDR_2 (0x04UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCSPLT_HUBADDR_3 (0x08UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCSPLT_HUBADDR_4 (0x10UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000800 */ +#define USB_OTG_HCSPLT_HUBADDR_5 (0x20UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00001000 */ +#define USB_OTG_HCSPLT_HUBADDR_6 (0x40UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00002000 */ + +#define USB_OTG_HCSPLT_XACTPOS_Pos (14U) +#define USB_OTG_HCSPLT_XACTPOS_Msk (0x3UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x0000C000 */ +#define USB_OTG_HCSPLT_XACTPOS USB_OTG_HCSPLT_XACTPOS_Msk /*!< XACTPOS */ +#define USB_OTG_HCSPLT_XACTPOS_0 (0x1UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00004000 */ +#define USB_OTG_HCSPLT_XACTPOS_1 (0x2UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00008000 */ +#define USB_OTG_HCSPLT_COMPLSPLT_Pos (16U) +#define USB_OTG_HCSPLT_COMPLSPLT_Msk (0x1UL << USB_OTG_HCSPLT_COMPLSPLT_Pos) /*!< 0x00010000 */ +#define USB_OTG_HCSPLT_COMPLSPLT USB_OTG_HCSPLT_COMPLSPLT_Msk /*!< Do complete split */ +#define USB_OTG_HCSPLT_SPLITEN_Pos (31U) +#define USB_OTG_HCSPLT_SPLITEN_Msk (0x1UL << USB_OTG_HCSPLT_SPLITEN_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCSPLT_SPLITEN USB_OTG_HCSPLT_SPLITEN_Msk /*!< Split enable */ + +/******************** Bit definition for USB_OTG_HCINT register ********************/ +#define USB_OTG_HCINT_XFRC_Pos (0U) +#define USB_OTG_HCINT_XFRC_Msk (0x1UL << USB_OTG_HCINT_XFRC_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCINT_XFRC USB_OTG_HCINT_XFRC_Msk /*!< Transfer completed */ +#define USB_OTG_HCINT_CHH_Pos (1U) +#define USB_OTG_HCINT_CHH_Msk (0x1UL << USB_OTG_HCINT_CHH_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCINT_CHH USB_OTG_HCINT_CHH_Msk /*!< Channel halted */ +#define USB_OTG_HCINT_AHBERR_Pos (2U) +#define USB_OTG_HCINT_AHBERR_Msk (0x1UL << USB_OTG_HCINT_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCINT_AHBERR USB_OTG_HCINT_AHBERR_Msk /*!< AHB error */ +#define USB_OTG_HCINT_STALL_Pos (3U) +#define USB_OTG_HCINT_STALL_Msk (0x1UL << USB_OTG_HCINT_STALL_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCINT_STALL USB_OTG_HCINT_STALL_Msk /*!< STALL response received interrupt */ +#define USB_OTG_HCINT_NAK_Pos (4U) +#define USB_OTG_HCINT_NAK_Msk (0x1UL << USB_OTG_HCINT_NAK_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCINT_NAK USB_OTG_HCINT_NAK_Msk /*!< NAK response received interrupt */ +#define USB_OTG_HCINT_ACK_Pos (5U) +#define USB_OTG_HCINT_ACK_Msk (0x1UL << USB_OTG_HCINT_ACK_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCINT_ACK USB_OTG_HCINT_ACK_Msk /*!< ACK response received/transmitted interrupt */ +#define USB_OTG_HCINT_NYET_Pos (6U) +#define USB_OTG_HCINT_NYET_Msk (0x1UL << USB_OTG_HCINT_NYET_Pos) /*!< 0x00000040 */ +#define USB_OTG_HCINT_NYET USB_OTG_HCINT_NYET_Msk /*!< Response received interrupt */ +#define USB_OTG_HCINT_TXERR_Pos (7U) +#define USB_OTG_HCINT_TXERR_Msk (0x1UL << USB_OTG_HCINT_TXERR_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCINT_TXERR USB_OTG_HCINT_TXERR_Msk /*!< Transaction error */ +#define USB_OTG_HCINT_BBERR_Pos (8U) +#define USB_OTG_HCINT_BBERR_Msk (0x1UL << USB_OTG_HCINT_BBERR_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCINT_BBERR USB_OTG_HCINT_BBERR_Msk /*!< Babble error */ +#define USB_OTG_HCINT_FRMOR_Pos (9U) +#define USB_OTG_HCINT_FRMOR_Msk (0x1UL << USB_OTG_HCINT_FRMOR_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCINT_FRMOR USB_OTG_HCINT_FRMOR_Msk /*!< Frame overrun */ +#define USB_OTG_HCINT_DTERR_Pos (10U) +#define USB_OTG_HCINT_DTERR_Msk (0x1UL << USB_OTG_HCINT_DTERR_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCINT_DTERR USB_OTG_HCINT_DTERR_Msk /*!< Data toggle error */ + +/******************** Bit definition for USB_OTG_DIEPINT register ********************/ +#define USB_OTG_DIEPINT_XFRC_Pos (0U) +#define USB_OTG_DIEPINT_XFRC_Msk (0x1UL << USB_OTG_DIEPINT_XFRC_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPINT_XFRC USB_OTG_DIEPINT_XFRC_Msk /*!< Transfer completed interrupt */ +#define USB_OTG_DIEPINT_EPDISD_Pos (1U) +#define USB_OTG_DIEPINT_EPDISD_Msk (0x1UL << USB_OTG_DIEPINT_EPDISD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPINT_EPDISD USB_OTG_DIEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */ +#define USB_OTG_DIEPINT_AHBERR_Pos (2U) +#define USB_OTG_DIEPINT_AHBERR_Msk (0x1UL << USB_OTG_DIEPINT_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_DIEPINT_AHBERR USB_OTG_DIEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an IN transaction */ +#define USB_OTG_DIEPINT_TOC_Pos (3U) +#define USB_OTG_DIEPINT_TOC_Msk (0x1UL << USB_OTG_DIEPINT_TOC_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPINT_TOC USB_OTG_DIEPINT_TOC_Msk /*!< Timeout condition */ +#define USB_OTG_DIEPINT_ITTXFE_Pos (4U) +#define USB_OTG_DIEPINT_ITTXFE_Msk (0x1UL << USB_OTG_DIEPINT_ITTXFE_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPINT_ITTXFE USB_OTG_DIEPINT_ITTXFE_Msk /*!< IN token received when TxFIFO is empty */ +#define USB_OTG_DIEPINT_INEPNM_Pos (5U) +#define USB_OTG_DIEPINT_INEPNM_Msk (0x1UL << USB_OTG_DIEPINT_INEPNM_Pos) /*!< 0x00000004 */ +#define USB_OTG_DIEPINT_INEPNM USB_OTG_DIEPINT_INEPNM_Msk /*!< IN token received with EP mismatch */ +#define USB_OTG_DIEPINT_INEPNE_Pos (6U) +#define USB_OTG_DIEPINT_INEPNE_Msk (0x1UL << USB_OTG_DIEPINT_INEPNE_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPINT_INEPNE USB_OTG_DIEPINT_INEPNE_Msk /*!< IN endpoint NAK effective */ +#define USB_OTG_DIEPINT_TXFE_Pos (7U) +#define USB_OTG_DIEPINT_TXFE_Msk (0x1UL << USB_OTG_DIEPINT_TXFE_Pos) /*!< 0x00000080 */ +#define USB_OTG_DIEPINT_TXFE USB_OTG_DIEPINT_TXFE_Msk /*!< Transmit FIFO empty */ +#define USB_OTG_DIEPINT_TXFIFOUDRN_Pos (8U) +#define USB_OTG_DIEPINT_TXFIFOUDRN_Msk (0x1UL << USB_OTG_DIEPINT_TXFIFOUDRN_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPINT_TXFIFOUDRN USB_OTG_DIEPINT_TXFIFOUDRN_Msk /*!< Transmit Fifo Underrun */ +#define USB_OTG_DIEPINT_BNA_Pos (9U) +#define USB_OTG_DIEPINT_BNA_Msk (0x1UL << USB_OTG_DIEPINT_BNA_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPINT_BNA USB_OTG_DIEPINT_BNA_Msk /*!< Buffer not available interrupt */ +#define USB_OTG_DIEPINT_PKTDRPSTS_Pos (11U) +#define USB_OTG_DIEPINT_PKTDRPSTS_Msk (0x1UL << USB_OTG_DIEPINT_PKTDRPSTS_Pos) /*!< 0x00000800 */ +#define USB_OTG_DIEPINT_PKTDRPSTS USB_OTG_DIEPINT_PKTDRPSTS_Msk /*!< Packet dropped status */ +#define USB_OTG_DIEPINT_BERR_Pos (12U) +#define USB_OTG_DIEPINT_BERR_Msk (0x1UL << USB_OTG_DIEPINT_BERR_Pos) /*!< 0x00001000 */ +#define USB_OTG_DIEPINT_BERR USB_OTG_DIEPINT_BERR_Msk /*!< Babble error interrupt */ +#define USB_OTG_DIEPINT_NAK_Pos (13U) +#define USB_OTG_DIEPINT_NAK_Msk (0x1UL << USB_OTG_DIEPINT_NAK_Pos) /*!< 0x00002000 */ +#define USB_OTG_DIEPINT_NAK USB_OTG_DIEPINT_NAK_Msk /*!< NAK interrupt */ + +/******************** Bit definition for USB_OTG_HCINTMSK register ********************/ +#define USB_OTG_HCINTMSK_XFRCM_Pos (0U) +#define USB_OTG_HCINTMSK_XFRCM_Msk (0x1UL << USB_OTG_HCINTMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCINTMSK_XFRCM USB_OTG_HCINTMSK_XFRCM_Msk /*!< Transfer completed mask */ +#define USB_OTG_HCINTMSK_CHHM_Pos (1U) +#define USB_OTG_HCINTMSK_CHHM_Msk (0x1UL << USB_OTG_HCINTMSK_CHHM_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCINTMSK_CHHM USB_OTG_HCINTMSK_CHHM_Msk /*!< Channel halted mask */ +#define USB_OTG_HCINTMSK_AHBERR_Pos (2U) +#define USB_OTG_HCINTMSK_AHBERR_Msk (0x1UL << USB_OTG_HCINTMSK_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCINTMSK_AHBERR USB_OTG_HCINTMSK_AHBERR_Msk /*!< AHB error */ +#define USB_OTG_HCINTMSK_STALLM_Pos (3U) +#define USB_OTG_HCINTMSK_STALLM_Msk (0x1UL << USB_OTG_HCINTMSK_STALLM_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCINTMSK_STALLM USB_OTG_HCINTMSK_STALLM_Msk /*!< STALL response received interrupt mask */ +#define USB_OTG_HCINTMSK_NAKM_Pos (4U) +#define USB_OTG_HCINTMSK_NAKM_Msk (0x1UL << USB_OTG_HCINTMSK_NAKM_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCINTMSK_NAKM USB_OTG_HCINTMSK_NAKM_Msk /*!< NAK response received interrupt mask */ +#define USB_OTG_HCINTMSK_ACKM_Pos (5U) +#define USB_OTG_HCINTMSK_ACKM_Msk (0x1UL << USB_OTG_HCINTMSK_ACKM_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCINTMSK_ACKM USB_OTG_HCINTMSK_ACKM_Msk /*!< ACK response received/transmitted interrupt mask */ +#define USB_OTG_HCINTMSK_NYET_Pos (6U) +#define USB_OTG_HCINTMSK_NYET_Msk (0x1UL << USB_OTG_HCINTMSK_NYET_Pos) /*!< 0x00000040 */ +#define USB_OTG_HCINTMSK_NYET USB_OTG_HCINTMSK_NYET_Msk /*!< response received interrupt mask */ +#define USB_OTG_HCINTMSK_TXERRM_Pos (7U) +#define USB_OTG_HCINTMSK_TXERRM_Msk (0x1UL << USB_OTG_HCINTMSK_TXERRM_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCINTMSK_TXERRM USB_OTG_HCINTMSK_TXERRM_Msk /*!< Transaction error mask */ +#define USB_OTG_HCINTMSK_BBERRM_Pos (8U) +#define USB_OTG_HCINTMSK_BBERRM_Msk (0x1UL << USB_OTG_HCINTMSK_BBERRM_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCINTMSK_BBERRM USB_OTG_HCINTMSK_BBERRM_Msk /*!< Babble error mask */ +#define USB_OTG_HCINTMSK_FRMORM_Pos (9U) +#define USB_OTG_HCINTMSK_FRMORM_Msk (0x1UL << USB_OTG_HCINTMSK_FRMORM_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCINTMSK_FRMORM USB_OTG_HCINTMSK_FRMORM_Msk /*!< Frame overrun mask */ +#define USB_OTG_HCINTMSK_DTERRM_Pos (10U) +#define USB_OTG_HCINTMSK_DTERRM_Msk (0x1UL << USB_OTG_HCINTMSK_DTERRM_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCINTMSK_DTERRM USB_OTG_HCINTMSK_DTERRM_Msk /*!< Data toggle error mask */ + +/******************** Bit definition for USB_OTG_DIEPTSIZ register ********************/ + +#define USB_OTG_DIEPTSIZ_XFRSIZ_Pos (0U) +#define USB_OTG_DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */ +#define USB_OTG_DIEPTSIZ_XFRSIZ USB_OTG_DIEPTSIZ_XFRSIZ_Msk /*!< Transfer size */ +#define USB_OTG_DIEPTSIZ_PKTCNT_Pos (19U) +#define USB_OTG_DIEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DIEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */ +#define USB_OTG_DIEPTSIZ_PKTCNT USB_OTG_DIEPTSIZ_PKTCNT_Msk /*!< Packet count */ +#define USB_OTG_DIEPTSIZ_MULCNT_Pos (29U) +#define USB_OTG_DIEPTSIZ_MULCNT_Msk (0x3UL << USB_OTG_DIEPTSIZ_MULCNT_Pos) /*!< 0x60000000 */ +#define USB_OTG_DIEPTSIZ_MULCNT USB_OTG_DIEPTSIZ_MULCNT_Msk /*!< Packet count */ +/******************** Bit definition for USB_OTG_HCTSIZ register ********************/ +#define USB_OTG_HCTSIZ_XFRSIZ_Pos (0U) +#define USB_OTG_HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_HCTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */ +#define USB_OTG_HCTSIZ_XFRSIZ USB_OTG_HCTSIZ_XFRSIZ_Msk /*!< Transfer size */ +#define USB_OTG_HCTSIZ_PKTCNT_Pos (19U) +#define USB_OTG_HCTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_HCTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */ +#define USB_OTG_HCTSIZ_PKTCNT USB_OTG_HCTSIZ_PKTCNT_Msk /*!< Packet count */ +#define USB_OTG_HCTSIZ_DOPING_Pos (31U) +#define USB_OTG_HCTSIZ_DOPING_Msk (0x1UL << USB_OTG_HCTSIZ_DOPING_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCTSIZ_DOPING USB_OTG_HCTSIZ_DOPING_Msk /*!< Do PING */ +#define USB_OTG_HCTSIZ_DPID_Pos (29U) +#define USB_OTG_HCTSIZ_DPID_Msk (0x3UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x60000000 */ +#define USB_OTG_HCTSIZ_DPID USB_OTG_HCTSIZ_DPID_Msk /*!< Data PID */ +#define USB_OTG_HCTSIZ_DPID_0 (0x1UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x20000000 */ +#define USB_OTG_HCTSIZ_DPID_1 (0x2UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for USB_OTG_DIEPDMA register ********************/ +#define USB_OTG_DIEPDMA_DMAADDR_Pos (0U) +#define USB_OTG_DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_DIEPDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_DIEPDMA_DMAADDR USB_OTG_DIEPDMA_DMAADDR_Msk /*!< DMA address */ + +/******************** Bit definition for USB_OTG_HCDMA register ********************/ +#define USB_OTG_HCDMA_DMAADDR_Pos (0U) +#define USB_OTG_HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_HCDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_HCDMA_DMAADDR USB_OTG_HCDMA_DMAADDR_Msk /*!< DMA address */ + +/******************** Bit definition for USB_OTG_DTXFSTS register ********************/ +#define USB_OTG_DTXFSTS_INEPTFSAV_Pos (0U) +#define USB_OTG_DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << USB_OTG_DTXFSTS_INEPTFSAV_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DTXFSTS_INEPTFSAV USB_OTG_DTXFSTS_INEPTFSAV_Msk /*!< IN endpoint TxFIFO space available */ + +/******************** Bit definition for USB_OTG_DIEPTXF register ********************/ +#define USB_OTG_DIEPTXF_INEPTXSA_Pos (0U) +#define USB_OTG_DIEPTXF_INEPTXSA_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DIEPTXF_INEPTXSA USB_OTG_DIEPTXF_INEPTXSA_Msk /*!< IN endpoint FIFOx transmit RAM start address */ +#define USB_OTG_DIEPTXF_INEPTXFD_Pos (16U) +#define USB_OTG_DIEPTXF_INEPTXFD_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DIEPTXF_INEPTXFD USB_OTG_DIEPTXF_INEPTXFD_Msk /*!< IN endpoint TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DOEPCTL register ********************/ + +#define USB_OTG_DOEPCTL_MPSIZ_Pos (0U) +#define USB_OTG_DOEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DOEPCTL_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_DOEPCTL_MPSIZ USB_OTG_DOEPCTL_MPSIZ_Msk /*!< Maximum packet size */ /*!ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); + } + + //------------- Clear All Registers -------------// + dcd_reg->ENDPTNAK = dcd_reg->ENDPTNAK; + dcd_reg->ENDPTNAKEN = 0; + dcd_reg->USBSTS = dcd_reg->USBSTS; + dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT; + dcd_reg->ENDPTCOMPLETE = dcd_reg->ENDPTCOMPLETE; + + while (dcd_reg->ENDPTPRIME) {} + dcd_reg->ENDPTFLUSH = 0xFFFFFFFF; + while (dcd_reg->ENDPTFLUSH) {} + + // read reset bit in portsc + + //------------- Queue Head & Queue TD -------------// + tu_memclr(&_dcd_data, sizeof(dcd_data_t)); + + //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// + _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1; + _dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; + _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID; + + _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only +} + +void dcd_init(uint8_t rhport) +{ + tu_memclr(&_dcd_data, sizeof(dcd_data_t)); + + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + // Reset controller + dcd_reg->USBCMD |= USBCMD_RESET; + while( dcd_reg->USBCMD & USBCMD_RESET ) {} + + // Set mode to device, must be set immediately after reset + dcd_reg->USBMODE = USBMODE_CM_DEVICE; + dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION; + +#if !TUD_OPT_HIGH_SPEED + dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; +#endif + + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + + dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment + dcd_reg->USBSTS = dcd_reg->USBSTS; + dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND; + + dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect +} + +void dcd_int_enable(uint8_t rhport) +{ + CI_DCD_INT_ENABLE(rhport); +} + +void dcd_int_disable(uint8_t rhport) +{ + CI_DCD_INT_DISABLE(rhport); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + // Response with status first before changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME; +} + +void dcd_connect(uint8_t rhport) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->USBCMD |= USBCMD_RUN_STOP; +} + +void dcd_disconnect(uint8_t rhport) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->USBCMD &= ~USBCMD_RUN_STOP; +} + +//--------------------------------------------------------------------+ +// HELPER +//--------------------------------------------------------------------+ + +static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) +{ + // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the + // address to 32-byte boundaries. Buffer must be word aligned + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31); + + tu_memclr(p_qtd, sizeof(dcd_qtd_t)); + + p_qtd->next = QTD_NEXT_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + p_qtd->int_on_complete = true; + + if (data_ptr != NULL) + { + p_qtd->buffer[0] = (uint32_t) data_ptr; + + uint32_t const bufend = p_qtd->buffer[0] + total_bytes; + for(uint8_t i=1; i<5; i++) + { + uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096; + if ( bufend <= next_page ) break; + + p_qtd->buffer[i] = next_page; + + // TODO page[1] FRAME_N for ISO transfer + } + } +} + +//--------------------------------------------------------------------+ +// DCD Endpoint Port +//--------------------------------------------------------------------+ +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0); + + // flush to abort any primed buffer + dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0)); +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // data toggle also need to be reset + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << ( dir ? 16 : 0 ); + dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << ( dir ? 16 : 0)); +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +{ + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + + // Must not exceed max endpoint number + TU_ASSERT( epnum < _ci_controller[rhport].ep_count ); + + //------------- Prepare Queue Head -------------// + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; + tu_memclr(p_qhd, sizeof(dcd_qhd_t)); + + p_qhd->zero_length_termination = 1; + p_qhd->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); + if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + { + p_qhd->iso_mult = 1; + } + + p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; + + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + + // Enable EP Control + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; + + if ( dir == TUSB_DIR_OUT ) + { + dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl; + }else + { + dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16); + } + + return true; +} + +void dcd_edpt_close_all (uint8_t rhport) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + // Disable all non-control endpoints + for( uint8_t epnum=1; epnum < _ci_controller[rhport].ep_count; epnum++) + { + _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; + _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1; + + dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16); + dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); + } +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + + // Flush EP + uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); + dcd_reg->ENDPTFLUSH = flush_mask; + while(dcd_reg->ENDPTFLUSH & flush_mask); + + // Clear EP enable + dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0)); +} + +static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir]; + + p_qhd->qtd_overlay.halted = false; // clear any previous error + p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd + + // flush cache + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + + if ( epnum == 0 ) + { + // follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism + // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out + while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {} + } + + // start transfer + dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0)); +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir]; + + // Prepare qtd + qtd_init(p_qtd, buffer, total_bytes); + + // Start qhd transfer + p_qhd->ff = NULL; + qhd_start_xfer(rhport, epnum, dir); + + return true; +} + +// fifo has to be aligned to 4k boundary +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir]; + + tu_fifo_buffer_info_t fifo_info; + + if (dir) + { + tu_fifo_get_read_info(ff, &fifo_info); + } else + { + tu_fifo_get_write_info(ff, &fifo_info); + } + + if ( fifo_info.len_lin >= total_bytes ) + { + // Linear length is enough for this transfer + qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes); + } + else + { + // linear part is not enough + + // prepare TD up to linear length + qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin); + + if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) ) + { + // If buffer is aligned to 4K & buffer size is multiple of 4K + // We can make use of buffer page array to also combine the linear + wrapped length + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + + for(uint8_t i = 1, page = 0; i < 5; i++) + { + // pick up buffer array where linear ends + if (p_qtd->buffer[i] == 0) + { + p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page; + page++; + } + } + + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31); + } + else + { + // TODO we may need to carry the wrapped length after the linear part complete + // for now only transfer up to linear part + } + } + + // Start qhd transfer + p_qhd->ff = ff; + qhd_start_xfer(rhport, epnum, dir); + + return true; +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ + +static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir) +{ + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir]; + + uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED : + ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; + + if ( result != XFER_RESULT_SUCCESS ) + { + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + // flush to abort error buffer + dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0)); + } + + uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes; + + if (p_qhd->ff) + { + if (dir == TUSB_DIR_IN) + { + tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes); + } else + { + tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes); + } + } + + // only number of bytes in the IOC qtd + dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true); +} + +void dcd_int_handler(uint8_t rhport) +{ + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + + uint32_t const int_enable = dcd_reg->USBINTR; + uint32_t const int_status = dcd_reg->USBSTS & int_enable; + dcd_reg->USBSTS = int_status; // Acknowledge handled interrupt + + // disabled interrupt sources + if (int_status == 0) return; + + // Set if the port controller enters the full or high-speed operational state. + // either from Bus Reset or Suspended state + if (int_status & INTR_PORT_CHANGE) + { + // TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1); + + // Reset interrupt is not enabled, we manually check if Port Change is due + // to connection / disconnection + if ( dcd_reg->USBSTS & INTR_RESET ) + { + dcd_reg->USBSTS = INTR_RESET; + + if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS) + { + uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS; + bus_reset(rhport); + dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true); + }else + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + } + else + { + // Triggered by resuming from suspended state + if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) ) + { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + } + } + + if (int_status & INTR_SUSPEND) + { + // TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1); + + if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND) + { + // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. + // Skip suspend event if we are not addressed + if ((dcd_reg->DEVICEADDR >> 25) & 0x0f) + { + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + } + } + + if (int_status & INTR_USB) + { + // Make sure we read the latest version of _dcd_data. + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + + uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE; + dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge + + if (dcd_reg->ENDPTSETUPSTAT) + { + //------------- Set up Received -------------// + // 23.10.10.2 Operational model for setup transfers + dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT; + + dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true); + } + + // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set + // nothing to do, we will submit xfer as error to usbd + // if (int_status & INTR_ERROR) { } + + if ( edpt_complete ) + { + for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++) + { + if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT); + if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN); + } + } + } + + if (int_status & INTR_SOF) + { + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } +} + +#endif diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c new file mode 100644 index 000000000..3d028bf32 --- /dev/null +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -0,0 +1,93 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +// Chipidea Highspeed USB IP implement EHCI for host functionality + +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/tusb_common.h" +#include "portable/ehci/ehci_api.h" +#include "ci_hs_type.h" + +#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #include "ci_hs_imxrt.h" +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + #include "ci_hs_lpc18_43.h" +#else + #error "Unsupported MCUs" +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +bool hcd_init(uint8_t rhport) +{ + ci_hs_regs_t* hcd_reg = CI_HS_REG(rhport); + + // Reset controller + hcd_reg->USBCMD |= USBCMD_RESET; + while( hcd_reg->USBCMD & USBCMD_RESET ) {} + + // Set mode to device, must be set immediately after reset +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX + // LPC18XX/43XX need to set VBUS Power Select to HIGH + // RHPORT1 is fullspeed only (need external PHY for Highspeed) + hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; + if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; +#else + hcd_reg->USBMODE = USBMODE_CM_HOST; +#endif + + // FIXME force full speed, still have issue with Highspeed enumeration + hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + + return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD); +} + +void hcd_int_enable(uint8_t rhport) +{ + CI_HCD_INT_ENABLE(rhport); +} + +void hcd_int_disable(uint8_t rhport) +{ + CI_HCD_INT_DISABLE(rhport); +} + +#endif diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 5fcf3bc5b..311119747 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -60,10 +60,17 @@ #define EP_MAX 4 +// Node functional states #define NFSR_NODE_RESET 0 #define NFSR_NODE_RESUME 1 #define NFSR_NODE_OPERATIONAL 2 #define NFSR_NODE_SUSPEND 3 +// Those two following states are added to allow going out of sleep mode +// using frame interrupt. On remove wakeup RESUME state must be kept for +// at least 1ms. It is accomplished by using FRAME interrupt that goes +// through those two fake states before entering OPERATIONAL state. +#define NFSR_NODE_WAKING (0x10 | (NFSR_NODE_RESUME)) +#define NFSR_NODE_WAKING2 (0x20 | (NFSR_NODE_RESUME)) static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8]; @@ -133,7 +140,7 @@ typedef struct __IOM uint32_t USB_RXC2_REG; /*!< (@ 0x000000DC) Receive Command Register 2 */ __IOM uint32_t USB_RXC3_REG; /*!< (@ 0x000000FC) Receive Command Register 3 */ }; -} EPx_REGS; +} volatile EPx_REGS; #define EP_REGS(first_ep_reg) (EPx_REGS*)(&USB->first_ep_reg) @@ -193,8 +200,14 @@ typedef struct #define REG_CLR_BIT(reg, field) USB->reg &= ~USB_ ## reg ## _ ## field ## _Msk #define REG_SET_VAL(reg, field, val) USB->reg = (USB->reg & ~USB_ ## reg ## _ ## field ## _Msk) | (val << USB_ ## reg ## _ ## field ## _Pos) +static EPx_REGS * const ep_regs[EP_MAX] = { + EP_REGS(USB_EPC0_REG), + EP_REGS(USB_EPC1_REG), + EP_REGS(USB_EPC3_REG), + EP_REGS(USB_EPC5_REG), +}; + typedef struct { - EPx_REGS * regs; uint8_t * buffer; // Total length of current transfer uint16_t total_len; @@ -217,22 +230,24 @@ typedef struct { static struct { bool vbus_present; - bool in_reset; + bool init_called; + uint8_t nfsr; xfer_ctl_t xfer_status[EP_MAX][2]; // Endpoints that use DMA, one for each direction uint8_t dma_ep[2]; } _dcd = { .vbus_present = false, - .xfer_status = - { - { { .regs = EP_REGS(USB_EPC0_REG) }, { .regs = EP_REGS(USB_EPC0_REG) } }, - { { .regs = EP_REGS(USB_EPC1_REG) }, { .regs = EP_REGS(USB_EPC1_REG) } }, - { { .regs = EP_REGS(USB_EPC3_REG) }, { .regs = EP_REGS(USB_EPC3_REG) } }, - { { .regs = EP_REGS(USB_EPC5_REG) }, { .regs = EP_REGS(USB_EPC5_REG) } }, - } + .init_called = false, }; +// Converts xfer pointer to epnum (0,1,2,3) regardless of xfer direction +#define XFER_EPNUM(xfer) ((xfer - &_dcd.xfer_status[0][0]) >> 1) +// Converts xfer pinter to EPx_REGS pointer (returns same pointer for IN and OUT with same endpoint number) +#define XFER_REGS(xfer) ep_regs[XFER_EPNUM(xfer)] +// Converts epnum (0,1,2,3) to EPx_REGS pointer +#define EPNUM_REGS(epnum) ep_regs[epnum] + // Two endpoint 0 descriptor definition for unified dcd_edpt_open() static const tusb_desc_endpoint_t ep0OUT_desc = { @@ -241,7 +256,7 @@ static const tusb_desc_endpoint_t ep0OUT_desc = .bEndpointAddress = 0x00, .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, .bInterval = 0 }; @@ -252,18 +267,27 @@ static const tusb_desc_endpoint_t ep0IN_desc = .bEndpointAddress = 0x80, .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, .bInterval = 0 }; #define XFER_CTL_BASE(_ep, _dir) &_dcd.xfer_status[_ep][_dir] +static void set_nfsr(uint8_t val) +{ + _dcd.nfsr = val; + // Write only lower 2 bits to register, higher bits are used + // to count down till OPERATIONAL state can be entered when + // remote wakeup activated. + USB->USB_NFSR_REG = val & 3; +} + static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; uint8_t const *src; - EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); + EPx_REGS *regs = EPNUM_REGS(epnum); src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; @@ -291,7 +315,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) } else { - xfer->regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; + regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos)); // Whole packet already in fifo, no need to refill it later. Mark last. regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk; @@ -332,30 +356,31 @@ static void start_rx_packet(xfer_ctl_t *xfer) uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint16_t remaining = xfer->total_len - xfer->transferred; uint16_t size = tu_min16(remaining, xfer->max_packet_size); + EPx_REGS *regs = XFER_REGS(xfer); xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { if (try_allocate_dma(epnum, TUSB_DIR_OUT)) { - start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); + start_rx_dma(®s->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. - // For endpoint size greater then FIFO size enable FIFO level warning interrupt - // when FIFO has less then 17 bytes free. - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; + // For endpoint size greater than FIFO size enable FIFO level warning interrupt + // when FIFO has less than 17 bytes free. + regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos); } } else if (epnum != 0) { // If max_packet_size would fit in FIFO no need for FIFO level warning interrupt. - xfer->regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; + regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos)); } - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } static void start_tx_dma(void *src, volatile void *dst, uint16_t size) @@ -374,13 +399,13 @@ static void start_tx_packet(xfer_ctl_t *xfer) uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint16_t remaining = xfer->total_len - xfer->transferred; uint16_t size = tu_min16(remaining, xfer->max_packet_size); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(epnum); xfer->last_packet_size = 0; regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; - if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; + if (xfer->data1) regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) { @@ -395,9 +420,9 @@ static void start_tx_packet(xfer_ctl_t *xfer) regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk; } -static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) +static uint16_t read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) { - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = XFER_REGS(xfer); uint16_t remaining = xfer->total_len - xfer->transferred - xfer->last_packet_size; uint16_t receive_this_time = bytes_in_fifo; @@ -408,6 +433,8 @@ static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; xfer->last_packet_size += receive_this_time; + + return bytes_in_fifo - receive_this_time; } static void handle_ep0_rx(void) @@ -467,7 +494,7 @@ static void handle_ep0_tx(void) { uint32_t txs0; xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = XFER_REGS(xfer); txs0 = regs->USB_TXS0_REG; @@ -501,7 +528,7 @@ static void handle_epx_rx_ev(uint8_t ep) int fifo_bytes; xfer_ctl_t *xfer = XFER_CTL_BASE(ep, TUSB_DIR_OUT); - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(ep); do { @@ -537,7 +564,7 @@ static void handle_epx_rx_ev(uint8_t ep) // FIFO maybe empty if DMA read it before or it's final iteration and function already read all that was to read. if (fifo_bytes > 0) { - read_rx_fifo(xfer, fifo_bytes); + fifo_bytes = read_rx_fifo(xfer, fifo_bytes); } if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) { @@ -552,6 +579,13 @@ static void handle_epx_rx_ev(uint8_t ep) xfer->transferred += xfer->last_packet_size; if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size || xfer->iso) { + if (fifo_bytes) + { + // There are extra bytes in the FIFO just flush them + regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; + fifo_bytes = 0; + } + dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, XFER_RESULT_SUCCESS, true); } else @@ -580,7 +614,7 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer) { uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint32_t txs; - EPx_REGS *regs = xfer->regs; + EPx_REGS *regs = EPNUM_REGS(epnum); txs = regs->txs; @@ -607,6 +641,13 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer) return; } } + else if (regs->epc_in & USB_USB_EPC1_REG_USB_STALL_Msk) + { + // TX_DONE also indicates that STALL packet was just sent, there is + // no point to put anything into transmit FIFO. It could result in + // empty packet being scheduled. + return; + } } if (txs & USB_USB_TXS1_REG_USB_TX_URUN_Msk) { @@ -626,60 +667,81 @@ static void handle_tx_ev(void) handle_epx_tx_ev(XFER_CTL_BASE(3, TUSB_DIR_IN)); } +static uint32_t check_reset_end(uint32_t alt_ev) +{ + if (_dcd.nfsr == NFSR_NODE_RESET) + { + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESET)) + { + // Could be still in reset, but since USB_M_RESET is disabled it can + // be also old reset state that was not cleared yet. + // If (after reading USB_ALTEV_REG register again) bit is cleared + // reset state just ended. + // Keep non-reset bits combined from two previous ALTEV read and + // one from the next line. + alt_ev = (alt_ev & ~USB_USB_ALTEV_REG_USB_RESET_Msk) | USB->USB_ALTEV_REG; + } + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESET) == 0) + { + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk | + USB_USB_ALTEV_REG_USB_SD3_Msk; + set_nfsr(NFSR_NODE_OPERATIONAL); + dcd_edpt_open(0, &ep0OUT_desc); + dcd_edpt_open(0, &ep0IN_desc); + } + } + return alt_ev; +} + static void handle_bus_reset(void) { + uint32_t alt_ev; + USB->USB_NFSR_REG = 0; USB->USB_FAR_REG = 0x80; USB->USB_ALTMSK_REG = 0; USB->USB_NFSR_REG = NFSR_NODE_RESET; USB->USB_TXMSK_REG = 0; USB->USB_RXMSK_REG = 0; - (void)USB->USB_ALTEV_REG; - _dcd.in_reset = true; + set_nfsr(NFSR_NODE_RESET); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); USB->USB_DMA_CTRL_REG = 0; USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | -#if USE_SOF USB_USB_MAMSK_REG_USB_M_FRAME_Msk | -#endif USB_USB_MAMSK_REG_USB_M_WARN_Msk | USB_USB_MAMSK_REG_USB_M_ALT_Msk; - USB->USB_NFSR_REG = NFSR_NODE_OPERATIONAL; - USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_SD3_Msk | - USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; - // There is no information about end of reset state - // USB_FRAME event will be used to enable reset detection again - REG_SET_BIT(USB_MAEV_REG, USB_FRAME); - dcd_edpt_open (0, &ep0OUT_desc); - dcd_edpt_open (0, &ep0IN_desc); + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; + alt_ev = USB->USB_ALTEV_REG; + check_reset_end(alt_ev); } static void handle_alt_ev(void) { uint32_t alt_ev = USB->USB_ALTEV_REG; - if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESET)) + alt_ev = check_reset_end(alt_ev); + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESET) && _dcd.nfsr != NFSR_NODE_RESET) { handle_bus_reset(); } - else + else if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESUME)) { - if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESUME)) + if (USB->USB_NFSR_REG == NFSR_NODE_SUSPEND) { - USB->USB_NFSR_REG = NFSR_NODE_OPERATIONAL; - USB->USB_ALTMSK_REG &= ~USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; - USB->USB_ALTMSK_REG |= USB_USB_ALTMSK_REG_USB_M_SD3_Msk; + set_nfsr(NFSR_NODE_OPERATIONAL); + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk | + USB_USB_ALTMSK_REG_USB_M_SD3_Msk; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_SD3)) - { - USB->USB_NFSR_REG = NFSR_NODE_SUSPEND; - USB->USB_ALTMSK_REG |= USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; - USB->USB_ALTMSK_REG &= ~USB_USB_ALTMSK_REG_USB_M_SD3_Msk | USB_USB_ALTMSK_REG_USB_M_SD5_Msk; - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); - } + } + else if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_SD3)) + { + set_nfsr(NFSR_NODE_SUSPEND); + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk | + USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } } @@ -735,19 +797,13 @@ static void handle_ep0_nak(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; - USB->USB_NFSR_REG = 0; - USB->USB_FAR_REG = 0x80; - USB->USB_NFSR_REG = NFSR_NODE_RESET; - USB->USB_TXMSK_REG = 0; - USB->USB_RXMSK_REG = 0; + (void) rhport; - USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | - USB_USB_MAMSK_REG_USB_M_ALT_Msk | - USB_USB_MAMSK_REG_USB_M_WARN_Msk; - USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; - - dcd_connect(rhport); + _dcd.init_called = true; + if (_dcd.vbus_present) + { + dcd_connect(rhport); + } } void dcd_int_enable(uint8_t rhport) @@ -777,16 +833,37 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; + if (_dcd.nfsr == NFSR_NODE_SUSPEND) + { + // Enter fake state that will use FRAME interrupt to wait before going operational. + set_nfsr(NFSR_NODE_WAKING); + USB->USB_MAMSK_REG |= USB_USB_MAMSK_REG_USB_M_FRAME_Msk; + } } void dcd_connect(uint8_t rhport) { (void)rhport; - REG_SET_BIT(USB_MCTRL_REG, USB_NAT); + if (GET_BIT(USB->USB_MCTRL_REG, USB_USB_MCTRL_REG_USB_NAT) == 0) + { + USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; + USB->USB_NFSR_REG = 0; + USB->USB_FAR_REG = 0x80; + USB->USB_TXMSK_REG = 0; + USB->USB_RXMSK_REG = 0; - // Select chosen DMA to be triggered by USB. - DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX; + USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | + USB_USB_MAMSK_REG_USB_M_ALT_Msk | + USB_USB_MAMSK_REG_USB_M_WARN_Msk; + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk | + USB_USB_ALTEV_REG_USB_SD3_Msk; + + USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk | USB_USB_MCTRL_REG_USB_NAT_Msk; + + // Select chosen DMA to be triggered by USB. + DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX; + } } void dcd_disconnect(uint8_t rhport) @@ -796,6 +873,30 @@ void dcd_disconnect(uint8_t rhport) REG_CLR_BIT(USB_MCTRL_REG, USB_NAT); } +TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void) +{ + return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; +} + +void tusb_vbus_changed(bool present) +{ + if (present && !_dcd.vbus_present) + { + _dcd.vbus_present = true; + // If power event happened before USB started, delay dcd_connect + // until dcd_init is called. + if (_dcd.init_called) + { + dcd_connect(0); + } + } + else if (!present && _dcd.vbus_present) + { + _dcd.vbus_present = false; + USB->USB_MCTRL_REG = 0; + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr()); + } +} /*------------------------------------------------------------------*/ /* DCD Endpoint port @@ -808,11 +909,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); uint8_t iso_mask = 0; TU_ASSERT(epnum < EP_MAX); - xfer->max_packet_size = desc_edpt->wMaxPacketSize.size; + xfer->max_packet_size = tu_edpt_packet_size(desc_edpt); xfer->ep_addr = desc_edpt->bEndpointAddress; xfer->data1 = 0; xfer->iso = 0; @@ -832,13 +934,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; USB->USB_RXMSK_REG |= 0x101 << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_RX_EV); } else { - xfer->regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; USB->USB_TXMSK_REG |= 0x101 << (epnum - 1); REG_SET_BIT(USB_MAMSK_REG, USB_M_TX_EV); } @@ -847,10 +949,22 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + + for (int epnum = 1; epnum < EP_MAX; ++epnum) + { + dcd_edpt_close(0, epnum | TUSB_DIR_OUT); + dcd_edpt_close(0, epnum | TUSB_DIR_IN); + } +} + void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + EPx_REGS *regs = EPNUM_REGS(epnum); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); (void)rhport; @@ -866,8 +980,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { if (dir == TUSB_DIR_OUT) { - xfer->regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; - xfer->regs->epc_out = 0; + regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; + regs->epc_out = 0; USB->USB_RXMSK_REG &= ~(0x101 << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_OUT] == epnum) @@ -878,8 +992,8 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) } else { - xfer->regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; - xfer->regs->epc_in = 0; + regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; + regs->epc_in = 0; USB->USB_TXMSK_REG &= ~(0x101 << (epnum - 1)); // Release DMA if needed if (_dcd.dma_ep[TUSB_DIR_IN] == epnum) @@ -889,6 +1003,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) } } } + tu_memclr(xfer, sizeof(*xfer)); } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) @@ -924,6 +1039,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) (void)rhport; xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); xfer->stall = 1; if (epnum == 0) @@ -932,11 +1048,11 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) REG_SET_BIT(USB_EPC0_REG, USB_STALL); if (dir == TUSB_DIR_OUT) { - xfer->regs->USB_RXC0_REG = USB_USB_RXC0_REG_USB_RX_EN_Msk; + regs->USB_RXC0_REG = USB_USB_RXC0_REG_USB_RX_EN_Msk; } else { - if (xfer->regs->USB_RXC0_REG & USB_USB_RXC0_REG_USB_RX_EN_Msk) + if (regs->USB_RXC0_REG & USB_USB_RXC0_REG_USB_RX_EN_Msk) { // If RX is also enabled TX will not be stalled since RX has // higher priority. Enable NAK interrupt to handle stall. @@ -944,7 +1060,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) } else { - xfer->regs->USB_TXC0_REG |= USB_USB_TXC0_REG_USB_TX_EN_Msk; + regs->USB_TXC0_REG |= USB_USB_TXC0_REG_USB_TX_EN_Msk; } } } @@ -952,13 +1068,13 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out |= USB_USB_EPC1_REG_USB_STALL_Msk; - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + regs->epc_out |= USB_USB_EPC1_REG_USB_STALL_Msk; + regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } else { - xfer->regs->epc_in |= USB_USB_EPC1_REG_USB_STALL_Msk; - xfer->regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; + regs->epc_in |= USB_USB_EPC1_REG_USB_STALL_Msk; + regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; } } } @@ -971,6 +1087,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) (void)rhport; xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + EPx_REGS *regs = EPNUM_REGS(epnum); // Clear stall is called in response to Clear Feature ENDPOINT_HALT, reset toggle xfer->data1 = 0; @@ -978,11 +1095,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) if (dir == TUSB_DIR_OUT) { - xfer->regs->epc_out &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + regs->epc_out &= ~USB_USB_EPC1_REG_USB_STALL_Msk; } else { - xfer->regs->epc_in &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + regs->epc_in &= ~USB_USB_EPC1_REG_USB_STALL_Msk; } if (epnum == 0) { @@ -996,7 +1113,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) void dcd_int_handler(uint8_t rhport) { - uint32_t int_status = USB->USB_MAEV_REG; + uint32_t int_status = USB->USB_MAEV_REG & USB->USB_MAMSK_REG; (void)rhport; @@ -1038,19 +1155,38 @@ void dcd_int_handler(uint8_t rhport) if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_FRAME)) { - if (_dcd.in_reset) + if (_dcd.nfsr == NFSR_NODE_RESET) { - // Enable reset detection - _dcd.in_reset = false; - (void)USB->USB_ALTEV_REG; + // During reset FRAME interrupt is enabled to periodically + // check when reset state ends. + // FRAME interrupt is generated every 1ms without host sending + // actual SOF. + check_reset_end(USB_USB_ALTEV_REG_USB_RESET_Msk); } + else if (_dcd.nfsr == NFSR_NODE_WAKING) + { + // No need to call set_nfsr, just set state + _dcd.nfsr = NFSR_NODE_WAKING2; + } + else if (_dcd.nfsr == NFSR_NODE_WAKING2) + { + // No need to call set_nfsr, just set state + _dcd.nfsr = NFSR_NODE_RESUME; + } + else if (_dcd.nfsr == NFSR_NODE_RESUME) + { + set_nfsr(NFSR_NODE_OPERATIONAL); + } + else + { #if USE_SOF - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); #else - // SOF was used to re-enable reset detection - // No need to keep it enabled - USB->USB_MAMSK_REG &= ~USB_USB_MAMSK_REG_USB_M_FRAME_Msk; + // FRAME interrupt was used to re-enable reset detection or remote + // wakeup no need to keep it enabled when USE_SOF is off. + USB->USB_MAMSK_REG &= ~USB_USB_MAMSK_REG_USB_M_FRAME_Msk; #endif + } } if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_TX_EV)) diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index e3b7499cc..e92f8a951 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -128,7 +128,7 @@ static inline ehci_qtd_t* qtd_find_free (void); static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new); static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); -static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); +static void qtd_init (ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes); static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); @@ -392,7 +392,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - qtd_init(td, (void*) setup_packet, 8); + qtd_init(td, setup_packet, 8); td->pid = EHCI_PID_SETUP; td->int_on_complete = 1; td->next.terminate = 1; @@ -802,7 +802,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->ep_speed = devtree_info.speed; p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head - p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size; + p_qhd->max_packet_size = tu_edpt_packet_size(ep_desc); p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0; p_qhd->nak_reload = 0; @@ -857,7 +857,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c } } -static void qtd_init(ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes) +static void qtd_init(ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes) { tu_memclr(p_qtd, sizeof(ehci_qtd_t)); diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index d728487c2..a9c311324 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -31,7 +31,6 @@ #if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) // Espressif -#include "driver/periph_ctrl.h" #include "freertos/xtensa_api.h" #include "esp_intr_alloc.h" #include "esp_log.h" @@ -39,13 +38,10 @@ #include "soc/dport_reg.h" #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" +#include "soc/periph_defs.h" // for interrupt source #include "device/dcd.h" -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#define USE_SOF 0 - // Max number of bi-directional endpoints including EP0 // Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 // We should probably prohibit enabling Endpoint IN > 4 (not done yet) @@ -92,11 +88,12 @@ static void bus_reset(void) USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK } - USB0.dcfg &= ~USB_DEVADDR_M; // reset address + // clear device address + USB0.dcfg &= ~USB_DEVADDR_M; - USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture @@ -193,9 +190,6 @@ void dcd_init(uint8_t rhport) USB0.gintsts = ~0U; //clear pending ints USB0.gintmsk = USB_OTGINTMSK_M | USB_MODEMISMSK_M | - #if USE_SOF - USB_SOFMSK_M | - #endif USB_RXFLVIMSK_M | USB_ERLYSUSPMSK_M | USB_USBSUSPMSK_M | @@ -220,8 +214,17 @@ void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; - // TODO must manually clear this bit after 1-15 ms - // USB0.DCTL |= USB_RMTWKUPSIG_M; + // set remote wakeup + USB0.dctl |= USB_RMTWKUPSIG_M; + + // enable SOF to detect bus resume + USB0.gintsts = USB_SOF_M; + USB0.gintmsk |= USB_SOFMSK_M; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + vTaskDelay(pdMS_TO_TICKS(1)); + + USB0.dctl &= ~USB_RMTWKUPSIG_M; } // connect by enabling internal pull-up resistor on D+/D- @@ -253,16 +256,16 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = desc_edpt->wMaxPacketSize.size; + xfer->max_size = tu_edpt_packet_size(desc_edpt); if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP0_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | - desc_edpt->wMaxPacketSize.size << USB_MPS0_S; + out_ep[epnum].doepctl |= USB_USBACTEP1_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | + xfer->max_size << USB_MPS1_S; USB0.daintmsk |= (1 << (16 + epnum)); } else { // "USB Data FIFOs" section in reference manual @@ -296,7 +299,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) fifo_num << USB_D_TXFNUM1_S | desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - desc_edpt->wMaxPacketSize.size << 0; + xfer->max_size << 0; USB0.daintmsk |= (1 << (0 + epnum)); @@ -312,6 +315,30 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) return true; } +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + // Disable non-control interrupt + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].doepctl = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].diepctl = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + _allocated_fifos = 1; +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { (void)rhport; @@ -361,49 +388,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void)rhport; - - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; } #endif @@ -748,8 +732,8 @@ static void _dcd_int_handler(void* arg) (void) arg; uint8_t const rhport = 0; - const uint32_t int_status = USB0.gintsts; - //const uint32_t int_msk = USB0.gintmsk; + const uint32_t int_msk = USB0.gintmsk; + const uint32_t int_status = USB0.gintsts & int_msk; if (int_status & USB_USBRST_M) { // start of reset @@ -802,12 +786,15 @@ static void _dcd_int_handler(void* arg) USB0.gotgint = otg_int; } -#if USE_SOF if (int_status & USB_SOF_M) { USB0.gintsts = USB_SOF_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually + + // Disable SOF interrupt since currently only used for remote wakeup detection + USB0.gintmsk &= ~USB_SOFMSK_M; + + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } -#endif + if (int_status & USB_RXFLVI_M) { // RXFLVL bit is read-only diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c new file mode 100644 index 000000000..f6e05e134 --- /dev/null +++ b/src/portable/mentor/musb/dcd_musb.c @@ -0,0 +1,900 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * + * 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_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && \ + TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + +#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) +/* GCC warns that an address may be unaligned, even though + * the target CPU has the capability for unaligned memory access. */ +_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); +#endif + +#include "device/dcd.h" + +#if TU_CHECK_MCU(OPT_MCU_MSP432E4) + #include "musb_msp432e.h" + +#elif TU_CHECK_MCU(OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #include "musb_tm4c.h" + + // HACK generalize later + #include "musb_type.h" + #define FIFO0_WORD FIFO0 + #define FIFO1_WORD FIFO1 + +#else + #error "Unsupported MCUs" +#endif + +/*------------------------------------------------------------------ + * MACRO TYPEDEF CONSTANT ENUM DECLARATION + *------------------------------------------------------------------*/ +#define REQUEST_TYPE_INVALID (0xFFu) + +typedef struct { + uint_fast16_t beg; /* offset of including first element */ + uint_fast16_t end; /* offset of excluding the last element */ +} free_block_t; + +typedef struct TU_ATTR_PACKED { + uint16_t TXMAXP; + uint8_t TXCSRL; + uint8_t TXCSRH; + uint16_t RXMAXP; + uint8_t RXCSRL; + uint8_t RXCSRH; + uint16_t RXCOUNT; + uint16_t RESERVED[3]; +} hw_endpoint_t; + +typedef union { + uint8_t u8; + uint16_t u16; + uint32_t u32; +} hw_fifo_t; + +typedef struct TU_ATTR_PACKED +{ + void *buf; /* the start address of a transfer data buffer */ + uint16_t length; /* the number of bytes in the buffer */ + uint16_t remaining; /* the number of bytes remaining in the buffer */ +} pipe_state_t; + +typedef struct +{ + tusb_control_request_t setup_packet; + uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ + int8_t status_out; + pipe_state_t pipe0; + pipe_state_t pipe[2][7]; /* pipe[direction][endpoint number - 1] */ + uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */ +} dcd_data_t; + +/*------------------------------------------------------------------ + * INTERNAL OBJECT & FUNCTION DECLARATION + *------------------------------------------------------------------*/ +static dcd_data_t _dcd; + + +static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) +{ + free_block_t *cur = beg; + for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ; + return cur; +} + +static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) +{ + free_block_t *p = find_containing_block(blks, blks + num, addr); + TU_ASSERT(p != blks + num, -2); + if (p->beg == addr) { + /* Shrink block */ + p->beg = addr + size; + if (p->beg != p->end) return 0; + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } else { + /* Split into 2 blocks */ + free_block_t tmp = { + .beg = addr + size, + .end = p->end + }; + p->end = addr; + if (p->beg == p->end) { + if (tmp.beg != tmp.end) { + *p = tmp; + return 0; + } + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } + if (tmp.beg == tmp.end) return 0; + blks[num] = tmp; + return 1; + } +} + +static inline unsigned free_block_size(free_block_t const *blk) +{ + return blk->end - blk->beg; +} + +#if 0 +static inline void print_block_list(free_block_t const *blk, unsigned num) +{ + TU_LOG1("*************\n"); + for (unsigned i = 0; i < num; ++i) { + TU_LOG1(" Blk%u %u %u\n", i, blk->beg, blk->end); + ++blk; + } +} +#else +#define print_block_list(a,b) +#endif + +static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) +{ + free_block_t free_blocks[2 * (DCD_ATTR_ENDPOINT_MAX - 1)]; + unsigned num_blocks = 1; + + /* Initialize free memory block list */ + free_blocks[0].beg = 64 / 8; + free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ + for (int i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { + uint_fast16_t addr; + int num; + USB0->EPIDX = i; + addr = USB0->TXFIFOADD; + if (addr) { + unsigned sz = USB0->TXFIFOSZ; + unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + print_block_list(free_blocks, num_blocks); + } + addr = USB0->RXFIFOADD; + if (addr) { + unsigned sz = USB0->RXFIFOSZ; + unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + print_block_list(free_blocks, num_blocks); + } + } + print_block_list(free_blocks, num_blocks); + + /* Find the best fit memory block */ + uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; + free_block_t const *min = NULL; + uint_fast16_t min_sz = 0xFFFFu; + free_block_t const *end = &free_blocks[num_blocks]; + for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) { + uint_fast16_t sz = free_block_size(cur); + if (sz < size_in_8byte_unit) continue; + if (size_in_8byte_unit == sz) return cur->beg; + if (sz < min_sz) min = cur; + } + TU_ASSERT(min, 0); + return min->beg; +} + +static inline volatile hw_endpoint_t* edpt_regs(unsigned epnum_minus1) +{ + volatile hw_endpoint_t *regs = (volatile hw_endpoint_t*)((uintptr_t)&USB0->TXMAXP1); + return regs + epnum_minus1; +} + +static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + reg->u32 = *(uint32_t const *)addr; + addr += 4; + len -= 4; + } + if (len >= 2) { + reg->u16 = *(uint16_t const *)addr; + addr += 2; + len -= 2; + } + if (len) { + reg->u8 = *(uint8_t const *)addr; + } +} + +static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + *(uint32_t *)addr = reg->u32; + addr += 4; + len -= 4; + } + if (len >= 2) { + *(uint16_t *)addr = reg->u16; + addr += 2; + len -= 2; + } + if (len) { + *(uint8_t *)addr = reg->u8; + } +} + +static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) +{ + static const struct { + void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info); + void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n); + void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len); + } ops[] = { + /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet}, + /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet}, + }; + tu_fifo_buffer_info_t info; + ops[dir].tu_fifo_get_info(f, &info); + unsigned total_len = len; + len = TU_MIN(total_len, info.len_lin); + ops[dir].pipe_read_write(info.ptr_lin, fifo, len); + unsigned rem = total_len - len; + if (rem) { + len = TU_MIN(rem, info.len_wrap); + ops[dir].pipe_read_write(info.ptr_wrap, fifo, len); + rem -= len; + } + ops[dir].tu_fifo_advance(f, total_len - rem); +} + +static void process_setup_packet(uint8_t rhport) +{ + uint32_t *p = (void*)&_dcd.setup_packet; + p[0] = USB0->FIFO0_WORD; + p[1] = USB0->FIFO0_WORD; + + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); + + const unsigned len = _dcd.setup_packet.wLength; + _dcd.remaining_ctrl = len; + const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType); + /* Clear RX FIFO and reverse the transaction direction */ + if (len && dir_in) USB0->CSRL0 = USB_CSRL0_RXRDYC; +} + +static bool handle_xfer_in(uint_fast8_t ep_addr) +{ + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; + const unsigned rem = pipe->remaining; + + if (!rem) { + pipe->buf = NULL; + return true; + } + + volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); + const unsigned mps = regs->TXMAXP; + const unsigned len = TU_MIN(mps, rem); + void *buf = pipe->buf; + // TU_LOG1(" %p mps %d len %d rem %d\n", buf, mps, len, rem); + if (len) { + if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { + pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_IN); + } else { + pipe_write_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len); + pipe->buf = buf + len; + } + pipe->remaining = rem - len; + } + regs->TXCSRL = USB_TXCSRL1_TXRDY; + // TU_LOG1(" TXCSRL%d = %x %d\n", epnum_minus1 + 1, regs->TXCSRL, rem - len); + return false; +} + +static bool handle_xfer_out(uint_fast8_t ep_addr) +{ + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; + volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); + // TU_LOG1(" RXCSRL%d = %x\n", epnum_minus1 + 1, regs->RXCSRL); + + TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY); + + const unsigned mps = regs->RXMAXP; + const unsigned rem = pipe->remaining; + const unsigned vld = regs->RXCOUNT; + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { + pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_OUT); + } else { + pipe_read_packet(buf, &USB0->FIFO1_WORD + epnum_minus1, len); + pipe->buf = buf + len; + } + pipe->remaining = rem - len; + } + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return NULL != buf; + } + regs->RXCSRL = 0; /* Clear RXRDY bit */ + return false; +} + +static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + unsigned dir_in = tu_edpt_dir(ep_addr); + + pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1]; + pipe->buf = buffer; + pipe->length = total_bytes; + pipe->remaining = total_bytes; + + if (dir_in) { + handle_xfer_in(ep_addr); + } else { + volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1); + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) regs->RXCSRL = 0; + } + return true; +} + +static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ + + const unsigned req = _dcd.setup_packet.bmRequestType; + TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0); + + if (req == REQUEST_TYPE_INVALID || _dcd.status_out) { + /* STATUS OUT stage. + * MUSB controller automatically handles STATUS OUT packets without + * software helps. We do not have to do anything. And STATUS stage + * may have already finished and received the next setup packet + * without calling this function, so we have no choice but to + * invoke the callback function of status packet here. */ + // TU_LOG1(" STATUS OUT USB0->CSRL0 = %x\n", USB0->CSRL0); + _dcd.status_out = 0; + if (req == REQUEST_TYPE_INVALID) { + dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false); + } else { + /* The next setup packet has already been received, it aborts + * invoking callback function to avoid confusing TUSB stack. */ + TU_LOG1("Drop CONTROL_STAGE_ACK\n"); + } + return true; + } + const unsigned dir_in = tu_edpt_dir(ep_addr); + if (tu_edpt_dir(req) == dir_in) { /* DATA stage */ + TU_ASSERT(total_bytes <= _dcd.remaining_ctrl); + const unsigned rem = _dcd.remaining_ctrl; + const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); + if (dir_in) { + pipe_write_packet(buffer, &USB0->FIFO0_WORD, len); + + _dcd.pipe0.buf = buffer + len; + _dcd.pipe0.length = len; + _dcd.pipe0.remaining = 0; + + _dcd.remaining_ctrl = rem - len; + if ((len < 64) || (rem == len)) { + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */ + _dcd.status_out = 1; + /* Flush TX FIFO and reverse the transaction direction. */ + USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_DATAEND; + } else { + USB0->CSRL0 = USB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */ + } + // TU_LOG1(" IN USB0->CSRL0 = %x\n", USB0->CSRL0); + } else { + // TU_LOG1(" OUT USB0->CSRL0 = %x\n", USB0->CSRL0); + _dcd.pipe0.buf = buffer; + _dcd.pipe0.length = len; + _dcd.pipe0.remaining = len; + USB0->CSRL0 = USB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */ + } + } else if (dir_in) { + // TU_LOG1(" STATUS IN USB0->CSRL0 = %x\n", USB0->CSRL0); + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + /* Clear RX FIFO and reverse the transaction direction */ + USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND; + } + return true; +} + +static void process_ep0(uint8_t rhport) +{ + uint_fast8_t csrl = USB0->CSRL0; + + // TU_LOG1(" EP0 USB0->CSRL0 = %x\n", csrl); + + if (csrl & USB_CSRL0_STALLED) { + /* Returned STALL packet to HOST. */ + USB0->CSRL0 = 0; /* Clear STALL */ + return; + } + + unsigned req = _dcd.setup_packet.bmRequestType; + if (csrl & USB_CSRL0_SETEND) { + TU_LOG1(" ABORT by the next packets\n"); + USB0->CSRL0 = USB_CSRL0_SETENDC; + if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) { + /* DATA stage was aborted by receiving STATUS or SETUP packet. */ + _dcd.pipe0.buf = NULL; + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + dcd_event_xfer_complete(rhport, + req & TUSB_DIR_IN_MASK, + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + req = REQUEST_TYPE_INVALID; + if (!(csrl & USB_CSRL0_RXRDY)) return; /* Received SETUP packet */ + } + + if (csrl & USB_CSRL0_RXRDY) { + /* Received SETUP or DATA OUT packet */ + if (req == REQUEST_TYPE_INVALID) { + /* SETUP */ + TU_ASSERT(sizeof(tusb_control_request_t) == USB0->COUNT0,); + process_setup_packet(rhport); + return; + } + if (_dcd.pipe0.buf) { + /* DATA OUT */ + const unsigned vld = USB0->COUNT0; + const unsigned rem = _dcd.pipe0.remaining; + const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); + pipe_read_packet(_dcd.pipe0.buf, &USB0->FIFO0_WORD, len); + + _dcd.pipe0.remaining = rem - len; + _dcd.remaining_ctrl -= len; + + _dcd.pipe0.buf = NULL; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + return; + } + + /* When CSRL0 is zero, it means that completion of sending a any length packet + * or receiving a zero length packet. */ + if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) { + /* STATUS IN */ + if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) { + /* The address must be changed on completion of the control transfer. */ + USB0->FADDR = (uint8_t)_dcd.setup_packet.wValue; + } + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_IN), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + return; + } + if (_dcd.pipe0.buf) { + /* DATA IN */ + _dcd.pipe0.buf = NULL; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_IN), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) +{ + bool completed; + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned epn_minus1 = tu_edpt_number(ep_addr) - 1; + + volatile hw_endpoint_t *regs = edpt_regs(epn_minus1); + if (dir_in) { + // TU_LOG1(" TXCSRL%d = %x\n", epn_minus1 + 1, regs->TXCSRL); + if (regs->TXCSRL & USB_TXCSRL1_STALLED) { + regs->TXCSRL &= ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_UNDRN); + return; + } + completed = handle_xfer_in(ep_addr); + } else { + // TU_LOG1(" RXCSRL%d = %x\n", epn_minus1 + 1, regs->RXCSRL); + if (regs->RXCSRL & USB_RXCSRL1_STALLED) { + regs->RXCSRL &= ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_OVER); + return; + } + completed = handle_xfer_out(ep_addr); + } + + if (completed) { + pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1]; + dcd_event_xfer_complete(rhport, ep_addr, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), + * a control transfer state is SETUP or STATUS stage. */ + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.status_out = 0; + /* When pipe0.buf has not NULL, DATA stage works in progress. */ + _dcd.pipe0.buf = NULL; + + USB0->TXIE = 1; /* Enable only EP0 */ + USB0->RXIE = 0; + + /* Clear FIFO settings */ + for (unsigned i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { + USB0->EPIDX = i; + USB0->TXFIFOSZ = 0; + USB0->TXFIFOADD = 0; + USB0->RXFIFOSZ = 0; + USB0->RXFIFOADD = 0; + } + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); +} + +/*------------------------------------------------------------------ + * Device API + *------------------------------------------------------------------*/ + +void dcd_init(uint8_t rhport) +{ + (void)rhport; + USB0->IE |= USB_IE_SUSPND; + NVIC_ClearPendingIRQ(USB0_IRQn); + + dcd_connect(rhport); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + (void)dev_addr; + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + /* Clear RX FIFO to return ACK. */ + USB0->CSRL0 = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND; +} + +// Wake up host +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + USB0->POWER |= USB_POWER_RESUME; + + unsigned cnt = SystemCoreClock / 1000; + while (cnt--) __NOP(); + + USB0->POWER &= ~USB_POWER_RESUME; +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + USB0->POWER |= USB_POWER_SOFTCONN; +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + USB0->POWER &= ~USB_POWER_SOFTCONN; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned xfer = ep_desc->bmAttributes.xfer; + const unsigned mps = tu_edpt_packet_size(ep_desc); + + TU_ASSERT(epn < DCD_ATTR_ENDPOINT_MAX); + + pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + + volatile hw_endpoint_t *regs = edpt_regs(epn - 1); + if (dir_in) { + regs->TXMAXP = mps; + regs->TXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_TXCSRH1_ISO : 0; + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + USB0->TXIE |= TU_BIT(epn); + } else { + regs->RXMAXP = mps; + regs->RXCSRH = (xfer == TUSB_XFER_ISOCHRONOUS) ? USB_RXCSRH1_ISO : 0; + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + USB0->RXIE |= TU_BIT(epn); + } + + /* Setup FIFO */ + int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps)); + if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3; + unsigned addr = find_free_memory(size_in_log2_minus3); + TU_ASSERT(addr); + + USB0->EPIDX = epn; + if (dir_in) { + USB0->TXFIFOADD = addr; + USB0->TXFIFOSZ = size_in_log2_minus3; + } else { + USB0->RXFIFOADD = addr; + USB0->RXFIFOSZ = size_in_log2_minus3; + } + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + volatile hw_endpoint_t *regs = (volatile hw_endpoint_t *)(uintptr_t)&USB0->TXMAXP1; + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + USB0->TXIE = 1; /* Enable only EP0 */ + USB0->RXIE = 0; + for (unsigned i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { + regs->TXMAXP = 0; + regs->TXCSRH = 0; + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + + regs->RXMAXP = 0; + regs->RXCSRH = 0; + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + + USB0->EPIDX = i; + USB0->TXFIFOSZ = 0; + USB0->TXFIFOADD = 0; + USB0->RXFIFOSZ = 0; + USB0->RXFIFOADD = 0; + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + unsigned const dir_in = tu_edpt_dir(ep_addr); + + hw_endpoint_t volatile *regs = edpt_regs(epn - 1); + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + if (dir_in) { + USB0->TXIE &= ~TU_BIT(epn); + regs->TXMAXP = 0; + regs->TXCSRH = 0; + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + + USB0->EPIDX = epn; + USB0->TXFIFOSZ = 0; + USB0->TXFIFOADD = 0; + } else { + USB0->RXIE &= ~TU_BIT(epn); + regs->RXMAXP = 0; + regs->RXCSRH = 0; + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + + USB0->EPIDX = epn; + USB0->RXFIFOSZ = 0; + USB0->RXFIFOADD = 0; + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void)rhport; + bool ret; + // TU_LOG1("X %x %d\n", ep_addr, total_bytes); + unsigned const epnum = tu_edpt_number(ep_addr); + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + if (epnum) { + _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1); + ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes); + } else + ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes); + if (ie) NVIC_EnableIRQ(USB0_IRQn); + return ret; +} + +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; + bool ret; + // TU_LOG1("X %x %d\n", ep_addr, total_bytes); + unsigned const epnum = tu_edpt_number(ep_addr); + TU_ASSERT(epnum); + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1); + ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes); + if (ie) NVIC_EnableIRQ(USB0_IRQn); + return ret; +} + +// Stall endpoint +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + if (0 == epn) { + if (!ep_addr) { /* Ignore EP80 */ + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.pipe0.buf = NULL; + USB0->CSRL0 = USB_CSRL0_STALL; + } + } else { + volatile hw_endpoint_t *regs = edpt_regs(epn - 1); + if (tu_edpt_dir(ep_addr)) { /* IN */ + regs->TXCSRL = USB_TXCSRL1_STALL; + } else { /* OUT */ + TU_ASSERT(!(regs->RXCSRL & USB_RXCSRL1_RXRDY),); + regs->RXCSRL = USB_RXCSRL1_STALL; + } + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + hw_endpoint_t volatile *regs = edpt_regs(epn - 1); + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + if (tu_edpt_dir(ep_addr)) { /* IN */ + regs->TXCSRL = USB_TXCSRL1_CLRDT; + } else { /* OUT */ + regs->RXCSRL = USB_RXCSRL1_CLRDT; + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +/*------------------------------------------------------------------- + * ISR + *-------------------------------------------------------------------*/ +void dcd_int_handler(uint8_t rhport) +{ + uint_fast8_t is, txis, rxis; + + is = USB0->IS; /* read and clear interrupt status */ + txis = USB0->TXIS; /* read and clear interrupt status */ + rxis = USB0->RXIS; /* read and clear interrupt status */ + // TU_LOG1("D%2x T%2x R%2x\n", is, txis, rxis); + + is &= USB0->IE; /* Clear disabled interrupts */ + if (is & USB_IS_DISCON) { + } + if (is & USB_IS_SOF) { + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + if (is & USB_IS_RESET) { + process_bus_reset(rhport); + } + if (is & USB_IS_RESUME) { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + if (is & USB_IS_SUSPEND) { + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + txis &= USB0->TXIE; /* Clear disabled interrupts */ + if (txis & USB_TXIE_EP0) { + process_ep0(rhport); + txis &= ~TU_BIT(0); + } + while (txis) { + unsigned const num = __builtin_ctz(txis); + process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN)); + txis &= ~TU_BIT(num); + } + rxis &= USB0->RXIE; /* Clear disabled interrupts */ + while (rxis) { + unsigned const num = __builtin_ctz(rxis); + process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT)); + rxis &= ~TU_BIT(num); + } +} + +#endif diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c new file mode 100644 index 000000000..acccb7674 --- /dev/null +++ b/src/portable/mentor/musb/hcd_musb.c @@ -0,0 +1,876 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * + * 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_option.h" + +#if TUSB_OPT_HOST_ENABLED && \ + TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + +#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED) +/* GCC warns that an address may be unaligned, even though + * the target CPU has the capability for unaligned memory access. */ +_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); +#endif + +#include "host/hcd.h" + +#if TU_CHECK_MCU(OPT_MCU_MSP432E4) + #include "musb_msp432e.h" + +#elif TU_CHECK_MCU(OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #include "musb_tm4c.h" + + // HACK generalize later + #include "musb_type.h" + #define FIFO0_WORD FIFO0 + +#else + #error "Unsupported MCUs" +#endif + +#ifndef HCD_ATTR_ENDPOINT_MAX +# define HCD_ATTR_ENDPOINT_MAX 8 +#endif + +/*------------------------------------------------------------------ + * MACRO TYPEDEF CONSTANT ENUM DECLARATION + *------------------------------------------------------------------*/ +#define REQUEST_TYPE_INVALID (0xFFu) + +typedef struct { + uint_fast16_t beg; /* offset of including first element */ + uint_fast16_t end; /* offset of excluding the last element */ +} free_block_t; + +typedef struct TU_ATTR_PACKED { + uint8_t TXFUNCADDR; + uint8_t RESERVED0; + uint8_t TXHUBADDR; + uint8_t TXHUBPORT; + uint8_t RXFUNCADDR; + uint8_t RESERVED1; + uint8_t RXHUBADDR; + uint8_t RXHUBPORT; +} hw_addr_t; + +typedef struct TU_ATTR_PACKED { + uint16_t TXMAXP; + uint8_t TXCSRL; + uint8_t TXCSRH; + uint16_t RXMAXP; + uint8_t RXCSRL; + uint8_t RXCSRH; + uint16_t RXCOUNT; + uint8_t TXTYPE; + uint8_t TXINTERVAL; + uint8_t RXTYPE; + uint8_t RXINTERVAL; + uint16_t RESERVED; +} hw_endpoint_t; + +typedef union { + uint8_t u8; + uint16_t u16; + uint32_t u32; +} hw_fifo_t; + +typedef struct TU_ATTR_PACKED +{ + void *buf; /* the start address of a transfer data buffer */ + uint16_t length; /* the number of bytes in the buffer */ + uint16_t remaining; /* the number of bytes remaining in the buffer */ +} pipe_state_t; + +typedef struct TU_ATTR_PACKED +{ + uint8_t dev; + uint8_t ep; +} pipe_addr_t; + +typedef struct +{ + bool need_reset; /* The device has not been reset after connection. */ + uint8_t bmRequestType; + uint8_t ctl_mps[7]; /* EP0 max packet size for each device */ + pipe_state_t pipe0; + pipe_state_t pipe[7][2]; /* pipe[pipe number - 1][direction 0:RX 1:TX] */ + pipe_addr_t addr[7][2]; /* addr[pipe number - 1][direction 0:RX 1:TX] */ +} hcd_data_t; + +/*------------------------------------------------------------------ + * INTERNAL OBJECT & FUNCTION DECLARATION + *------------------------------------------------------------------*/ +static hcd_data_t _hcd; + +static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) +{ + free_block_t *cur = beg; + for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ; + return cur; +} + +static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) +{ + free_block_t *p = find_containing_block(blks, blks + num, addr); + TU_ASSERT(p != blks + num, -2); + if (p->beg == addr) { + /* Shrink block */ + p->beg = addr + size; + if (p->beg != p->end) return 0; + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } else { + /* Split into 2 blocks */ + free_block_t tmp = { + .beg = addr + size, + .end = p->end + }; + p->end = addr; + if (p->beg == p->end) { + if (tmp.beg != tmp.end) { + *p = tmp; + return 0; + } + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } + if (tmp.beg == tmp.end) return 0; + blks[num] = tmp; + return 1; + } +} + +static inline unsigned free_block_size(free_block_t const *blk) +{ + return blk->end - blk->beg; +} + +static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) +{ + free_block_t free_blocks[2 * (HCD_ATTR_ENDPOINT_MAX - 1)]; + unsigned num_blocks = 1; + + /* Initialize free memory block list */ + free_blocks[0].beg = 64 / 8; + free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ + for (int i = 1; i < HCD_ATTR_ENDPOINT_MAX; ++i) { + uint_fast16_t addr; + int num; + USB0->EPIDX = i; + addr = USB0->TXFIFOADD; + if (addr) { + unsigned sz = USB0->TXFIFOSZ; + unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + } + addr = USB0->RXFIFOADD; + if (addr) { + unsigned sz = USB0->RXFIFOSZ; + unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + } + } + + /* Find the best fit memory block */ + uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; + free_block_t const *min = NULL; + uint_fast16_t min_sz = 0xFFFFu; + free_block_t const *end = &free_blocks[num_blocks]; + for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) { + uint_fast16_t sz = free_block_size(cur); + if (sz < size_in_8byte_unit) continue; + if (size_in_8byte_unit == sz) return cur->beg; + if (sz < min_sz) min = cur; + } + TU_ASSERT(min, 0); + return min->beg; +} + +static inline volatile hw_endpoint_t* edpt_regs(unsigned epnum_minus1) +{ + volatile hw_endpoint_t *regs = (volatile hw_endpoint_t*)((uintptr_t)&USB0->TXMAXP1); + return regs + epnum_minus1; +} + +static unsigned find_pipe(uint_fast8_t dev_addr, uint_fast8_t ep_addr) +{ + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + pipe_addr_t const *p = &_hcd.addr[0][dir_tx]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i, p += 2) { + if ((dev_addr == p->dev) && (ep_addr == p->ep)) + return i + 1; + } + return 0; +} + +static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + reg->u32 = *(uint32_t const *)addr; + addr += 4; + len -= 4; + } + if (len >= 2) { + reg->u16 = *(uint16_t const *)addr; + addr += 2; + len -= 2; + } + if (len) { + reg->u8 = *(uint8_t const *)addr; + } +} + +static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) +{ + volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; + uintptr_t addr = (uintptr_t)buf; + while (len >= 4) { + *(uint32_t *)addr = reg->u32; + addr += 4; + len -= 4; + } + if (len >= 2) { + *(uint16_t *)addr = reg->u16; + addr += 2; + len -= 2; + } + if (len) { + *(uint8_t *)addr = reg->u8; + } +} + +static bool edpt0_xfer_out(void) +{ + pipe_state_t *pipe = &_hcd.pipe0; + unsigned const rem = pipe->remaining; + if (!rem) { + pipe->buf = NULL; + return true; + } + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const mps = _hcd.ctl_mps[dev_addr]; + unsigned const len = TU_MIN(rem, mps); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0->FIFO0_WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + USB0->CSRL0 = USB_CSRL0_TXRDY; + return false; +} + +static bool edpt0_xfer_in(void) +{ + pipe_state_t *pipe = &_hcd.pipe0; + unsigned const rem = pipe->remaining; + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const mps = _hcd.ctl_mps[dev_addr]; + unsigned const vld = USB0->COUNT0; + unsigned const len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0->FIFO0_WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return true; + } + USB0->CSRL0 = USB_CSRL0_REQPKT; + return false; +} + +static bool edpt0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + + unsigned const req = _hcd.bmRequestType; + TU_ASSERT(req != REQUEST_TYPE_INVALID); + TU_ASSERT(dev_addr < sizeof(_hcd.ctl_mps)); + + USB0->TXFUNCADDR0 = dev_addr; + const unsigned dir_in = tu_edpt_dir(ep_addr); + if (tu_edpt_dir(req) == dir_in) { /* DATA stage */ + TU_ASSERT(buffer); + _hcd.pipe0.buf = buffer; + _hcd.pipe0.length = buflen; + _hcd.pipe0.remaining = buflen; + if (dir_in) + USB0->CSRL0 = USB_CSRL0_REQPKT; + else + edpt0_xfer_out(); + } else { /* STATUS stage */ + _hcd.pipe0.buf = NULL; + _hcd.pipe0.length = 0; + _hcd.pipe0.remaining = 0; + USB0->CSRL0 = USB_CSRL0_STATUS | (dir_in ? USB_CSRL0_REQPKT: USB_CSRL0_TXRDY); + } + return true; +} + +static bool pipe_xfer_out(uint_fast8_t pipenum) +{ + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][1]; + unsigned const rem = pipe->remaining; + if (!rem) { + pipe->buf = NULL; + return true; + } + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + unsigned const mps = regs->TXMAXP; + unsigned const len = TU_MIN(rem, mps); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0->FIFO0_WORD + pipenum, len); + pipe->buf = (uint8_t*)buf + len; + } + pipe->remaining = rem - len; + regs->TXCSRL = USB_TXCSRL1_TXRDY; + return false; +} + +static bool pipe_xfer_in(uint_fast8_t pipenum) +{ + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][0]; + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + + TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY); + + const unsigned mps = regs->RXMAXP; + const unsigned rem = pipe->remaining; + const unsigned vld = regs->RXCOUNT; + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0->FIFO0_WORD + pipenum, len); + pipe->buf = buf + len; + pipe->remaining = rem - len; + } + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return NULL != buf; + } + regs->RXCSRL = USB_RXCSRL1_REQPKT; + return false; +} + +static bool edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + unsigned const pipenum = find_pipe(dev_addr, ep_addr); + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][dir_tx]; + pipe->buf = buffer; + pipe->length = buflen; + pipe->remaining = buflen; + if (dir_tx) { + pipe_xfer_out(pipenum); + } else { + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + regs->RXCSRL = USB_RXCSRL1_REQPKT; + } + return true; +} + +static void process_ep0(uint8_t rhport) +{ + (void)rhport; + + uint_fast8_t csrl = USB0->CSRL0; + // TU_LOG1(" EP0 CSRL = %x\n", csrl); + + unsigned const dev_addr = USB0->TXFUNCADDR0; + unsigned const req = _hcd.bmRequestType; + if (csrl & (USB_CSRL0_ERROR | USB_CSRL0_NAKTO | USB_CSRL0_STALLED)) { + /* No response / NAK timed out / Stall received */ + if (csrl & (USB_CSRL0_RXRDY | USB_CSRL0_TXRDY)) + USB0->CSRH0 = USB_CSRH0_FLUSH; + USB0->CSRL0 = 0; + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + uint8_t result = (csrl & USB_CSRL0_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + if (REQUEST_TYPE_INVALID == req) { /* SETUP */ + uint8_t const ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } else if (csrl & USB_CSRL0_STATUS) { /* STATUS */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_OUT): tu_edpt_addr(0, TUSB_DIR_IN); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } else { /* DATA */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_IN): tu_edpt_addr(0, TUSB_DIR_OUT); + hcd_event_xfer_complete(dev_addr, ep_addr, + _hcd.pipe0.length - _hcd.pipe0.remaining, + result, true); + } + return; + } + if (csrl & USB_CSRL0_STATUS) { + /* STATUS IN */ + TU_ASSERT(USB_CSRL0_RXRDY == (csrl & USB_CSRL0_RXRDY),); + TU_ASSERT(0 == USB0->COUNT0,); + USB0->CSRH0 = USB_CSRH0_FLUSH; + USB0->CSRL0 = 0; + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_IN), + 0, XFER_RESULT_SUCCESS, true); + return; + } + if (csrl & USB_CSRL0_RXRDY) { + /* DATA IN */ + TU_ASSERT(REQUEST_TYPE_INVALID != req,); + TU_ASSERT(_hcd.pipe0.buf,); + if (edpt0_xfer_in()) { + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_IN), + _hcd.pipe0.length - _hcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + return; + } + + /* When CSRL0 is zero, it means that completion of sending a any length packet. */ + if (!_hcd.pipe0.buf) { + /* STATUS OUT */ + TU_ASSERT(REQUEST_TYPE_INVALID != req,); + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + /* EP address is the reverse direction of DATA stage */ + uint8_t const ep_addr = tu_edpt_dir(req) ? + tu_edpt_addr(0, TUSB_DIR_OUT): tu_edpt_addr(0, TUSB_DIR_IN); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); + return; + } + if (REQUEST_TYPE_INVALID == req) { + /* SETUP */ + _hcd.bmRequestType = *(uint8_t*)_hcd.pipe0.buf; + _hcd.pipe0.buf = NULL; + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_OUT), + 8, XFER_RESULT_SUCCESS, true); + return; + } + + /* DATA OUT */ + if (edpt0_xfer_out()) { + hcd_event_xfer_complete(dev_addr, tu_edpt_addr(0, TUSB_DIR_OUT), + _hcd.pipe0.length - _hcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_pipe_tx(uint8_t rhport, uint_fast8_t pipenum) +{ + (void)rhport; + bool completed; + uint8_t result; + + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + unsigned const csrl = regs->TXCSRL; + // TU_LOG1(" TXCSRL%d = %x\n", pipenum, csrl); + if (csrl & (USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) { + if (csrl & USB_TXCSRL1_TXRDY) + regs->TXCSRL = (csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR); + completed = true; + result = (csrl & USB_TXCSRL1_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + } else { + completed = pipe_xfer_out(pipenum); + result = XFER_RESULT_SUCCESS; + } + if (completed) { + pipe_addr_t *addr = &_hcd.addr[pipenum - 1][1]; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][1]; + hcd_event_xfer_complete(addr->dev, addr->ep, + pipe->length - pipe->remaining, + result, true); + } +} + +static void process_pipe_rx(uint8_t rhport, uint_fast8_t pipenum) +{ + (void)rhport; + bool completed; + uint8_t result; + + volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1); + unsigned const csrl = regs->RXCSRL; + // TU_LOG1(" RXCSRL%d = %x\n", pipenum, csrl); + if (csrl & (USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) { + if (csrl & USB_RXCSRL1_RXRDY) + regs->RXCSRL = (csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR); + completed = true; + result = (csrl & USB_RXCSRL1_STALLED) ? XFER_RESULT_STALLED: XFER_RESULT_FAILED; + } else { + completed = pipe_xfer_in(pipenum); + result = XFER_RESULT_SUCCESS; + } + if (completed) { + pipe_addr_t *addr = &_hcd.addr[pipenum - 1][0]; + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][0]; + hcd_event_xfer_complete(addr->dev, addr->ep, + pipe->length - pipe->remaining, + result, true); + } +} + +/*------------------------------------------------------------------ + * Host API + *------------------------------------------------------------------*/ + +bool hcd_init(uint8_t rhport) +{ + (void)rhport; + + NVIC_ClearPendingIRQ(USB0_IRQn); + _hcd.bmRequestType = REQUEST_TYPE_INVALID; + USB0->DEVCTL |= USB_DEVCTL_SESSION; + USB0->IE = USB_IE_DISCON | USB_IE_CONN | USB_IE_BABBLE | USB_IE_RESUME; + return true; +} + +void hcd_int_enable(uint8_t rhport) +{ + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) +{ + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} + +uint32_t hcd_frame_number(uint8_t rhport) +{ + (void)rhport; + /* The device must be reset at least once after connection + * in order to start the frame counter. */ + if (_hcd.need_reset) hcd_port_reset(rhport); + return USB0->FRAME; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +bool hcd_port_connect_status(uint8_t rhport) +{ + (void)rhport; + unsigned devctl = USB0->DEVCTL; + if (!(devctl & USB_DEVCTL_HOST)) return false; + if (devctl & (USB_DEVCTL_LSDEV | USB_DEVCTL_FSDEV)) return true; + return false; +} + +void hcd_port_reset(uint8_t rhport) +{ + (void)rhport; + USB0->POWER |= USB_POWER_HSENAB | USB_POWER_RESET; + unsigned cnt = SystemCoreClock / 1000 * 20; + while (cnt--) __NOP(); + USB0->POWER &= ~USB_POWER_RESET; + _hcd.need_reset = false; +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + (void)rhport; + unsigned devctl = USB0->DEVCTL; + if (devctl & USB_DEVCTL_LSDEV) return TUSB_SPEED_LOW; + if (!(devctl & USB_DEVCTL_FSDEV)) return TUSB_SPEED_INVALID; + if (USB0->POWER & USB_POWER_HSMODE) return TUSB_SPEED_HIGH; + return TUSB_SPEED_FULL; +} + +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + if (sizeof(_hcd.ctl_mps) <= dev_addr) return; + + unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + _hcd.ctl_mps[dev_addr] = 0; + if (!dev_addr) return; + + pipe_addr_t *p = &_hcd.addr[0][0]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i) { + for (unsigned j = 0; j < 2; ++j, ++p) { + if (dev_addr != p->dev) continue; + hw_addr_t volatile *fadr = (hw_addr_t volatile*)&USB0->TXFUNCADDR0 + i + 1; + hw_endpoint_t volatile *regs = edpt_regs(i); + USB0->EPIDX = i + 1; + if (j) { + USB0->TXIE &= ~TU_BIT(i + 1); + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + regs->TXMAXP = 0; + regs->TXTYPE = 0; + regs->TXINTERVAL = 0; + fadr->TXFUNCADDR = 0; + fadr->TXHUBADDR = 0; + fadr->TXHUBPORT = 0; + USB0->TXFIFOADD = 0; + USB0->TXFIFOSZ = 0; + } else { + USB0->RXIE &= ~TU_BIT(i + 1); + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + regs->RXMAXP = 0; + regs->RXTYPE = 0; + regs->RXINTERVAL = 0; + fadr->RXFUNCADDR = 0; + fadr->RXHUBADDR = 0; + fadr->RXHUBPORT = 0; + USB0->RXFIFOADD = 0; + USB0->RXFIFOSZ = 0; + } + p->dev = 0; + p->ep = 0; + pipe_state_t *pipe = &_hcd.pipe[i][j]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + } + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void)rhport; + pipe_write_packet((void*)(uintptr_t)setup_packet, &USB0->FIFO0_WORD, 8); + _hcd.pipe0.buf = (void*)(uintptr_t)setup_packet; + _hcd.pipe0.length = 8; + _hcd.pipe0.remaining = 0; + + hcd_devtree_info_t devtree; + hcd_devtree_get_info(dev_addr, &devtree); + switch (devtree.speed) { + default: return false; + case TUSB_SPEED_LOW: USB0->TYPE0 = USB_TYPE0_SPEED_LOW; break; + case TUSB_SPEED_FULL: USB0->TYPE0 = USB_TYPE0_SPEED_FULL; break; + case TUSB_SPEED_HIGH: USB0->TYPE0 = USB_TYPE0_SPEED_HIGH; break; + } + USB0->TXHUBADDR0 = devtree.hub_addr; + USB0->TXHUBPORT0 = devtree.hub_port; + USB0->TXFUNCADDR0 = dev_addr; + USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; + return true; +} + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void)rhport; + if (sizeof(_hcd.ctl_mps) <= dev_addr) return false; + unsigned const ep_addr = ep_desc->bEndpointAddress; + unsigned const epn = tu_edpt_number(ep_addr); + if (0 == epn) { + _hcd.ctl_mps[dev_addr] = ep_desc->wMaxPacketSize; + return true; + } + + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + /* Find a free pipe */ + unsigned pipenum = 0; + pipe_addr_t *p = &_hcd.addr[0][dir_tx]; + for (unsigned i = 0; i < sizeof(_hcd.addr)/sizeof(_hcd.addr[0]); ++i, p += 2) { + if (0 == p->ep) { + p->dev = dev_addr; + p->ep = ep_addr; + pipenum = i + 1; + break; + } + } + if (!pipenum) return false; + + unsigned const xfer = ep_desc->bmAttributes.xfer; + unsigned const mps = tu_edpt_packet_size(ep_desc); + + pipe_state_t *pipe = &_hcd.pipe[pipenum - 1][dir_tx]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + + uint8_t pipe_type = 0; + hcd_devtree_info_t devtree; + hcd_devtree_get_info(dev_addr, &devtree); + switch (devtree.speed) { + default: return false; + case TUSB_SPEED_LOW: pipe_type |= USB_TXTYPE1_SPEED_LOW; break; + case TUSB_SPEED_FULL: pipe_type |= USB_TXTYPE1_SPEED_FULL; break; + case TUSB_SPEED_HIGH: pipe_type |= USB_TXTYPE1_SPEED_HIGH; break; + } + switch (xfer) { + default: return false; + case TUSB_XFER_BULK: pipe_type |= USB_TXTYPE1_PROTO_BULK; break; + case TUSB_XFER_INTERRUPT: pipe_type |= USB_TXTYPE1_PROTO_INT; break; + case TUSB_XFER_ISOCHRONOUS: pipe_type |= USB_TXTYPE1_PROTO_ISOC; break; + } + + hw_addr_t volatile *fadr = (hw_addr_t volatile*)&USB0->TXFUNCADDR0 + pipenum; + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + if (dir_tx) { + fadr->TXFUNCADDR = dev_addr; + fadr->TXHUBADDR = devtree.hub_addr; + fadr->TXHUBPORT = devtree.hub_port; + regs->TXMAXP = mps; + regs->TXTYPE = pipe_type | epn; + regs->TXINTERVAL = ep_desc->bInterval; + if (regs->TXCSRL & USB_TXCSRL1_TXRDY) + regs->TXCSRL = USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH; + else + regs->TXCSRL = USB_TXCSRL1_CLRDT; + USB0->TXIE |= TU_BIT(pipenum); + } else { + fadr->RXFUNCADDR = dev_addr; + fadr->RXHUBADDR = devtree.hub_addr; + fadr->RXHUBPORT = devtree.hub_port; + regs->RXMAXP = mps; + regs->RXTYPE = pipe_type | epn; + regs->RXINTERVAL = ep_desc->bInterval; + if (regs->RXCSRL & USB_RXCSRL1_RXRDY) + regs->RXCSRL = USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + USB0->RXIE |= TU_BIT(pipenum); + } + + /* Setup FIFO */ + int size_in_log2_minus3 = 28 - TU_MIN(28, __CLZ((uint32_t)mps)); + if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3; + unsigned addr = find_free_memory(size_in_log2_minus3); + TU_ASSERT(addr); + + USB0->EPIDX = pipenum; + if (dir_tx) { + USB0->TXFIFOADD = addr; + USB0->TXFIFOSZ = size_in_log2_minus3; + } else { + USB0->RXFIFOADD = addr; + USB0->RXFIFOSZ = size_in_log2_minus3; + } + return true; +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) +{ + (void)rhport; + bool ret = false; + if (0 == tu_edpt_number(ep_addr)) { + ret = edpt0_xfer(rhport, dev_addr, ep_addr, buffer, buflen); + } else { + ret = edpt_xfer(rhport, dev_addr, ep_addr, buffer, buflen); + } + return ret; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + unsigned const pipenum = find_pipe(dev_addr, ep_addr); + if (!pipenum) return false; + hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); + unsigned const dir_tx = tu_edpt_dir(ep_addr) ? 0: 1; + if (dir_tx) + regs->TXCSRL = USB_TXCSRL1_CLRDT; + else + regs->RXCSRL = USB_RXCSRL1_CLRDT; + return true; +} + +/*------------------------------------------------------------------- + * ISR + *-------------------------------------------------------------------*/ +void hcd_int_handler(uint8_t rhport) +{ + uint_fast8_t is, txis, rxis; + + is = USB0->IS; /* read and clear interrupt status */ + txis = USB0->TXIS; /* read and clear interrupt status */ + rxis = USB0->RXIS; /* read and clear interrupt status */ + // TU_LOG1("D%2x T%2x R%2x\n", is, txis, rxis); + + is &= USB0->IE; /* Clear disabled interrupts */ + if (is & USB_IS_RESUME) { + } + if (is & USB_IS_CONN) { + _hcd.need_reset = true; + hcd_event_device_attach(rhport, true); + } + if (is & USB_IS_DISCON) { + hcd_event_device_remove(rhport, true); + } + if (is & USB_IS_BABBLE) { + } + txis &= USB0->TXIE; /* Clear disabled interrupts */ + if (txis & USB_TXIE_EP0) { + process_ep0(rhport); + txis &= ~TU_BIT(0); + } + while (txis) { + unsigned const num = __builtin_ctz(txis); + process_pipe_tx(rhport, num); + txis &= ~TU_BIT(num); + } + rxis &= USB0->RXIE; /* Clear disabled interrupts */ + while (rxis) { + unsigned const num = __builtin_ctz(rxis); + process_pipe_rx(rhport, num); + rxis &= ~TU_BIT(num); + } +} + +#endif diff --git a/src/portable/mentor/musb/musb_msp432e.h b/src/portable/mentor/musb/musb_msp432e.h new file mode 100644 index 000000000..fce21de88 --- /dev/null +++ b/src/portable/mentor/musb/musb_msp432e.h @@ -0,0 +1,40 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MUSB_MSP432E_H_ +#define _TUSB_MUSB_MSP432E_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "msp.h" + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/mentor/musb/musb_tm4c.h b/src/portable/mentor/musb/musb_tm4c.h new file mode 100644 index 000000000..65a1751b0 --- /dev/null +++ b/src/portable/mentor/musb/musb_tm4c.h @@ -0,0 +1,45 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MUSB_TM4C_H_ +#define _TUSB_MUSB_TM4C_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#if CFG_TUSB_MCU == OPT_MCU_TM4C123 + #include "TM4C123.h" +//#elif CFG_TUSB_MCU == OPT_MCU_TM4C129 +#else + #error "Unsupported MCUs" +#endif + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/mentor/musb/musb_type.h b/src/portable/mentor/musb/musb_type.h new file mode 100644 index 000000000..8f83305a5 --- /dev/null +++ b/src/portable/mentor/musb/musb_type.h @@ -0,0 +1,2624 @@ +/****************************************************************************** +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*******************************************************************************/ + +#ifndef _TUSB_MUSB_TYPE_H_ +#define _TUSB_MUSB_TYPE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FADDR register. +// +//***************************************************************************** +#define USB_FADDR_M 0x0000007F // Function Address +#define USB_FADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_POWER register. +// +//***************************************************************************** +#define USB_POWER_ISOUP 0x00000080 // Isochronous Update +#define USB_POWER_SOFTCONN 0x00000040 // Soft Connect/Disconnect +#define USB_POWER_HSENAB 0x00000020 // High Speed Enable +#define USB_POWER_HSMODE 0x00000010 // High Speed Enable +#define USB_POWER_RESET 0x00000008 // RESET Signaling +#define USB_POWER_RESUME 0x00000004 // RESUME Signaling +#define USB_POWER_SUSPEND 0x00000002 // SUSPEND Mode +#define USB_POWER_PWRDNPHY 0x00000001 // Power Down PHY + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXIS register. +// +//***************************************************************************** +#define USB_TXIS_EP7 0x00000080 // TX Endpoint 7 Interrupt +#define USB_TXIS_EP6 0x00000040 // TX Endpoint 6 Interrupt +#define USB_TXIS_EP5 0x00000020 // TX Endpoint 5 Interrupt +#define USB_TXIS_EP4 0x00000010 // TX Endpoint 4 Interrupt +#define USB_TXIS_EP3 0x00000008 // TX Endpoint 3 Interrupt +#define USB_TXIS_EP2 0x00000004 // TX Endpoint 2 Interrupt +#define USB_TXIS_EP1 0x00000002 // TX Endpoint 1 Interrupt +#define USB_TXIS_EP0 0x00000001 // TX and RX Endpoint 0 Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXIS register. +// +//***************************************************************************** +#define USB_RXIS_EP7 0x00000080 // RX Endpoint 7 Interrupt +#define USB_RXIS_EP6 0x00000040 // RX Endpoint 6 Interrupt +#define USB_RXIS_EP5 0x00000020 // RX Endpoint 5 Interrupt +#define USB_RXIS_EP4 0x00000010 // RX Endpoint 4 Interrupt +#define USB_RXIS_EP3 0x00000008 // RX Endpoint 3 Interrupt +#define USB_RXIS_EP2 0x00000004 // RX Endpoint 2 Interrupt +#define USB_RXIS_EP1 0x00000002 // RX Endpoint 1 Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXIE register. +// +//***************************************************************************** +#define USB_TXIE_EP7 0x00000080 // TX Endpoint 7 Interrupt Enable +#define USB_TXIE_EP6 0x00000040 // TX Endpoint 6 Interrupt Enable +#define USB_TXIE_EP5 0x00000020 // TX Endpoint 5 Interrupt Enable +#define USB_TXIE_EP4 0x00000010 // TX Endpoint 4 Interrupt Enable +#define USB_TXIE_EP3 0x00000008 // TX Endpoint 3 Interrupt Enable +#define USB_TXIE_EP2 0x00000004 // TX Endpoint 2 Interrupt Enable +#define USB_TXIE_EP1 0x00000002 // TX Endpoint 1 Interrupt Enable +#define USB_TXIE_EP0 0x00000001 // TX and RX Endpoint 0 Interrupt + // Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXIE register. +// +//***************************************************************************** +#define USB_RXIE_EP7 0x00000080 // RX Endpoint 7 Interrupt Enable +#define USB_RXIE_EP6 0x00000040 // RX Endpoint 6 Interrupt Enable +#define USB_RXIE_EP5 0x00000020 // RX Endpoint 5 Interrupt Enable +#define USB_RXIE_EP4 0x00000010 // RX Endpoint 4 Interrupt Enable +#define USB_RXIE_EP3 0x00000008 // RX Endpoint 3 Interrupt Enable +#define USB_RXIE_EP2 0x00000004 // RX Endpoint 2 Interrupt Enable +#define USB_RXIE_EP1 0x00000002 // RX Endpoint 1 Interrupt Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_IS register. +// +//***************************************************************************** +#define USB_IS_VBUSERR 0x00000080 // VBUS Error (OTG only) +#define USB_IS_SESREQ 0x00000040 // SESSION REQUEST (OTG only) +#define USB_IS_DISCON 0x00000020 // Session Disconnect (OTG only) +#define USB_IS_CONN 0x00000010 // Session Connect +#define USB_IS_SOF 0x00000008 // Start of Frame +#define USB_IS_BABBLE 0x00000004 // Babble Detected +#define USB_IS_RESET 0x00000004 // RESET Signaling Detected +#define USB_IS_RESUME 0x00000002 // RESUME Signaling Detected +#define USB_IS_SUSPEND 0x00000001 // SUSPEND Signaling Detected + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_IE register. +// +//***************************************************************************** +#define USB_IE_VBUSERR 0x00000080 // Enable VBUS Error Interrupt (OTG + // only) +#define USB_IE_SESREQ 0x00000040 // Enable Session Request (OTG + // only) +#define USB_IE_DISCON 0x00000020 // Enable Disconnect Interrupt +#define USB_IE_CONN 0x00000010 // Enable Connect Interrupt +#define USB_IE_SOF 0x00000008 // Enable Start-of-Frame Interrupt +#define USB_IE_BABBLE 0x00000004 // Enable Babble Interrupt +#define USB_IE_RESET 0x00000004 // Enable RESET Interrupt +#define USB_IE_RESUME 0x00000002 // Enable RESUME Interrupt +#define USB_IE_SUSPND 0x00000001 // Enable SUSPEND Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FRAME register. +// +//***************************************************************************** +#define USB_FRAME_M 0x000007FF // Frame Number +#define USB_FRAME_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPIDX register. +// +//***************************************************************************** +#define USB_EPIDX_EPIDX_M 0x0000000F // Endpoint Index +#define USB_EPIDX_EPIDX_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TEST register. +// +//***************************************************************************** +#define USB_TEST_FORCEH 0x00000080 // Force Host Mode +#define USB_TEST_FIFOACC 0x00000040 // FIFO Access +#define USB_TEST_FORCEFS 0x00000020 // Force Full-Speed Mode +#define USB_TEST_FORCEHS 0x00000010 // Force High-Speed Mode +#define USB_TEST_TESTPKT 0x00000008 // Test Packet Mode Enable +#define USB_TEST_TESTK 0x00000004 // Test_K Mode Enable +#define USB_TEST_TESTJ 0x00000002 // Test_J Mode Enable +#define USB_TEST_TESTSE0NAK 0x00000001 // Test_SE0_NAK Test Mode Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO0 register. +// +//***************************************************************************** +#define USB_FIFO0_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO0_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO1 register. +// +//***************************************************************************** +#define USB_FIFO1_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO1_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO2 register. +// +//***************************************************************************** +#define USB_FIFO2_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO2_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO3 register. +// +//***************************************************************************** +#define USB_FIFO3_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO3_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO4 register. +// +//***************************************************************************** +#define USB_FIFO4_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO4_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO5 register. +// +//***************************************************************************** +#define USB_FIFO5_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO5_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO6 register. +// +//***************************************************************************** +#define USB_FIFO6_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO6_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FIFO7 register. +// +//***************************************************************************** +#define USB_FIFO7_EPDATA_M 0xFFFFFFFF // Endpoint Data +#define USB_FIFO7_EPDATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DEVCTL register. +// +//***************************************************************************** +#define USB_DEVCTL_DEV 0x00000080 // Device Mode (OTG only) +#define USB_DEVCTL_FSDEV 0x00000040 // Full-Speed Device Detected +#define USB_DEVCTL_LSDEV 0x00000020 // Low-Speed Device Detected +#define USB_DEVCTL_VBUS_M 0x00000018 // VBUS Level (OTG only) +#define USB_DEVCTL_VBUS_NONE 0x00000000 // Below SessionEnd +#define USB_DEVCTL_VBUS_SEND 0x00000008 // Above SessionEnd, below AValid +#define USB_DEVCTL_VBUS_AVALID 0x00000010 // Above AValid, below VBUSValid +#define USB_DEVCTL_VBUS_VALID 0x00000018 // Above VBUSValid +#define USB_DEVCTL_HOST 0x00000004 // Host Mode +#define USB_DEVCTL_HOSTREQ 0x00000002 // Host Request (OTG only) +#define USB_DEVCTL_SESSION 0x00000001 // Session Start/End (OTG only) + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CCONF register. +// +//***************************************************************************** +#define USB_CCONF_TXEDMA 0x00000002 // TX Early DMA Enable +#define USB_CCONF_RXEDMA 0x00000001 // TX Early DMA Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFIFOSZ register. +// +//***************************************************************************** +#define USB_TXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support +#define USB_TXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size +#define USB_TXFIFOSZ_SIZE_8 0x00000000 // 8 +#define USB_TXFIFOSZ_SIZE_16 0x00000001 // 16 +#define USB_TXFIFOSZ_SIZE_32 0x00000002 // 32 +#define USB_TXFIFOSZ_SIZE_64 0x00000003 // 64 +#define USB_TXFIFOSZ_SIZE_128 0x00000004 // 128 +#define USB_TXFIFOSZ_SIZE_256 0x00000005 // 256 +#define USB_TXFIFOSZ_SIZE_512 0x00000006 // 512 +#define USB_TXFIFOSZ_SIZE_1024 0x00000007 // 1024 +#define USB_TXFIFOSZ_SIZE_2048 0x00000008 // 2048 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFIFOSZ register. +// +//***************************************************************************** +#define USB_RXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support +#define USB_RXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size +#define USB_RXFIFOSZ_SIZE_8 0x00000000 // 8 +#define USB_RXFIFOSZ_SIZE_16 0x00000001 // 16 +#define USB_RXFIFOSZ_SIZE_32 0x00000002 // 32 +#define USB_RXFIFOSZ_SIZE_64 0x00000003 // 64 +#define USB_RXFIFOSZ_SIZE_128 0x00000004 // 128 +#define USB_RXFIFOSZ_SIZE_256 0x00000005 // 256 +#define USB_RXFIFOSZ_SIZE_512 0x00000006 // 512 +#define USB_RXFIFOSZ_SIZE_1024 0x00000007 // 1024 +#define USB_RXFIFOSZ_SIZE_2048 0x00000008 // 2048 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFIFOADD +// register. +// +//***************************************************************************** +#define USB_TXFIFOADD_ADDR_M 0x000001FF // Transmit/Receive Start Address +#define USB_TXFIFOADD_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFIFOADD +// register. +// +//***************************************************************************** +#define USB_RXFIFOADD_ADDR_M 0x000001FF // Transmit/Receive Start Address +#define USB_RXFIFOADD_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_ULPIVBUSCTL +// register. +// +//***************************************************************************** +#define USB_ULPIVBUSCTL_USEEXTVBUSIND \ + 0x00000002 // Use External VBUS Indicator +#define USB_ULPIVBUSCTL_USEEXTVBUS \ + 0x00000001 // Use External VBUS + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_ULPIREGDATA +// register. +// +//***************************************************************************** +#define USB_ULPIREGDATA_REGDATA_M \ + 0x000000FF // Register Data +#define USB_ULPIREGDATA_REGDATA_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_ULPIREGADDR +// register. +// +//***************************************************************************** +#define USB_ULPIREGADDR_ADDR_M 0x000000FF // Register Address +#define USB_ULPIREGADDR_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_ULPIREGCTL +// register. +// +//***************************************************************************** +#define USB_ULPIREGCTL_RDWR 0x00000004 // Read/Write Control +#define USB_ULPIREGCTL_REGCMPLT 0x00000002 // Register Access Complete +#define USB_ULPIREGCTL_REGACC 0x00000001 // Initiate Register Access + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPINFO register. +// +//***************************************************************************** +#define USB_EPINFO_RXEP_M 0x000000F0 // RX Endpoints +#define USB_EPINFO_TXEP_M 0x0000000F // TX Endpoints +#define USB_EPINFO_RXEP_S 4 +#define USB_EPINFO_TXEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RAMINFO register. +// +//***************************************************************************** +#define USB_RAMINFO_DMACHAN_M 0x000000F0 // DMA Channels +#define USB_RAMINFO_RAMBITS_M 0x0000000F // RAM Address Bus Width +#define USB_RAMINFO_DMACHAN_S 4 +#define USB_RAMINFO_RAMBITS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CONTIM register. +// +//***************************************************************************** +#define USB_CONTIM_WTCON_M 0x000000F0 // Connect Wait +#define USB_CONTIM_WTID_M 0x0000000F // Wait ID +#define USB_CONTIM_WTCON_S 4 +#define USB_CONTIM_WTID_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_VPLEN register. +// +//***************************************************************************** +#define USB_VPLEN_VPLEN_M 0x000000FF // VBUS Pulse Length +#define USB_VPLEN_VPLEN_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_HSEOF register. +// +//***************************************************************************** +#define USB_HSEOF_HSEOFG_M 0x000000FF // HIgh-Speed End-of-Frame Gap +#define USB_HSEOF_HSEOFG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_FSEOF register. +// +//***************************************************************************** +#define USB_FSEOF_FSEOFG_M 0x000000FF // Full-Speed End-of-Frame Gap +#define USB_FSEOF_FSEOFG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LSEOF register. +// +//***************************************************************************** +#define USB_LSEOF_LSEOFG_M 0x000000FF // Low-Speed End-of-Frame Gap +#define USB_LSEOF_LSEOFG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR0 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR0_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR0_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR0 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR0_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR0_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT0 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT0_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT0_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR1 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR1_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR1 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR1_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT1 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT1_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT1_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR1 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR1_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR1 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR1_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT1 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT1_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT1_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR2 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR2_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR2 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR2_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT2 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT2_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT2_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR2 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR2_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR2 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR2_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT2 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT2_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT2_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR3 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR3_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR3 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR3_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT3 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT3_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT3_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR3 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR3_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR3 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR3_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT3 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT3_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT3_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR4 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR4_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR4 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR4_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT4 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT4_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT4_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR4 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR4_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR4 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR4_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT4 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT4_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT4_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR5 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR5_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR5_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR5 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR5_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR5_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT5 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT5_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT5_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR5 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR5_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR5_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR5 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR5_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR5_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT5 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT5_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT5_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR6 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR6_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR6_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR6 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR6_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR6_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT6 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT6_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT6_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR6 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR6_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR6_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR6 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR6_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR6_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT6 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT6_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT6_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXFUNCADDR7 +// register. +// +//***************************************************************************** +#define USB_TXFUNCADDR7_ADDR_M 0x0000007F // Device Address +#define USB_TXFUNCADDR7_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBADDR7 +// register. +// +//***************************************************************************** +#define USB_TXHUBADDR7_ADDR_M 0x0000007F // Hub Address +#define USB_TXHUBADDR7_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXHUBPORT7 +// register. +// +//***************************************************************************** +#define USB_TXHUBPORT7_PORT_M 0x0000007F // Hub Port +#define USB_TXHUBPORT7_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXFUNCADDR7 +// register. +// +//***************************************************************************** +#define USB_RXFUNCADDR7_ADDR_M 0x0000007F // Device Address +#define USB_RXFUNCADDR7_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBADDR7 +// register. +// +//***************************************************************************** +#define USB_RXHUBADDR7_ADDR_M 0x0000007F // Hub Address +#define USB_RXHUBADDR7_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXHUBPORT7 +// register. +// +//***************************************************************************** +#define USB_RXHUBPORT7_PORT_M 0x0000007F // Hub Port +#define USB_RXHUBPORT7_PORT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CSRL0 register. +// +//***************************************************************************** +#define USB_CSRL0_NAKTO 0x00000080 // NAK Timeout +#define USB_CSRL0_SETENDC 0x00000080 // Setup End Clear +#define USB_CSRL0_STATUS 0x00000040 // STATUS Packet +#define USB_CSRL0_RXRDYC 0x00000040 // RXRDY Clear +#define USB_CSRL0_REQPKT 0x00000020 // Request Packet +#define USB_CSRL0_STALL 0x00000020 // Send Stall +#define USB_CSRL0_SETEND 0x00000010 // Setup End +#define USB_CSRL0_ERROR 0x00000010 // Error +#define USB_CSRL0_DATAEND 0x00000008 // Data End +#define USB_CSRL0_SETUP 0x00000008 // Setup Packet +#define USB_CSRL0_STALLED 0x00000004 // Endpoint Stalled +#define USB_CSRL0_TXRDY 0x00000002 // Transmit Packet Ready +#define USB_CSRL0_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CSRH0 register. +// +//***************************************************************************** +#define USB_CSRH0_DISPING 0x00000008 // PING Disable +#define USB_CSRH0_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_CSRH0_DT 0x00000002 // Data Toggle +#define USB_CSRH0_FLUSH 0x00000001 // Flush FIFO + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_COUNT0 register. +// +//***************************************************************************** +#define USB_COUNT0_COUNT_M 0x0000007F // FIFO Count +#define USB_COUNT0_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TYPE0 register. +// +//***************************************************************************** +#define USB_TYPE0_SPEED_M 0x000000C0 // Operating Speed +#define USB_TYPE0_SPEED_HIGH 0x00000040 // High +#define USB_TYPE0_SPEED_FULL 0x00000080 // Full +#define USB_TYPE0_SPEED_LOW 0x000000C0 // Low + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_NAKLMT register. +// +//***************************************************************************** +#define USB_NAKLMT_NAKLMT_M 0x0000001F // EP0 NAK Limit +#define USB_NAKLMT_NAKLMT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP1 register. +// +//***************************************************************************** +#define USB_TXMAXP1_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP1_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL1 register. +// +//***************************************************************************** +#define USB_TXCSRL1_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL1_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL1_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL1_STALL 0x00000010 // Send STALL +#define USB_TXCSRL1_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL1_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL1_ERROR 0x00000004 // Error +#define USB_TXCSRL1_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL1_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL1_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH1 register. +// +//***************************************************************************** +#define USB_TXCSRH1_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH1_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH1_MODE 0x00000020 // Mode +#define USB_TXCSRH1_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH1_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH1_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH1_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH1_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP1 register. +// +//***************************************************************************** +#define USB_RXMAXP1_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP1_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL1 register. +// +//***************************************************************************** +#define USB_RXCSRL1_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL1_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL1_STALL 0x00000020 // Send STALL +#define USB_RXCSRL1_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL1_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL1_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL1_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL1_OVER 0x00000004 // Overrun +#define USB_RXCSRL1_ERROR 0x00000004 // Error +#define USB_RXCSRL1_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL1_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH1 register. +// +//***************************************************************************** +#define USB_RXCSRH1_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH1_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH1_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH1_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH1_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH1_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH1_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH1_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH1_DT 0x00000002 // Data Toggle +#define USB_RXCSRH1_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT1 register. +// +//***************************************************************************** +#define USB_RXCOUNT1_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT1_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE1 register. +// +//***************************************************************************** +#define USB_TXTYPE1_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE1_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE1_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE1_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE1_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE1_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE1_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE1_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE1_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE1_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE1_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE1_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL1 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL1_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL1_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL1_TXPOLL_S \ + 0 +#define USB_TXINTERVAL1_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE1 register. +// +//***************************************************************************** +#define USB_RXTYPE1_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE1_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE1_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE1_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE1_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE1_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE1_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE1_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE1_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE1_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE1_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE1_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL1 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL1_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL1_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL1_TXPOLL_S \ + 0 +#define USB_RXINTERVAL1_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP2 register. +// +//***************************************************************************** +#define USB_TXMAXP2_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP2_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL2 register. +// +//***************************************************************************** +#define USB_TXCSRL2_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL2_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL2_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL2_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL2_STALL 0x00000010 // Send STALL +#define USB_TXCSRL2_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL2_ERROR 0x00000004 // Error +#define USB_TXCSRL2_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL2_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL2_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH2 register. +// +//***************************************************************************** +#define USB_TXCSRH2_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH2_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH2_MODE 0x00000020 // Mode +#define USB_TXCSRH2_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH2_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH2_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH2_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH2_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP2 register. +// +//***************************************************************************** +#define USB_RXMAXP2_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP2_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL2 register. +// +//***************************************************************************** +#define USB_RXCSRL2_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL2_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL2_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL2_STALL 0x00000020 // Send STALL +#define USB_RXCSRL2_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL2_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL2_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL2_ERROR 0x00000004 // Error +#define USB_RXCSRL2_OVER 0x00000004 // Overrun +#define USB_RXCSRL2_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL2_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH2 register. +// +//***************************************************************************** +#define USB_RXCSRH2_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH2_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH2_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH2_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH2_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH2_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH2_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH2_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH2_DT 0x00000002 // Data Toggle +#define USB_RXCSRH2_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT2 register. +// +//***************************************************************************** +#define USB_RXCOUNT2_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT2_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE2 register. +// +//***************************************************************************** +#define USB_TXTYPE2_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE2_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE2_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE2_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE2_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE2_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE2_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE2_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE2_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE2_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE2_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE2_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL2 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL2_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL2_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL2_NAKLMT_S \ + 0 +#define USB_TXINTERVAL2_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE2 register. +// +//***************************************************************************** +#define USB_RXTYPE2_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE2_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE2_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE2_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE2_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE2_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE2_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE2_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE2_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE2_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE2_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE2_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL2 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL2_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL2_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL2_TXPOLL_S \ + 0 +#define USB_RXINTERVAL2_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP3 register. +// +//***************************************************************************** +#define USB_TXMAXP3_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP3_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL3 register. +// +//***************************************************************************** +#define USB_TXCSRL3_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL3_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL3_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL3_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL3_STALL 0x00000010 // Send STALL +#define USB_TXCSRL3_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL3_ERROR 0x00000004 // Error +#define USB_TXCSRL3_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL3_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL3_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH3 register. +// +//***************************************************************************** +#define USB_TXCSRH3_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH3_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH3_MODE 0x00000020 // Mode +#define USB_TXCSRH3_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH3_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH3_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH3_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH3_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP3 register. +// +//***************************************************************************** +#define USB_RXMAXP3_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP3_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL3 register. +// +//***************************************************************************** +#define USB_RXCSRL3_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL3_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL3_STALL 0x00000020 // Send STALL +#define USB_RXCSRL3_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL3_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL3_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL3_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL3_ERROR 0x00000004 // Error +#define USB_RXCSRL3_OVER 0x00000004 // Overrun +#define USB_RXCSRL3_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL3_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH3 register. +// +//***************************************************************************** +#define USB_RXCSRH3_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH3_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH3_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH3_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH3_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH3_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH3_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH3_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH3_DT 0x00000002 // Data Toggle +#define USB_RXCSRH3_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT3 register. +// +//***************************************************************************** +#define USB_RXCOUNT3_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT3_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE3 register. +// +//***************************************************************************** +#define USB_TXTYPE3_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE3_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE3_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE3_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE3_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE3_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE3_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE3_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE3_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE3_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE3_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE3_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL3 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL3_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL3_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL3_TXPOLL_S \ + 0 +#define USB_TXINTERVAL3_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE3 register. +// +//***************************************************************************** +#define USB_RXTYPE3_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE3_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE3_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE3_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE3_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE3_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE3_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE3_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE3_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE3_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE3_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE3_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL3 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL3_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL3_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL3_TXPOLL_S \ + 0 +#define USB_RXINTERVAL3_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP4 register. +// +//***************************************************************************** +#define USB_TXMAXP4_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP4_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL4 register. +// +//***************************************************************************** +#define USB_TXCSRL4_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL4_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL4_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL4_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL4_STALL 0x00000010 // Send STALL +#define USB_TXCSRL4_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL4_ERROR 0x00000004 // Error +#define USB_TXCSRL4_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL4_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL4_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH4 register. +// +//***************************************************************************** +#define USB_TXCSRH4_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH4_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH4_MODE 0x00000020 // Mode +#define USB_TXCSRH4_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH4_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH4_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH4_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH4_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP4 register. +// +//***************************************************************************** +#define USB_RXMAXP4_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP4_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL4 register. +// +//***************************************************************************** +#define USB_RXCSRL4_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL4_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL4_STALL 0x00000020 // Send STALL +#define USB_RXCSRL4_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL4_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL4_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL4_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL4_OVER 0x00000004 // Overrun +#define USB_RXCSRL4_ERROR 0x00000004 // Error +#define USB_RXCSRL4_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL4_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH4 register. +// +//***************************************************************************** +#define USB_RXCSRH4_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH4_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH4_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH4_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH4_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH4_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH4_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH4_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH4_DT 0x00000002 // Data Toggle +#define USB_RXCSRH4_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT4 register. +// +//***************************************************************************** +#define USB_RXCOUNT4_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT4_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE4 register. +// +//***************************************************************************** +#define USB_TXTYPE4_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE4_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE4_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE4_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE4_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE4_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE4_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE4_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE4_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE4_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE4_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE4_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL4 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL4_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL4_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL4_NAKLMT_S \ + 0 +#define USB_TXINTERVAL4_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE4 register. +// +//***************************************************************************** +#define USB_RXTYPE4_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE4_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE4_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE4_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE4_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE4_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE4_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE4_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE4_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE4_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE4_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE4_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL4 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL4_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL4_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL4_NAKLMT_S \ + 0 +#define USB_RXINTERVAL4_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP5 register. +// +//***************************************************************************** +#define USB_TXMAXP5_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP5_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL5 register. +// +//***************************************************************************** +#define USB_TXCSRL5_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL5_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL5_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL5_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL5_STALL 0x00000010 // Send STALL +#define USB_TXCSRL5_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL5_ERROR 0x00000004 // Error +#define USB_TXCSRL5_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL5_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL5_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH5 register. +// +//***************************************************************************** +#define USB_TXCSRH5_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH5_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH5_MODE 0x00000020 // Mode +#define USB_TXCSRH5_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH5_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH5_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH5_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH5_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP5 register. +// +//***************************************************************************** +#define USB_RXMAXP5_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP5_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL5 register. +// +//***************************************************************************** +#define USB_RXCSRL5_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL5_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL5_STALL 0x00000020 // Send STALL +#define USB_RXCSRL5_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL5_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL5_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL5_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL5_ERROR 0x00000004 // Error +#define USB_RXCSRL5_OVER 0x00000004 // Overrun +#define USB_RXCSRL5_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL5_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH5 register. +// +//***************************************************************************** +#define USB_RXCSRH5_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH5_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH5_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH5_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH5_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH5_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH5_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH5_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH5_DT 0x00000002 // Data Toggle +#define USB_RXCSRH5_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT5 register. +// +//***************************************************************************** +#define USB_RXCOUNT5_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT5_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE5 register. +// +//***************************************************************************** +#define USB_TXTYPE5_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE5_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE5_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE5_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE5_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE5_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE5_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE5_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE5_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE5_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE5_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE5_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL5 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL5_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL5_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL5_NAKLMT_S \ + 0 +#define USB_TXINTERVAL5_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE5 register. +// +//***************************************************************************** +#define USB_RXTYPE5_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE5_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE5_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE5_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE5_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE5_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE5_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE5_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE5_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE5_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE5_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE5_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL5 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL5_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL5_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL5_TXPOLL_S \ + 0 +#define USB_RXINTERVAL5_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP6 register. +// +//***************************************************************************** +#define USB_TXMAXP6_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP6_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL6 register. +// +//***************************************************************************** +#define USB_TXCSRL6_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL6_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL6_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL6_STALL 0x00000010 // Send STALL +#define USB_TXCSRL6_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL6_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL6_ERROR 0x00000004 // Error +#define USB_TXCSRL6_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL6_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL6_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH6 register. +// +//***************************************************************************** +#define USB_TXCSRH6_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH6_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH6_MODE 0x00000020 // Mode +#define USB_TXCSRH6_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH6_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH6_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH6_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH6_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP6 register. +// +//***************************************************************************** +#define USB_RXMAXP6_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP6_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL6 register. +// +//***************************************************************************** +#define USB_RXCSRL6_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL6_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL6_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL6_STALL 0x00000020 // Send STALL +#define USB_RXCSRL6_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL6_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL6_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL6_ERROR 0x00000004 // Error +#define USB_RXCSRL6_OVER 0x00000004 // Overrun +#define USB_RXCSRL6_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL6_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH6 register. +// +//***************************************************************************** +#define USB_RXCSRH6_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH6_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH6_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH6_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH6_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH6_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH6_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH6_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH6_DT 0x00000002 // Data Toggle +#define USB_RXCSRH6_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT6 register. +// +//***************************************************************************** +#define USB_RXCOUNT6_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT6_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE6 register. +// +//***************************************************************************** +#define USB_TXTYPE6_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE6_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE6_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE6_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE6_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE6_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE6_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE6_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE6_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE6_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE6_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE6_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL6 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL6_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL6_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL6_TXPOLL_S \ + 0 +#define USB_TXINTERVAL6_NAKLMT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE6 register. +// +//***************************************************************************** +#define USB_RXTYPE6_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE6_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE6_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE6_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE6_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE6_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE6_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE6_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE6_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE6_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE6_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE6_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL6 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL6_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL6_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL6_NAKLMT_S \ + 0 +#define USB_RXINTERVAL6_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXMAXP7 register. +// +//***************************************************************************** +#define USB_TXMAXP7_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_TXMAXP7_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRL7 register. +// +//***************************************************************************** +#define USB_TXCSRL7_NAKTO 0x00000080 // NAK Timeout +#define USB_TXCSRL7_CLRDT 0x00000040 // Clear Data Toggle +#define USB_TXCSRL7_STALLED 0x00000020 // Endpoint Stalled +#define USB_TXCSRL7_STALL 0x00000010 // Send STALL +#define USB_TXCSRL7_SETUP 0x00000010 // Setup Packet +#define USB_TXCSRL7_FLUSH 0x00000008 // Flush FIFO +#define USB_TXCSRL7_ERROR 0x00000004 // Error +#define USB_TXCSRL7_UNDRN 0x00000004 // Underrun +#define USB_TXCSRL7_FIFONE 0x00000002 // FIFO Not Empty +#define USB_TXCSRL7_TXRDY 0x00000001 // Transmit Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXCSRH7 register. +// +//***************************************************************************** +#define USB_TXCSRH7_AUTOSET 0x00000080 // Auto Set +#define USB_TXCSRH7_ISO 0x00000040 // Isochronous Transfers +#define USB_TXCSRH7_MODE 0x00000020 // Mode +#define USB_TXCSRH7_DMAEN 0x00000010 // DMA Request Enable +#define USB_TXCSRH7_FDT 0x00000008 // Force Data Toggle +#define USB_TXCSRH7_DMAMOD 0x00000004 // DMA Request Mode +#define USB_TXCSRH7_DTWE 0x00000002 // Data Toggle Write Enable +#define USB_TXCSRH7_DT 0x00000001 // Data Toggle + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXMAXP7 register. +// +//***************************************************************************** +#define USB_RXMAXP7_MAXLOAD_M 0x000007FF // Maximum Payload +#define USB_RXMAXP7_MAXLOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRL7 register. +// +//***************************************************************************** +#define USB_RXCSRL7_CLRDT 0x00000080 // Clear Data Toggle +#define USB_RXCSRL7_STALLED 0x00000040 // Endpoint Stalled +#define USB_RXCSRL7_REQPKT 0x00000020 // Request Packet +#define USB_RXCSRL7_STALL 0x00000020 // Send STALL +#define USB_RXCSRL7_FLUSH 0x00000010 // Flush FIFO +#define USB_RXCSRL7_DATAERR 0x00000008 // Data Error +#define USB_RXCSRL7_NAKTO 0x00000008 // NAK Timeout +#define USB_RXCSRL7_ERROR 0x00000004 // Error +#define USB_RXCSRL7_OVER 0x00000004 // Overrun +#define USB_RXCSRL7_FULL 0x00000002 // FIFO Full +#define USB_RXCSRL7_RXRDY 0x00000001 // Receive Packet Ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCSRH7 register. +// +//***************************************************************************** +#define USB_RXCSRH7_AUTOCL 0x00000080 // Auto Clear +#define USB_RXCSRH7_ISO 0x00000040 // Isochronous Transfers +#define USB_RXCSRH7_AUTORQ 0x00000040 // Auto Request +#define USB_RXCSRH7_DMAEN 0x00000020 // DMA Request Enable +#define USB_RXCSRH7_PIDERR 0x00000010 // PID Error +#define USB_RXCSRH7_DISNYET 0x00000010 // Disable NYET +#define USB_RXCSRH7_DMAMOD 0x00000008 // DMA Request Mode +#define USB_RXCSRH7_DTWE 0x00000004 // Data Toggle Write Enable +#define USB_RXCSRH7_DT 0x00000002 // Data Toggle +#define USB_RXCSRH7_INCOMPRX 0x00000001 // Incomplete RX Transmission + // Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXCOUNT7 register. +// +//***************************************************************************** +#define USB_RXCOUNT7_COUNT_M 0x00001FFF // Receive Packet Count +#define USB_RXCOUNT7_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXTYPE7 register. +// +//***************************************************************************** +#define USB_TXTYPE7_SPEED_M 0x000000C0 // Operating Speed +#define USB_TXTYPE7_SPEED_DFLT 0x00000000 // Default +#define USB_TXTYPE7_SPEED_HIGH 0x00000040 // High +#define USB_TXTYPE7_SPEED_FULL 0x00000080 // Full +#define USB_TXTYPE7_SPEED_LOW 0x000000C0 // Low +#define USB_TXTYPE7_PROTO_M 0x00000030 // Protocol +#define USB_TXTYPE7_PROTO_CTRL 0x00000000 // Control +#define USB_TXTYPE7_PROTO_ISOC 0x00000010 // Isochronous +#define USB_TXTYPE7_PROTO_BULK 0x00000020 // Bulk +#define USB_TXTYPE7_PROTO_INT 0x00000030 // Interrupt +#define USB_TXTYPE7_TEP_M 0x0000000F // Target Endpoint Number +#define USB_TXTYPE7_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXINTERVAL7 +// register. +// +//***************************************************************************** +#define USB_TXINTERVAL7_TXPOLL_M \ + 0x000000FF // TX Polling +#define USB_TXINTERVAL7_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_TXINTERVAL7_NAKLMT_S \ + 0 +#define USB_TXINTERVAL7_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXTYPE7 register. +// +//***************************************************************************** +#define USB_RXTYPE7_SPEED_M 0x000000C0 // Operating Speed +#define USB_RXTYPE7_SPEED_DFLT 0x00000000 // Default +#define USB_RXTYPE7_SPEED_HIGH 0x00000040 // High +#define USB_RXTYPE7_SPEED_FULL 0x00000080 // Full +#define USB_RXTYPE7_SPEED_LOW 0x000000C0 // Low +#define USB_RXTYPE7_PROTO_M 0x00000030 // Protocol +#define USB_RXTYPE7_PROTO_CTRL 0x00000000 // Control +#define USB_RXTYPE7_PROTO_ISOC 0x00000010 // Isochronous +#define USB_RXTYPE7_PROTO_BULK 0x00000020 // Bulk +#define USB_RXTYPE7_PROTO_INT 0x00000030 // Interrupt +#define USB_RXTYPE7_TEP_M 0x0000000F // Target Endpoint Number +#define USB_RXTYPE7_TEP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXINTERVAL7 +// register. +// +//***************************************************************************** +#define USB_RXINTERVAL7_TXPOLL_M \ + 0x000000FF // RX Polling +#define USB_RXINTERVAL7_NAKLMT_M \ + 0x000000FF // NAK Limit +#define USB_RXINTERVAL7_NAKLMT_S \ + 0 +#define USB_RXINTERVAL7_TXPOLL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAINTR register. +// +//***************************************************************************** +#define USB_DMAINTR_CH7 0x00000080 // Channel 7 DMA Interrupt +#define USB_DMAINTR_CH6 0x00000040 // Channel 6 DMA Interrupt +#define USB_DMAINTR_CH5 0x00000020 // Channel 5 DMA Interrupt +#define USB_DMAINTR_CH4 0x00000010 // Channel 4 DMA Interrupt +#define USB_DMAINTR_CH3 0x00000008 // Channel 3 DMA Interrupt +#define USB_DMAINTR_CH2 0x00000004 // Channel 2 DMA Interrupt +#define USB_DMAINTR_CH1 0x00000002 // Channel 1 DMA Interrupt +#define USB_DMAINTR_CH0 0x00000001 // Channel 0 DMA Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL0 register. +// +//***************************************************************************** +#define USB_DMACTL0_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL0_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL0_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL0_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL0_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL0_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL0_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL0_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL0_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL0_DIR 0x00000002 // DMA Direction +#define USB_DMACTL0_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL0_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR0 register. +// +//***************************************************************************** +#define USB_DMAADDR0_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR0_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT0 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT0_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT0_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL1 register. +// +//***************************************************************************** +#define USB_DMACTL1_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL1_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL1_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL1_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL1_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL1_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL1_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL1_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL1_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL1_DIR 0x00000002 // DMA Direction +#define USB_DMACTL1_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL1_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR1 register. +// +//***************************************************************************** +#define USB_DMAADDR1_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR1_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT1 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT1_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT1_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL2 register. +// +//***************************************************************************** +#define USB_DMACTL2_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL2_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL2_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL2_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL2_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL2_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL2_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL2_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL2_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL2_DIR 0x00000002 // DMA Direction +#define USB_DMACTL2_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL2_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR2 register. +// +//***************************************************************************** +#define USB_DMAADDR2_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR2_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT2 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT2_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT2_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL3 register. +// +//***************************************************************************** +#define USB_DMACTL3_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL3_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL3_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL3_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL3_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL3_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL3_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL3_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL3_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL3_DIR 0x00000002 // DMA Direction +#define USB_DMACTL3_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL3_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR3 register. +// +//***************************************************************************** +#define USB_DMAADDR3_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR3_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT3 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT3_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT3_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL4 register. +// +//***************************************************************************** +#define USB_DMACTL4_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL4_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL4_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL4_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL4_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL4_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL4_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL4_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL4_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL4_DIR 0x00000002 // DMA Direction +#define USB_DMACTL4_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL4_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR4 register. +// +//***************************************************************************** +#define USB_DMAADDR4_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR4_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT4 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT4_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT4_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL5 register. +// +//***************************************************************************** +#define USB_DMACTL5_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL5_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL5_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL5_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL5_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL5_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL5_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL5_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL5_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL5_DIR 0x00000002 // DMA Direction +#define USB_DMACTL5_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL5_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR5 register. +// +//***************************************************************************** +#define USB_DMAADDR5_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR5_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT5 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT5_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT5_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL6 register. +// +//***************************************************************************** +#define USB_DMACTL6_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL6_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL6_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL6_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL6_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL6_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL6_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL6_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL6_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL6_DIR 0x00000002 // DMA Direction +#define USB_DMACTL6_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL6_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR6 register. +// +//***************************************************************************** +#define USB_DMAADDR6_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR6_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT6 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT6_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT6_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACTL7 register. +// +//***************************************************************************** +#define USB_DMACTL7_BRSTM_M 0x00000600 // Burst Mode +#define USB_DMACTL7_BRSTM_ANY 0x00000000 // Bursts of unspecified length +#define USB_DMACTL7_BRSTM_INC4 0x00000200 // INCR4 or unspecified length +#define USB_DMACTL7_BRSTM_INC8 0x00000400 // INCR8, INCR4 or unspecified + // length +#define USB_DMACTL7_BRSTM_INC16 0x00000600 // INCR16, INCR8, INCR4 or + // unspecified length +#define USB_DMACTL7_ERR 0x00000100 // Bus Error Bit +#define USB_DMACTL7_EP_M 0x000000F0 // Endpoint number +#define USB_DMACTL7_IE 0x00000008 // DMA Interrupt Enable +#define USB_DMACTL7_MODE 0x00000004 // DMA Transfer Mode +#define USB_DMACTL7_DIR 0x00000002 // DMA Direction +#define USB_DMACTL7_ENABLE 0x00000001 // DMA Transfer Enable +#define USB_DMACTL7_EP_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMAADDR7 register. +// +//***************************************************************************** +#define USB_DMAADDR7_ADDR_M 0xFFFFFFFC // DMA Address +#define USB_DMAADDR7_ADDR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DMACOUNT7 +// register. +// +//***************************************************************************** +#define USB_DMACOUNT7_COUNT_M 0xFFFFFFFC // DMA Count +#define USB_DMACOUNT7_COUNT_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT1 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT1_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT1_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT2 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT2_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT2_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT3 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT3_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT3_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT4 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT4_COUNT_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT4_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT5 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT5_COUNT_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT5_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT6 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT6_COUNT_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT6_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RQPKTCOUNT7 +// register. +// +//***************************************************************************** +#define USB_RQPKTCOUNT7_COUNT_M 0x0000FFFF // Block Transfer Packet Count +#define USB_RQPKTCOUNT7_COUNT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_RXDPKTBUFDIS +// register. +// +//***************************************************************************** +#define USB_RXDPKTBUFDIS_EP7 0x00000080 // EP7 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP6 0x00000040 // EP6 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP5 0x00000020 // EP5 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP4 0x00000010 // EP4 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP3 0x00000008 // EP3 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP2 0x00000004 // EP2 RX Double-Packet Buffer + // Disable +#define USB_RXDPKTBUFDIS_EP1 0x00000002 // EP1 RX Double-Packet Buffer + // Disable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_TXDPKTBUFDIS +// register. +// +//***************************************************************************** +#define USB_TXDPKTBUFDIS_EP7 0x00000080 // EP7 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP6 0x00000040 // EP6 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP5 0x00000020 // EP5 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP4 0x00000010 // EP4 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP3 0x00000008 // EP3 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP2 0x00000004 // EP2 TX Double-Packet Buffer + // Disable +#define USB_TXDPKTBUFDIS_EP1 0x00000002 // EP1 TX Double-Packet Buffer + // Disable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CTO register. +// +//***************************************************************************** +#define USB_CTO_CCTV_M 0x0000FFFF // Configurable Chirp Timeout Value +#define USB_CTO_CCTV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_HHSRTN register. +// +//***************************************************************************** +#define USB_HHSRTN_HHSRTN_M 0x0000FFFF // HIgh Speed to UTM Operating + // Delay +#define USB_HHSRTN_HHSRTN_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_HSBT register. +// +//***************************************************************************** +#define USB_HSBT_HSBT_M 0x0000000F // High Speed Timeout Adder +#define USB_HSBT_HSBT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LPMATTR register. +// +//***************************************************************************** +#define USB_LPMATTR_ENDPT_M 0x0000F000 // Endpoint +#define USB_LPMATTR_RMTWAK 0x00000100 // Remote Wake +#define USB_LPMATTR_HIRD_M 0x000000F0 // Host Initiated Resume Duration +#define USB_LPMATTR_LS_M 0x0000000F // Link State +#define USB_LPMATTR_LS_L1 0x00000001 // Sleep State (L1) +#define USB_LPMATTR_ENDPT_S 12 +#define USB_LPMATTR_HIRD_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LPMCNTRL register. +// +//***************************************************************************** +#define USB_LPMCNTRL_NAK 0x00000010 // LPM NAK +#define USB_LPMCNTRL_EN_M 0x0000000C // LPM Enable +#define USB_LPMCNTRL_EN_NONE 0x00000000 // LPM and Extended transactions + // are not supported. In this case, + // the USB does not respond to LPM + // transactions and LPM + // transactions cause a timeout +#define USB_LPMCNTRL_EN_EXT 0x00000004 // LPM is not supported but + // extended transactions are + // supported. In this case, the USB + // does respond to an LPM + // transaction with a STALL +#define USB_LPMCNTRL_EN_LPMEXT 0x0000000C // The USB supports LPM extended + // transactions. In this case, the + // USB responds with a NYET or an + // ACK as determined by the value + // of TXLPM and other conditions +#define USB_LPMCNTRL_RES 0x00000002 // LPM Resume +#define USB_LPMCNTRL_TXLPM 0x00000001 // Transmit LPM Transaction Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LPMIM register. +// +//***************************************************************************** +#define USB_LPMIM_ERR 0x00000020 // LPM Error Interrupt Mask +#define USB_LPMIM_RES 0x00000010 // LPM Resume Interrupt Mask +#define USB_LPMIM_NC 0x00000008 // LPM NC Interrupt Mask +#define USB_LPMIM_ACK 0x00000004 // LPM ACK Interrupt Mask +#define USB_LPMIM_NY 0x00000002 // LPM NY Interrupt Mask +#define USB_LPMIM_STALL 0x00000001 // LPM STALL Interrupt Mask + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LPMRIS register. +// +//***************************************************************************** +#define USB_LPMRIS_ERR 0x00000020 // LPM Interrupt Status +#define USB_LPMRIS_RES 0x00000010 // LPM Resume Interrupt Status +#define USB_LPMRIS_NC 0x00000008 // LPM NC Interrupt Status +#define USB_LPMRIS_ACK 0x00000004 // LPM ACK Interrupt Status +#define USB_LPMRIS_NY 0x00000002 // LPM NY Interrupt Status +#define USB_LPMRIS_LPMST 0x00000001 // LPM STALL Interrupt Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_LPMFADDR register. +// +//***************************************************************************** +#define USB_LPMFADDR_ADDR_M 0x0000007F // LPM Function Address +#define USB_LPMFADDR_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPC register. +// +//***************************************************************************** +#define USB_EPC_PFLTACT_M 0x00000300 // Power Fault Action +#define USB_EPC_PFLTACT_UNCHG 0x00000000 // Unchanged +#define USB_EPC_PFLTACT_TRIS 0x00000100 // Tristate +#define USB_EPC_PFLTACT_LOW 0x00000200 // Low +#define USB_EPC_PFLTACT_HIGH 0x00000300 // High +#define USB_EPC_PFLTAEN 0x00000040 // Power Fault Action Enable +#define USB_EPC_PFLTSEN_HIGH 0x00000020 // Power Fault Sense +#define USB_EPC_PFLTEN 0x00000010 // Power Fault Input Enable +#define USB_EPC_EPENDE 0x00000004 // EPEN Drive Enable +#define USB_EPC_EPEN_M 0x00000003 // External Power Supply Enable + // Configuration +#define USB_EPC_EPEN_LOW 0x00000000 // Power Enable Active Low +#define USB_EPC_EPEN_HIGH 0x00000001 // Power Enable Active High +#define USB_EPC_EPEN_VBLOW 0x00000002 // Power Enable High if VBUS Low + // (OTG only) +#define USB_EPC_EPEN_VBHIGH 0x00000003 // Power Enable High if VBUS High + // (OTG only) + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPCRIS register. +// +//***************************************************************************** +#define USB_EPCRIS_PF 0x00000001 // USB Power Fault Interrupt Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPCIM register. +// +//***************************************************************************** +#define USB_EPCIM_PF 0x00000001 // USB Power Fault Interrupt Mask + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_EPCISC register. +// +//***************************************************************************** +#define USB_EPCISC_PF 0x00000001 // USB Power Fault Interrupt Status + // and Clear + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DRRIS register. +// +//***************************************************************************** +#define USB_DRRIS_RESUME 0x00000001 // RESUME Interrupt Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DRIM register. +// +//***************************************************************************** +#define USB_DRIM_RESUME 0x00000001 // RESUME Interrupt Mask + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_DRISC register. +// +//***************************************************************************** +#define USB_DRISC_RESUME 0x00000001 // RESUME Interrupt Status and + // Clear + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_GPCS register. +// +//***************************************************************************** +#define USB_GPCS_DEVMOD_M 0x00000007 // Device Mode +#define USB_GPCS_DEVMOD_OTG 0x00000000 // Use USB0VBUS and USB0ID pin +#define USB_GPCS_DEVMOD_HOST 0x00000002 // Force USB0VBUS and USB0ID low +#define USB_GPCS_DEVMOD_DEV 0x00000003 // Force USB0VBUS and USB0ID high +#define USB_GPCS_DEVMOD_HOSTVBUS \ + 0x00000004 // Use USB0VBUS and force USB0ID + // low +#define USB_GPCS_DEVMOD_DEVVBUS 0x00000005 // Use USB0VBUS and force USB0ID + // high + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_VDC register. +// +//***************************************************************************** +#define USB_VDC_VBDEN 0x00000001 // VBUS Droop Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_VDCRIS register. +// +//***************************************************************************** +#define USB_VDCRIS_VD 0x00000001 // VBUS Droop Raw Interrupt Status + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_VDCIM register. +// +//***************************************************************************** +#define USB_VDCIM_VD 0x00000001 // VBUS Droop Interrupt Mask + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_VDCISC register. +// +//***************************************************************************** +#define USB_VDCISC_VD 0x00000001 // VBUS Droop Interrupt Status and + // Clear + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_PP register. +// +//***************************************************************************** +#define USB_PP_ECNT_M 0x0000FF00 // Endpoint Count +#define USB_PP_USB_M 0x000000C0 // USB Capability +#define USB_PP_USB_DEVICE 0x00000040 // DEVICE +#define USB_PP_USB_HOSTDEVICE 0x00000080 // HOST +#define USB_PP_USB_OTG 0x000000C0 // OTG +#define USB_PP_ULPI 0x00000020 // ULPI Present +#define USB_PP_PHY 0x00000010 // PHY Present +#define USB_PP_TYPE_M 0x0000000F // Controller Type +#define USB_PP_TYPE_0 0x00000000 // The first-generation USB + // controller +#define USB_PP_TYPE_1 0x00000001 // The second-generation USB + // controller revision +#define USB_PP_ECNT_S 8 + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_PC register. +// +//***************************************************************************** +#define USB_PC_ULPIEN 0x00010000 // ULPI Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the USB_O_CC register. +// +//***************************************************************************** +#define USB_CC_CLKEN 0x00000200 // USB Clock Enable +#define USB_CC_CSD 0x00000100 // Clock Source/Direction +#define USB_CC_CLKDIV_M 0x0000000F // PLL Clock Divisor +#define USB_CC_CLKDIV_S 0 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 577bd0e05..46aabc5aa 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -214,14 +214,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) UsbDeviceDescBank* bank = &sram_registers[epnum][dir]; uint32_t size_value = 0; while (size_value < 7) { - if (1 << (size_value + 3) == desc_edpt->wMaxPacketSize.size) { + if (1 << (size_value + 3) == tu_edpt_packet_size(desc_edpt)) { break; } size_value++; } // unsupported endpoint size - if ( size_value == 7 && desc_edpt->wMaxPacketSize.size != 1023 ) return false; + if ( size_value == 7 && tu_edpt_packet_size(desc_edpt) != 1023 ) return false; bank->PCKSIZE.bit.SIZE = size_value; @@ -230,16 +230,24 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if ( dir == TUSB_DIR_OUT ) { ep->EPCFG.bit.EPTYPE0 = desc_edpt->bmAttributes.xfer + 1; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0 | USB_DEVICE_EPSTATUSCLR_DTGLOUT; // clear stall & dtoggle ep->EPINTENSET.bit.TRCPT0 = true; }else { ep->EPCFG.bit.EPTYPE1 = desc_edpt->bmAttributes.xfer + 1; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1 | USB_DEVICE_EPSTATUSCLR_DTGLIN; // clear stall & dtoggle ep->EPINTENSET.bit.TRCPT1 = true; } return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index d50621ce4..2e9854153 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -258,7 +258,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) // Must not already enabled TU_ASSERT((UDP->UDP_CSR[epnum] & UDP_CSR_EPEDS_Msk) == 0); - xfer_epsize_set(&_dcd_xfer[epnum], ep_desc->wMaxPacketSize.size); + xfer_epsize_set(&_dcd_xfer[epnum], tu_edpt_packet_size(ep_desc)); // Configure type and enable EP csr_write(epnum, UDP_CSR_EPEDS_Msk | UDP_CSR_EPTYPE(ep_desc->bmAttributes.xfer + 4*dir)); @@ -269,6 +269,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 0d9e184f6..9e3b43840 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -84,7 +84,7 @@ static xfer_ctl_t xfer_status[EP_MAX]; static const tusb_desc_endpoint_t ep0_desc = { .bEndpointAddress = 0x00, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, }; TU_ATTR_ALWAYS_INLINE static inline void CleanInValidateCache(uint32_t *addr, int32_t size) @@ -460,7 +460,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) (void) rhport; uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + uint16_t const epMaxPktSize = tu_edpt_packet_size(ep_desc); tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; uint8_t fifoSize = 0; // FIFO size uint16_t defaultEndpointSize = 8; // Default size of Endpoint @@ -544,6 +544,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 59a40dc68..a3b69b987 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -283,7 +283,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) /* Response with status first before changing device address */ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -extern u32 SystemCoreClock ; +extern u32 SystemCoreClock; void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; @@ -323,7 +323,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = ep_desc->wMaxPacketSize.size; + ep->max_packet_size = tu_edpt_packet_size(ep_desc); unsigned val = USB_ENDPT_EPCTLDIS_MASK; val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; @@ -339,6 +339,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index f6b64c986..2bcd56b8a 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -63,7 +63,7 @@ typedef struct uint8_t* buffer; uint16_t total_len; volatile uint16_t actual_len; - uint16_t mps; // max packet size + uint16_t mps; // max packet size // nRF will auto accept OUT packet after DMA is done // indicate packet is already ACK @@ -82,11 +82,8 @@ static struct // +1 for ISO endpoints xfer_td_t xfer[EP_CBI_COUNT + 1][2]; - // Number of pending DMA that is started but not handled yet by dcd_int_handler(). - // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. - // However, in critical section with interrupt disabled, the DMA can be finished and added up - // until handled by dcd_int_handler() when exiting critical section. - volatile uint8_t dma_pending; + // nRF can only carry one DMA at a time, this is used to guard the access to EasyDMA + volatile bool dma_running; }_dcd; /*------------------------------------------------------------------*/ @@ -115,67 +112,68 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void) } // helper to start DMA +static void start_dma(volatile uint32_t* reg_startep) +{ + _dcd.dma_running = true; + + (*reg_startep) = 1; + __ISB(); __DSB(); + + // TASKS_EP0STATUS, TASKS_EP0RCVOUT seem to need EasyDMA to be available + // However these don't trigger any DMA transfer and got ENDED event subsequently + // Therefore dma_pending is corrected right away + if ( (reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT) ) + { + _dcd.dma_running = false; + } +} + +// only 1 EasyDMA can be active at any time // TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA // since current implementation does not 100% guarded against race condition static void edpt_dma_start(volatile uint32_t* reg_startep) { - // Only one dma can be active - if ( _dcd.dma_pending ) + // Called in critical section i.e within USB ISR, or USB/Global interrupt disabled + if ( is_in_isr() || __get_PRIMASK() || !NVIC_GetEnableIRQ(USBD_IRQn) ) { - if (is_in_isr()) + if (_dcd.dma_running) { - // Called within ISR, use usbd task to defer later - usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true ); - return; + //use usbd task to defer later + usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true); + }else + { + start_dma(reg_startep); } - else + }else + { + // Called in non-critical thread-mode, should be 99% of the time. + // Should be safe to blocking wait until previous DMA transfer complete + uint8_t const rhport = 0; + bool started = false; + while(!started) { - if ( __get_PRIMASK() || !NVIC_GetEnableIRQ(USBD_IRQn) ) - { - // Called in critical section with interrupt disabled. We have to manually check - // for the DMA complete by comparing current pending DMA with number of ENDED Events - uint32_t ended = 0; + // LDREX/STREX may be needed in form of std atomic (required C11) or + // use osal mutex to guard against multiple core MCUs such as nRF53 + dcd_int_disable(rhport); - while ( _dcd.dma_pending > ((uint8_t) ended) ) - { - ended = NRF_USBD->EVENTS_ENDISOIN + NRF_USBD->EVENTS_ENDISOOUT; - - for (uint8_t i=0; iEVENTS_ENDEPIN[i] + NRF_USBD->EVENTS_ENDEPOUT[i]; - } - } - }else + if ( !_dcd.dma_running ) { - // Called in non-critical thread-mode, should be 99% of the time. - // Should be safe to blocking wait until previous DMA transfer complete - while ( _dcd.dma_pending ) { } + start_dma(reg_startep); + started = true; } + + dcd_int_enable(rhport); + + // osal_yield(); } } - - _dcd.dma_pending++; - - (*reg_startep) = 1; - __ISB(); __DSB(); } // DMA is complete static void edpt_dma_end(void) { - TU_ASSERT(_dcd.dma_pending, ); - _dcd.dma_pending = 0; -} - -// helper to set TASKS_EP0STATUS / TASKS_EP0RCVOUT since they also need EasyDMA -// However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently -// Therefore dma_running state will be corrected right away -void start_ep0_task(volatile uint32_t* reg_task) -{ - edpt_dma_start(reg_task); - - // correct the dma_running++ in dma start - if (_dcd.dma_pending) _dcd.dma_pending--; + TU_ASSERT(_dcd.dma_running, ); + _dcd.dma_running = false; } // helper getting td @@ -194,7 +192,10 @@ static void xact_out_dma(uint8_t epnum) { xact_len = NRF_USBD->SIZE.ISOOUT; // If ZERO bit is set, ignore ISOOUT length - if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk) xact_len = 0; + if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk) + { + xact_len = 0; + } else { // Trigger DMA move data from Endpoint -> SRAM @@ -206,7 +207,8 @@ static void xact_out_dma(uint8_t epnum) } else { - xact_len = (uint8_t)NRF_USBD->SIZE.EPOUT[epnum]; + // limit xact len to remaining length + xact_len = tu_min16((uint16_t) NRF_USBD->SIZE.EPOUT[epnum], xfer->total_len - xfer->actual_len); // Trigger DMA move data from Endpoint -> SRAM NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer; @@ -214,9 +216,6 @@ static void xact_out_dma(uint8_t epnum) edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]); } - - xfer->buffer += xact_len; - xfer->actual_len += xact_len; } // Prepare for a CBI transaction IN, call at the start @@ -231,8 +230,6 @@ static void xact_in_dma(uint8_t epnum) NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer; NRF_USBD->EPIN[epnum].MAXCNT = xact_len; - xfer->buffer += xact_len; - edpt_dma_start(&NRF_USBD->TASKS_STARTEPIN[epnum]); } @@ -241,6 +238,7 @@ static void xact_in_dma(uint8_t epnum) //--------------------------------------------------------------------+ void dcd_init (uint8_t rhport) { + TU_LOG1("dcd init\r\n"); (void) rhport; } @@ -306,10 +304,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + uint8_t const ep_addr = desc_edpt->bEndpointAddress; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - _dcd.xfer[epnum][dir].mps = desc_edpt->wMaxPacketSize.size; + _dcd.xfer[epnum][dir].mps = tu_edpt_packet_size(desc_edpt); if (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) { @@ -359,11 +358,48 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk; } } + + // clear stall and reset DataToggle + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; + NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr; + __ISB(); __DSB(); return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + // disable interrupt to prevent race condition + dcd_int_disable(rhport); + + // disable all non-control (bulk + interrupt) endpoints + for ( uint8_t ep = 1; ep < EP_CBI_COUNT; ep++ ) + { + NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + ep) | TU_BIT(USBD_INTEN_ENDEPIN0_Pos + ep); + + NRF_USBD->TASKS_STARTEPIN[ep] = 0; + NRF_USBD->TASKS_STARTEPOUT[ep] = 0; + + tu_memclr(_dcd.xfer[ep], 2*sizeof(xfer_td_t)); + } + + // disable both ISO + NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk | USBD_INTENCLR_ENDISOOUT_Msk | USBD_INTENCLR_ENDISOIN_Msk; + NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir; + + NRF_USBD->TASKS_STARTISOIN = 0; + NRF_USBD->TASKS_STARTISOOUT = 0; + + tu_memclr(_dcd.xfer[EP_ISO_NUM], 2*sizeof(xfer_td_t)); + + // de-activate all non-control + NRF_USBD->EPOUTEN = 1UL; + NRF_USBD->EPINEN = 1UL; + + dcd_int_enable(rhport); +} + void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -427,7 +463,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( control_status ) { // Status Phase also requires EasyDMA has to be available as well !!!! - start_ep0_task(&NRF_USBD->TASKS_EP0STATUS); + edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); // The nRF doesn't interrupt on status transmit so we queue up a success response. dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr()); @@ -437,15 +473,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( epnum == 0 ) { // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA - start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT); + edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT); }else { if ( xfer->data_received ) { - // Data may already be received previously - xfer->data_received = false; - + // Data is already received previously // start DMA to copy to SRAM + xfer->data_received = false; xact_out_dma(epnum); } else @@ -467,7 +502,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_td_t* xfer = get_td(epnum, dir); if ( epnum == 0 ) { @@ -475,6 +514,14 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) }else if (epnum != EP_ISO_NUM) { NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr; + + // Note: nRF can auto ACK packet OUT before get stalled. + // There maybe data in endpoint fifo already, we need to pull it out + if ( (dir == TUSB_DIR_OUT) && xfer->data_received ) + { + xfer->data_received = false; + xact_out_dma(epnum); + } } __ISB(); __DSB(); @@ -488,14 +535,16 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) if ( epnum != 0 && epnum != EP_ISO_NUM ) { + // reset data toggle to DATA0 + // First write this register with VALUE=Nop to select the endpoint, then either read it to get the status from + // VALUE, or write it again with VALUE=Data0 or Data1 + NRF_USBD->DTOGGLE = ep_addr; + NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr; + // clear stall NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; - // reset data toggle to DATA0 - NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr; - // Write any value to SIZE register will allow nRF to ACK/accept data - // Drop any pending data if (dir == TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0; __ISB(); __DSB(); @@ -508,7 +557,9 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) void bus_reset(void) { // 6.35.6 USB controller automatically disabled all endpoints (except control) - // i.e EPOUTEN and EPINEN and reset USBADDR to 0 + NRF_USBD->EPOUTEN = 1UL; + NRF_USBD->EPINEN = 1UL; + for(int i=0; i<8; i++) { NRF_USBD->TASKS_STARTEPIN[i] = 0; @@ -662,7 +713,8 @@ void dcd_int_handler(uint8_t rhport) if ( int_status & EDPT_END_ALL_MASK ) { - // DMA complete move data from SRAM -> Endpoint + // DMA complete move data from SRAM <-> Endpoint + // Must before endpoint transfer handling edpt_dma_end(); } @@ -677,7 +729,7 @@ void dcd_int_handler(uint8_t rhport) * - Host -> Endpoint * EPDATA (or EP0DATADONE) interrupted, check EPDATASTATUS.EPOUT[i] * to start DMA. For Bulk/Interrupt, this step can occur automatically (without sw), - * which means data may or may not be ready (data_received flag). + * which means data may or may not be ready (out_received flag). * - Endpoint -> RAM * ENDEPOUT[i] interrupted, transaction complete, sw prepare next transaction * @@ -709,20 +761,16 @@ void dcd_int_handler(uint8_t rhport) xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT); uint8_t const xact_len = NRF_USBD->EPOUT[epnum].AMOUNT; + xfer->buffer += xact_len; + xfer->actual_len += xact_len; + // Transfer complete if transaction len < Max Packet Size or total len is transferred if ( (epnum != EP_ISO_NUM) && (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) { if ( epnum == 0 ) { // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA - if ( _dcd.dma_pending ) - { - // use usbd task to defer later - usbd_defer_func( (osal_task_func_t) start_ep0_task, (void*) &NRF_USBD->TASKS_EP0RCVOUT, true ); - }else - { - start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT); - } + edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT); }else { // nRF auto accept next Bulk/Interrupt OUT packet @@ -759,8 +807,10 @@ void dcd_int_handler(uint8_t rhport) if ( tu_bit_test(data_status, epnum) || (epnum == 0 && is_control_in) ) { xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN); + uint8_t const xact_len = NRF_USBD->EPIN[epnum].AMOUNT; - xfer->actual_len += NRF_USBD->EPIN[epnum].MAXCNT; + xfer->buffer += xact_len; + xfer->actual_len += xact_len; if ( xfer->actual_len < xfer->total_len ) { diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 57cc76e81..0d45090d1 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -251,7 +251,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = p_endpoint_desc->wMaxPacketSize.size; + int const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; @@ -273,6 +273,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index a776e46f5..fc7150508 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -200,11 +200,10 @@ static void bus_reset(void) } /* centralized location for USBD interrupt enable bit mask */ -#if USE_SOF -static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk | USBD_INTSTS_SOFIF_Msk; -#else -static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk; -#endif +enum { + ENABLED_IRQS = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | + USBD_INTSTS_USBIF_Msk | (USE_SOF ? USBD_INTSTS_SOFIF_Msk : 0) +}; /* NUC121/NUC125/NUC126 TinyUSB API driver implementation @@ -226,8 +225,8 @@ void dcd_init(uint8_t rhport) usb_attach(); - USBD->INTSTS = enabled_irqs; - USBD->INTEN = enabled_irqs; + USBD->INTSTS = ENABLED_IRQS; + USBD->INTEN = ENABLED_IRQS; } void dcd_int_enable(uint8_t rhport) @@ -252,10 +251,23 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } +static void remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while(count--) __NOP(); +} + void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - USBD->ATTR = USBD_ATTR_RWAKEUP_Msk; + // Enable PHY before sending Resume('K') state + USBD->ATTR |= USBD_ATTR_PHYEN_Msk; + USBD->ATTR |= USBD_ATTR_RWAKEUP_Msk; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + remote_wakeup_delay(); + USBD->ATTR &=~USBD_ATTR_RWAKEUP_Msk; } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) @@ -267,7 +279,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = p_endpoint_desc->wMaxPacketSize.size; + int const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; @@ -289,6 +301,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { (void) rhport; @@ -361,14 +379,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; USBD_EP_T *ep = ep_entry(ep_addr, false); - ep->CFG |= USBD_CFG_CSTALL_Msk; + ep->CFG = (ep->CFG & ~USBD_CFG_DSQSYNC_Msk) | USBD_CFG_CSTALL_Msk; } void dcd_int_handler(uint8_t rhport) { (void) rhport; - uint32_t status = USBD->INTSTS; + // Mask non-enabled irqs, ex. SOF + uint32_t status = USBD->INTSTS & (ENABLED_IRQS | 0xffffff00); + #ifdef SUPPORT_LPM uint32_t state = USBD->ATTR & 0x300f; #else @@ -499,7 +519,7 @@ void dcd_int_handler(uint8_t rhport) } /* acknowledge all interrupts */ - USBD->INTSTS = status & enabled_irqs; + USBD->INTSTS = status & ENABLED_IRQS; } // Invoked when a control transfer's status stage is complete. diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 4e633086d..aefb09f4e 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -144,7 +144,9 @@ static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) enum ep_enum ep_index; struct xfer_ctl_t *xfer; - for (ep_index = PERIPH_EPA, xfer = &xfer_table[PERIPH_EPA], ep = USBD->EP; ep_index < PERIPH_MAX_EP; ep_index++, xfer++, ep++) + for (ep_index = PERIPH_EPA, xfer = &xfer_table[PERIPH_EPA], ep = USBD->EP; + ep_index < PERIPH_MAX_EP; + ep_index++, xfer++, ep++) { if (add) { @@ -325,7 +327,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - int const size = p_endpoint_desc->wMaxPacketSize.size; + int const size = tu_edpt_packet_size(p_endpoint_desc); tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; @@ -353,6 +355,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { (void) rhport; @@ -390,6 +398,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* mine the data for the information we need */ tusb_dir_t dir = tu_edpt_dir(ep_addr); USBD_EP_T *ep = ep_entry(ep_addr, false); + TU_ASSERT(ep); struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* store away the information we'll needing now and later */ @@ -451,6 +460,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) if (tu_edpt_number(ep_addr)) { USBD_EP_T *ep = ep_entry(ep_addr, false); + TU_ASSERT(ep, ); ep->EPRSPCTL = (ep->EPRSPCTL & 0xf7) | USBD_EPRSPCTL_HALT_Msk; } else @@ -466,6 +476,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) if (tu_edpt_number(ep_addr)) { USBD_EP_T *ep = ep_entry(ep_addr, false); + TU_ASSERT(ep, ); ep->EPRSPCTL = USBD_EPRSPCTL_TOGGLE_Msk; } } diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index dce464fd2..8de924f90 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -52,23 +52,23 @@ typedef struct TU_ATTR_PACKED struct { union { struct { - uint16_t : 2; - uint16_t tok_pid : 4; - uint16_t data : 1; - uint16_t own : 1; - uint16_t : 8; + uint16_t : 2; + __IO uint16_t tok_pid : 4; + uint16_t data : 1; + __IO uint16_t own : 1; + uint16_t : 8; }; struct { - uint16_t : 2; - uint16_t bdt_stall: 1; - uint16_t dts : 1; - uint16_t ninc : 1; - uint16_t keep : 1; - uint16_t : 10; + uint16_t : 2; + uint16_t bdt_stall : 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; }; }; - uint16_t bc : 10; - uint16_t : 6; + __IO uint16_t bc : 10; + uint16_t : 6; }; }; uint8_t *addr; @@ -120,10 +120,8 @@ static void prepare_next_setup_packet(uint8_t rhport) { const unsigned out_odd = _dcd.endpoint[0][0].odd; const unsigned in_odd = _dcd.endpoint[0][1].odd; - if (_dcd.bdt[0][0][out_odd].own) { - TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); - return; - } + TU_ASSERT(0 == _dcd.bdt[0][0][out_odd].own, ); + _dcd.bdt[0][0][out_odd].data = 0; _dcd.bdt[0][0][out_odd ^ 1].data = 1; _dcd.bdt[0][1][in_odd].data = 1; @@ -134,10 +132,16 @@ static void prepare_next_setup_packet(uint8_t rhport) static void process_stall(uint8_t rhport) { - if (KHCI->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) { - /* clear stall condition of the control pipe */ - prepare_next_setup_packet(rhport); - KHCI->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + for (int i = 0; i < 16; ++i) { + unsigned const endpt = KHCI->ENDPOINT[i].ENDPT; + + if (endpt & USB_ENDPT_EPSTALL_MASK) { + // prepare next setup if endpoint0 + if ( i == 0 ) prepare_next_setup_packet(rhport); + + // clear stall bit + KHCI->ENDPOINT[i].ENDPT = endpt & ~USB_ENDPT_EPSTALL_MASK; + } } } @@ -145,12 +149,17 @@ static void process_tokdne(uint8_t rhport) { const unsigned s = KHCI->STAT; KHCI->ISTAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + + uint8_t const epnum = (s >> USB_STAT_ENDP_SHIFT); + uint8_t const dir = (s & USB_STAT_TX_MASK) >> USB_STAT_TX_SHIFT; + unsigned const odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; - unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; /* fetch pid before discarded by the next steps */ const unsigned pid = bd->tok_pid; + /* reset values for a next transfer */ bd->bdt_stall = 0; bd->dts = 1; @@ -163,9 +172,6 @@ static void process_tokdne(uint8_t rhport) KHCI->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; return; } - if (s >> 4) { - TU_LOG1("TKDNE %x\r\n", s); - } const unsigned bc = bd->bc; const unsigned remaining = ep->remaining - bc; @@ -184,9 +190,9 @@ static void process_tokdne(uint8_t rhport) } const unsigned length = ep->length; dcd_event_xfer_complete(rhport, - ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + tu_edpt_addr(epnum, dir), length - remaining, XFER_RESULT_SUCCESS, true); - if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { + if (0 == epnum && 0 == length) { /* After completion a ZLP of control transfer, * it prepares for the next steup transfer. */ if (_dcd.addr) { @@ -204,7 +210,8 @@ static void process_bus_reset(uint8_t rhport) KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; KHCI->CTL |= USB_CTL_ODDRST_MASK; KHCI->ADDR = 0; - KHCI->INTEN = (KHCI->INTEN & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + KHCI->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | USB_INTEN_SLEEPEN_MASK | + USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; KHCI->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; for (unsigned i = 1; i < 16; ++i) { @@ -229,21 +236,27 @@ static void process_bus_reset(uint8_t rhport) dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } -static void process_bus_inactive(uint8_t rhport) +static void process_bus_sleep(uint8_t rhport) { - (void) rhport; + // Enable resume & disable suspend interrupt const unsigned inten = KHCI->INTEN; + KHCI->INTEN = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + KHCI->USBTRC0 |= USB_USBTRC0_USBRESMEN_MASK; KHCI->USBCTRL |= USB_USBCTRL_SUSP_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } -static void process_bus_active(uint8_t rhport) +static void process_bus_resume(uint8_t rhport) { - (void) rhport; - KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; + // Enable suspend & disable resume interrupt const unsigned inten = KHCI->INTEN; + + KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; // will also clear USB_USBTRC0_USB_RESUME_INT_MASK + KHCI->USBTRC0 &= ~USB_USBTRC0_USBRESMEN_MASK; KHCI->INTEN = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } @@ -256,12 +269,15 @@ void dcd_init(uint8_t rhport) KHCI->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; while (KHCI->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + tu_memclr(&_dcd, sizeof(_dcd)); KHCI->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */ KHCI->BDTPAGE1 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); KHCI->BDTPAGE2 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); KHCI->BDTPAGE3 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); + KHCI->INTEN = USB_INTEN_USBRSTEN_MASK; + dcd_connect(rhport); NVIC_ClearPendingIRQ(USB0_IRQn); } @@ -269,8 +285,6 @@ void dcd_init(uint8_t rhport) void dcd_int_enable(uint8_t rhport) { (void) rhport; - KHCI->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; NVIC_EnableIRQ(USB0_IRQn); } @@ -278,13 +292,11 @@ void dcd_int_disable(uint8_t rhport) { (void) rhport; NVIC_DisableIRQ(USB0_IRQn); - KHCI->INTEN = 0; } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - _dcd.addr = dev_addr & 0x7F; + _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } @@ -292,9 +304,12 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - unsigned cnt = SystemCoreClock / 100; + KHCI->CTL |= USB_CTL_RESUME_MASK; + + unsigned cnt = SystemCoreClock / 1000; while (cnt--) __NOP(); + KHCI->CTL &= ~USB_CTL_RESUME_MASK; } @@ -321,17 +336,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) (void) rhport; const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; const unsigned odd = ep->odd; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = ep_desc->wMaxPacketSize.size; + ep->max_packet_size = tu_edpt_packet_size(ep_desc); unsigned val = USB_ENDPT_EPCTLDIS_MASK; val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; @@ -347,35 +362,60 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + for (unsigned i = 1; i < 16; ++i) { + KHCI->ENDPOINT[i].ENDPT = 0; + } + if (ie) NVIC_EnableIRQ(USB0_IRQn); + buffer_descriptor_t *bd = _dcd.bdt[1][0]; + for (unsigned i = 2; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + bd->head = 0; + } + endpoint_state_t *ep = &_dcd.endpoint[1][0]; + for (unsigned i = 2; i < sizeof(_dcd.endpoint)/sizeof(*ep); ++i, ++ep) { + /* Clear except the odd */ + ep->max_packet_size = 0; + ep->length = 0; + ep->remaining = 0; + } +} + void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); KHCI->ENDPOINT[epn].ENDPT &= ~msk; ep->max_packet_size = 0; ep->length = 0; ep->remaining = 0; - bd->head = 0; + bd[0].head = 0; + bd[1].head = 0; + if (ie) NVIC_EnableIRQ(USB0_IRQn); } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void) rhport; - NVIC_DisableIRQ(USB0_IRQn); - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + TU_ASSERT(0 == bd->own); + + const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); - if (bd->own) { - TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); - return false; /* The last transfer has not completed */ - } ep->length = total_bytes; ep->remaining = total_bytes; @@ -388,42 +428,69 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to next->addr = buffer + mps; next->own = 1; } - bd->bc = total_bytes >= mps ? mps: total_bytes; - bd->addr = buffer; + bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->addr = buffer; __DSB(); - bd->own = 1; /* the own bit must set after addr */ - NVIC_EnableIRQ(USB0_IRQn); + bd->own = 1; /* This bit must be set last */ + + if (ie) NVIC_EnableIRQ(USB0_IRQn); return true; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - const unsigned epn = ep_addr & 0xFu; + const unsigned epn = tu_edpt_number(ep_addr); + if (0 == epn) { KHCI->ENDPOINT[epn].ENDPT |= USB_ENDPT_EPSTALL_MASK; } else { - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - bd[0].bdt_stall = 1; - bd[1].bdt_stall = 1; + const unsigned dir = tu_edpt_dir(ep_addr); + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][odd]; + TU_ASSERT(0 == bd->own,); + + const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + + bd->bdt_stall = 1; + __DSB(); + bd->own = 1; /* This bit must be set last */ + + if (ie) NVIC_EnableIRQ(USB0_IRQn); } } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + TU_VERIFY(epn,); + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned odd = _dcd.endpoint[epn][dir].odd; buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + TU_VERIFY(bd[odd].own,); - bd[odd ^ 1].own = 0; - bd[odd ^ 1].data = 1; - bd[odd ^ 1].bdt_stall = 0; - bd[odd].own = 0; - bd[odd].data = 0; - bd[odd].bdt_stall = 0; + const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); + NVIC_DisableIRQ(USB0_IRQn); + + bd[odd].own = 0; + __DSB(); + + // clear stall + bd[odd].bdt_stall = 0; + + // Reset data toggle + bd[odd ].data = 0; + bd[odd ^ 1].data = 1; + + // We already cleared this in ISR, but just clear it here to be safe + const unsigned endpt = KHCI->ENDPOINT[epn].ENDPT; + if (endpt & USB_ENDPT_EPSTALL_MASK) { + KHCI->ENDPOINT[epn].ENDPT = endpt & ~USB_ENDPT_EPSTALL_MASK; + } + + if (ie) NVIC_EnableIRQ(USB0_IRQn); } //--------------------------------------------------------------------+ @@ -431,48 +498,59 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ void dcd_int_handler(uint8_t rhport) { - (void) rhport; - uint32_t is = KHCI->ISTAT; uint32_t msk = KHCI->INTEN; + + // clear non-enabled interrupts KHCI->ISTAT = is & ~msk; is &= msk; + if (is & USB_ISTAT_ERROR_MASK) { /* TODO: */ uint32_t es = KHCI->ERRSTAT; KHCI->ERRSTAT = es; KHCI->ISTAT = is; /* discard any pending events */ - return; } if (is & USB_ISTAT_USBRST_MASK) { KHCI->ISTAT = is; /* discard any pending events */ process_bus_reset(rhport); - return; } + if (is & USB_ISTAT_SLEEP_MASK) { + // TU_LOG2("Suspend: "); TU_LOG2_HEX(is); + + // Note Host usually has extra delay after bus reset (without SOF), which could falsely + // detected as Sleep event. Though usbd has debouncing logic so we are good KHCI->ISTAT = USB_ISTAT_SLEEP_MASK; - process_bus_inactive(rhport); - return; + process_bus_sleep(rhport); } + +#if 0 // ISTAT_RESUME never trigger, probably for host mode ? if (is & USB_ISTAT_RESUME_MASK) { + // TU_LOG2("ISTAT Resume: "); TU_LOG2_HEX(is); KHCI->ISTAT = USB_ISTAT_RESUME_MASK; - process_bus_active(rhport); - return; + process_bus_resume(rhport); } +#endif + + if (KHCI->USBTRC0 & USB_USBTRC0_USB_RESUME_INT_MASK) { + // TU_LOG2("USBTRC0 Resume: "); TU_LOG2_HEX(is); TU_LOG2_HEX(KHCI->USBTRC0); + process_bus_resume(rhport); + } + if (is & USB_ISTAT_SOFTOK_MASK) { KHCI->ISTAT = USB_ISTAT_SOFTOK_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - return; } + if (is & USB_ISTAT_STALL_MASK) { KHCI->ISTAT = USB_ISTAT_STALL_MASK; process_stall(rhport); - return; } + if (is & USB_ISTAT_TOKDNE_MASK) { process_tokdne(rhport); - return; } } diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 519d09151..0f500a88f 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -311,14 +311,15 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) } //------------- Realize Endpoint with Max Packet Size -------------// - set_ep_size(ep_id, p_endpoint_desc->wMaxPacketSize.size); + const uint16_t ep_size = tu_edpt_packet_size(p_endpoint_desc); + set_ep_size(ep_id, ep_size); //------------- first DD prepare -------------// dma_desc_t* const dd = &_dcd.dd[ep_id]; tu_memclr(dd, sizeof(dma_desc_t)); dd->isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - dd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size; + dd->max_packet_size = ep_size; dd->retired = 1; // invalid at first sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS + ep_id, 1, 0); // clear all endpoint status @@ -326,6 +327,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 4392d1882..1bdf72d6d 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -323,6 +323,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + static void prepare_setup_packet(uint8_t rhport) { if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index eeab3f487..f6433293d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -29,6 +29,8 @@ #if TUSB_OPT_DEVICE_ENABLED && \ (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) +#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly" + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ @@ -57,11 +59,15 @@ // ENDPTCTRL enum { ENDPTCTRL_STALL = TU_BIT(0), - ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), ///< used for test only + ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only ENDPTCTRL_TOGGLE_RESET = TU_BIT(6), ENDPTCTRL_ENABLE = TU_BIT(7) }; +enum { + ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field +}; + // USBSTS, USBINTR enum { INTR_USB = TU_BIT(0), @@ -91,12 +97,15 @@ typedef struct uint32_t : 3 ; uint32_t int_on_complete : 1 ; volatile uint32_t total_bytes : 15 ; - uint32_t : 0 ; + uint32_t : 1 ; // Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous - //------------- DCD Area -------------// + //--------------------------------------------------------------------+ + // TD is 32 bytes aligned but occupies only 28 bytes + // Therefore there are 4 bytes padding that we can use. + //--------------------------------------------------------------------+ uint16_t expected_bytes; uint8_t reserved[2]; } dcd_qtd_t; @@ -109,11 +118,10 @@ typedef struct // Word 0: Capabilities and Characteristics uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed. uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received. - uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) + uint32_t max_packet_size : 11 ; ///< Endpoint's wMaxPacketSize uint32_t : 2 ; uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length. uint32_t iso_mult : 2 ; ///< - uint32_t : 0 ; // Word 1: Current qTD Pointer volatile uint32_t qtd_addr; @@ -125,10 +133,11 @@ typedef struct volatile tusb_control_request_t setup_request; //--------------------------------------------------------------------+ - /// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes - /// thus there are 16 bytes padding free that we can make use of. + // QHD is 64 bytes aligned but occupies only 48 bytes + // Therefore there are 16 bytes padding that we can use. //--------------------------------------------------------------------+ - uint8_t reserved[16]; + tu_fifo_t * ff; + uint8_t reserved[12]; } dcd_qhd_t; TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); @@ -145,10 +154,6 @@ typedef struct }dcd_controller_t; #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - // Each endpoint with direction (IN/OUT) occupies a queue head - // Therefore QHD_MAX is 2 x max endpoint count - #define QHD_MAX (8*2) - static const dcd_controller_t _dcd_controller[] = { // RT1010 and RT1020 only has 1 USB controller @@ -161,8 +166,6 @@ typedef struct }; #else - #define QHD_MAX (6*2) - static const dcd_controller_t _dcd_controller[] = { { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 }, @@ -174,8 +177,10 @@ typedef struct typedef struct { // Must be at 2K alignment - dcd_qhd_t qhd[QHD_MAX] TU_ATTR_ALIGNED(64); - dcd_qtd_t qtd[QHD_MAX] TU_ATTR_ALIGNED(32); // for portability, TinyUSB only queue 1 TD for each Qhd + // Each endpoint with direction (IN/OUT) occupies a queue head + // for portability, TinyUSB only queue 1 TD for each Qhd + dcd_qhd_t qhd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(64); + dcd_qtd_t qtd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32); }dcd_data_t; CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048) @@ -195,9 +200,9 @@ static void bus_reset(uint8_t rhport) // endpoint type of the unused direction must be changed from the control type to any other // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior // for the data PID tracking on the active endpoint. - for( int i=1; i < _dcd_controller[rhport].ep_count; i++) + for( uint8_t i=1; i < _dcd_controller[rhport].ep_count; i++) { - dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << 2) | (TUSB_XFER_BULK << 18); + dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); } //------------- Clear All Registers -------------// @@ -217,11 +222,11 @@ static void bus_reset(uint8_t rhport) tu_memclr(&_dcd_data, sizeof(dcd_data_t)); //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// - _dcd_data.qhd[0].zero_length_termination = _dcd_data.qhd[1].zero_length_termination = 1; - _dcd_data.qhd[0].max_package_size = _dcd_data.qhd[1].max_package_size = CFG_TUD_ENDPOINT0_SIZE; - _dcd_data.qhd[0].qtd_overlay.next = _dcd_data.qhd[1].qtd_overlay.next = QTD_NEXT_INVALID; + _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1; + _dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; + _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID; - _dcd_data.qhd[0].int_on_setup = 1; // OUT only + _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only } void dcd_init(uint8_t rhport) @@ -238,14 +243,15 @@ void dcd_init(uint8_t rhport) dcd_reg->USBMODE = USBMODE_CM_DEVICE; dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION; - // TODO Force fullspeed on non-highspeed port - // dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; +#if !TUD_OPT_HIGH_SPEED + dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; +#endif CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment dcd_reg->USBSTS = dcd_reg->USBSTS; - dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/; + dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND; dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect @@ -272,7 +278,8 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME; } void dcd_connect(uint8_t rhport) @@ -290,26 +297,33 @@ void dcd_disconnect(uint8_t rhport) //--------------------------------------------------------------------+ // HELPER //--------------------------------------------------------------------+ -// index to bit position in register -static inline uint8_t ep_idx2bit(uint8_t ep_idx) -{ - return ep_idx/2 + ( (ep_idx%2) ? 16 : 0); -} static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) { + // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the + // address to 32-byte boundaries. Buffer must be word aligned + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31); + tu_memclr(p_qtd, sizeof(dcd_qtd_t)); - p_qtd->next = QTD_NEXT_INVALID; - p_qtd->active = 1; - p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + p_qtd->next = QTD_NEXT_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + p_qtd->int_on_complete = true; if (data_ptr != NULL) { - p_qtd->buffer[0] = (uint32_t) data_ptr; + p_qtd->buffer[0] = (uint32_t) data_ptr; + + uint32_t const bufend = p_qtd->buffer[0] + total_bytes; for(uint8_t i=1; i<5; i++) { - p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; + uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096; + if ( bufend <= next_page ) break; + + p_qtd->buffer[i] = next_page; + + // TODO page[1] FRAME_N for ISO transfer } } } @@ -324,12 +338,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0); + + // flush to abort any primed buffer + dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0)); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // data toggle also need to be reset dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; @@ -339,39 +356,87 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - // TODO not support ISO yet - TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - uint8_t const ep_idx = 2*epnum + dir; + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); // Must not exceed max endpoint number TU_ASSERT( epnum < _dcd_controller[rhport].ep_count ); //------------- Prepare Queue Head -------------// - dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx]; + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; tu_memclr(p_qhd, sizeof(dcd_qhd_t)); p_qhd->zero_length_termination = 1; - p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; + p_qhd->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); + if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + { + p_qhd->iso_mult = 1; + } + p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); // Enable EP Control dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; - dcd_reg->ENDPTCTRL[epnum] |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0); + + uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; + + if ( dir == TUSB_DIR_OUT ) + { + dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl; + }else + { + dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16); + } return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +void dcd_edpt_close_all (uint8_t rhport) { dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const ep_idx = 2*epnum + dir; + + // Disable all non-control endpoints + for( uint8_t epnum=1; epnum < _dcd_controller[rhport].ep_count; epnum++) + { + _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; + _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1; + + dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16); + dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); + } +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + + _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + + // Flush EP + uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); + dcd_reg->ENDPTFLUSH = flush_mask; + while(dcd_reg->ENDPTFLUSH & flush_mask); + + // Clear EP enable + dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0)); +} + +static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) +{ + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir]; + + p_qhd->qtd_overlay.halted = false; // clear any previous error + p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd + + // flush cache + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); if ( epnum == 0 ) { @@ -380,23 +445,87 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {} } - dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx]; - dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx]; - - // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the - // address to 32-byte boundaries. - // void* cast to suppress cast-align warning, buffer must be - CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); - - //------------- Prepare qtd -------------// - qtd_init(p_qtd, buffer, total_bytes); - p_qtd->int_on_complete = true; - p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd - - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); - // start transfer - dcd_reg->ENDPTPRIME = TU_BIT( ep_idx2bit(ep_idx) ) ; + dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0)); +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir]; + + // Prepare qtd + qtd_init(p_qtd, buffer, total_bytes); + + // Start qhd transfer + p_qhd->ff = NULL; + qhd_start_xfer(rhport, epnum, dir); + + return true; +} + +// fifo has to be aligned to 4k boundary +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir]; + + tu_fifo_buffer_info_t fifo_info; + + if (dir) + { + tu_fifo_get_read_info(ff, &fifo_info); + } else + { + tu_fifo_get_write_info(ff, &fifo_info); + } + + if ( fifo_info.len_lin >= total_bytes ) + { + // Linear length is enough for this transfer + qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes); + } + else + { + // linear part is not enough + + // prepare TD up to linear length + qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin); + + if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) ) + { + // If buffer is aligned to 4K & buffer size is multiple of 4K + // We can make use of buffer page array to also combine the linear + wrapped length + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + + for(uint8_t i = 1, page = 0; i < 5; i++) + { + // pick up buffer array where linear ends + if (p_qtd->buffer[i] == 0) + { + p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page; + page++; + } + } + + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31); + } + else + { + // TODO we may need to carry the wrapped length after the linear part complete + // for now only transfer up to linear part + } + } + + // Start qhd transfer + p_qhd->ff = ff; + qhd_start_xfer(rhport, epnum, dir); return true; } @@ -404,9 +533,42 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ + +static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir) +{ + dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; + dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir]; + + uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED : + ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; + + if ( result != XFER_RESULT_SUCCESS ) + { + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + // flush to abort error buffer + dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0)); + } + + uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes; + + if (p_qhd->ff) + { + if (dir == TUSB_DIR_IN) + { + tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes); + } else + { + tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes); + } + } + + // only number of bytes in the IOC qtd + dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true); +} + void dcd_int_handler(uint8_t rhport) { - dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; uint32_t const int_enable = dcd_reg->USBINTR; uint32_t const int_status = dcd_reg->USBSTS & int_enable; @@ -415,18 +577,46 @@ void dcd_int_handler(uint8_t rhport) // disabled interrupt sources if (int_status == 0) return; - if (int_status & INTR_RESET) - { - bus_reset(rhport); - uint32_t speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS; - dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true); - } + // Set if the port controller enters the full or high-speed operational state. + // either from Bus Reset or Suspended state + if (int_status & INTR_PORT_CHANGE) + { + // TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1); + + // Reset interrupt is not enabled, we manually check if Port Change is due + // to connection / disconnection + if ( dcd_reg->USBSTS & INTR_RESET ) + { + dcd_reg->USBSTS = INTR_RESET; + + if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS) + { + uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS; + bus_reset(rhport); + dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true); + }else + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + } + else + { + // Triggered by resuming from suspended state + if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) ) + { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + } + } if (int_status & INTR_SUSPEND) { + // TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1); + if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND) { // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. + // Skip suspend event if we are not addressed if ((dcd_reg->DEVICEADDR >> 25) & 0x0f) { dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); @@ -434,21 +624,11 @@ void dcd_int_handler(uint8_t rhport) } } - // Make sure we read the latest version of _dcd_data. - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); - - // TODO disconnection does not generate interrupt !!!!!! -// if (int_status & INTR_PORT_CHANGE) -// { -// if ( !(dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS) ) -// { -// dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_UNPLUGGED }; -// dcd_event_handler(&event, true); -// } -// } - if (int_status & INTR_USB) { + // Make sure we read the latest version of _dcd_data. + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE; dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge @@ -456,26 +636,21 @@ void dcd_int_handler(uint8_t rhport) { //------------- Set up Received -------------// // 23.10.10.2 Operational model for setup transfers - dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;// acknowledge + dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT; - dcd_event_setup_received(rhport, (uint8_t*) &_dcd_data.qhd[0].setup_request, true); + dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true); } + // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set + // nothing to do, we will submit xfer as error to usbd + // if (int_status & INTR_ERROR) { } + if ( edpt_complete ) { - for(uint8_t ep_idx = 0; ep_idx < QHD_MAX; ep_idx++) + for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++) { - if ( tu_bit_test(edpt_complete, ep_idx2bit(ep_idx)) ) - { - // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set - dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx]; - - uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED : - ( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; - - uint8_t const ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 ); - dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd - } + if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT); + if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN); } } } @@ -484,9 +659,6 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } - - if (int_status & INTR_NAK) {} - if (int_status & INTR_ERROR) TU_ASSERT(false, ); } #endif diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index d216f0728..81ad3152d 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -31,6 +31,8 @@ #if TUSB_OPT_HOST_ENABLED && \ (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) +#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly" + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index bcee34938..daa8075b7 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -412,7 +412,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } TU_ASSERT(p_ed); - ed_init( p_ed, dev_addr, ep_desc->wMaxPacketSize.size, ep_desc->bEndpointAddress, + ed_init( p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, ep_desc->bmAttributes.xfer, ep_desc->bInterval ); // control of dev0 is used as static async head diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 49284e92e..e084478e0 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -70,7 +70,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) { // size must be multiple of 64 - uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; + uint size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; // double buffered Bulk endpoint if ( transfer_type == TUSB_XFER_BULK ) @@ -88,7 +88,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) pico_info(" Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf); // Fill in endpoint control register with buffer offset - uint32_t const reg = EP_CTRL_ENABLE_BITS | (transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; *ep->endpoint_control = reg; } @@ -124,9 +124,7 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t // For device, IN is a tx transfer and OUT is an rx transfer ep->rx = (dir == TUSB_DIR_OUT); - // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = (num == 0 ? 1u : 0u); - + ep->next_pid = 0u; ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; @@ -145,8 +143,7 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t if ( num == 0 ) { - // EP0 has no endpoint control register because - // the buffer offsets are fixed + // EP0 has no endpoint control register because the buffer offsets are fixed ep->endpoint_control = NULL; // Buffer offset is fixed (also double buffered) @@ -178,16 +175,18 @@ static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_by static void hw_handle_buff_status(void) { uint32_t remaining_buffers = usb_hw->buf_status; - pico_trace("buf_status 0x%08x\n", remaining_buffers); + pico_trace("buf_status = 0x%08x\n", remaining_buffers); uint bit = 1u; - for (uint i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) + for (uint8_t i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) { if (remaining_buffers & bit) { // clear this in advance usb_hw_clear->buf_status = bit; + // IN transfer for even i, OUT transfer for odd i struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, !(i & 1u)); + // Continue xfer bool done = hw_endpoint_xfer_continue(ep); if (done) @@ -202,7 +201,7 @@ static void hw_handle_buff_status(void) } } -static void reset_ep0(void) +static void reset_ep0_pid(void) { // If we have finished this transfer on EP0 set pid back to 1 for next // setup transfer. Also clear a stall in case @@ -214,14 +213,18 @@ static void reset_ep0(void) } } -static void reset_all_endpoints(void) +static void reset_non_control_endpoints(void) { - memset(hw_endpoints, 0, sizeof(hw_endpoints)); - next_buffer_ptr = &usb_dpram->epx_data[0]; + // Disable all non-control + for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS-1; i++ ) + { + usb_dpram->ep_ctrl[i].in = 0; + usb_dpram->ep_ctrl[i].out = 0; + } - // Init Control endpoint out & in - hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); - hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); + // clear non-control hw endpoints + tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t)); + next_buffer_ptr = &usb_dpram->epx_data[0]; } static void dcd_rp2040_irq(void) @@ -233,8 +236,10 @@ static void dcd_rp2040_irq(void) { handled |= USB_INTS_SETUP_REQ_BITS; uint8_t const *setup = (uint8_t const *)&usb_dpram->setup_packet; - // Clear stall bits and reset pid - reset_ep0(); + + // reset pid to both 1 (data and ack) + reset_ep0_pid(); + // Pass setup packet to tiny usb dcd_event_setup_received(0, setup, true); usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; @@ -274,7 +279,7 @@ static void dcd_rp2040_irq(void) handled |= USB_INTS_BUS_RESET_BITS; usb_hw->dev_addr_ctrl = 0; - reset_all_endpoints(); + reset_non_control_endpoints(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; @@ -325,7 +330,6 @@ static void dcd_rp2040_irq(void) void dcd_init (uint8_t rhport) { - pico_trace("dcd_init %d\n", rhport); assert(rhport == 0); // Reset hardware to default state @@ -338,8 +342,13 @@ void dcd_init (uint8_t rhport) irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); - // reset endpoints - reset_all_endpoints(); + // Init control endpoints + tu_memclr(hw_endpoints[0], 2*sizeof(hw_endpoint_t)); + hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); + hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); + + // Init non-control endpoints + reset_non_control_endpoints(); // Initializes the USB peripheral for device mode and enables it. // Don't need to enable the pull up here. Force VBUS @@ -356,30 +365,28 @@ void dcd_init (uint8_t rhport) dcd_connect(rhport); } -void dcd_int_enable(uint8_t rhport) +void dcd_int_enable(__unused uint8_t rhport) { assert(rhport == 0); irq_set_enabled(USBCTRL_IRQ, true); } -void dcd_int_disable(uint8_t rhport) +void dcd_int_disable(__unused uint8_t rhport) { assert(rhport == 0); irq_set_enabled(USBCTRL_IRQ, false); } -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +void dcd_set_address (__unused uint8_t rhport, __unused uint8_t dev_addr) { - pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); assert(rhport == 0); // Can't set device address in hardware until status xfer has complete // Send 0len complete response on EP0 IN - reset_ep0(); hw_endpoint_xfer(0x80, NULL, 0); } -void dcd_remote_wakeup(uint8_t rhport) +void dcd_remote_wakeup(__unused uint8_t rhport) { pico_info("dcd_remote_wakeup %d\n", rhport); assert(rhport == 0); @@ -387,19 +394,17 @@ void dcd_remote_wakeup(uint8_t rhport) } // disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) +void dcd_disconnect(__unused uint8_t rhport) { - pico_info("dcd_disconnect %d\n", rhport); - assert(rhport == 0); - usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + (void) rhport; + usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } // connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) +void dcd_connect(__unused uint8_t rhport) { - pico_info("dcd_connect %d\n", rhport); - assert(rhport == 0); - usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + (void) rhport; + usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } /*------------------------------------------------------------------*/ @@ -414,21 +419,26 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS ) { - pico_trace("Set HW address %d\n", request->wValue); usb_hw->dev_addr_ctrl = (uint8_t) request->wValue; } - - reset_ep0(); } -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +bool dcd_edpt_open (__unused uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { assert(rhport == 0); - hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); + hw_endpoint_init(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), desc_edpt->bmAttributes.xfer); return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + + // may need to use EP Abort + reset_non_control_endpoints(); +} + +bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { assert(rhport == 0); hw_endpoint_xfer(ep_addr, buffer, total_bytes); @@ -437,8 +447,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_stall %02x\n", ep_addr); - assert(rhport == 0); + (void) rhport; if ( tu_edpt_number(ep_addr) == 0 ) { @@ -448,22 +457,22 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - // TODO check with double buffered - _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); + // stall and clear current pending buffer + // may need to use EP_ABORT + _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr); - assert(rhport == 0); + (void) rhport; if (tu_edpt_number(ep_addr)) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - // clear stall also reset toggle to DATA0 - // TODO check with double buffered - _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL | USB_BUF_CTRL_DATA1_PID); + // clear stall also reset toggle to DATA0, ready for next transfer + ep->next_pid = 0; + _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index e51dfac2b..3e80dd872 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -160,12 +160,11 @@ static void hw_handle_buff_status(void) static void hw_trans_complete(void) { - struct hw_endpoint *ep = &epx; - assert(ep->active); - if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) { pico_trace("Sent setup packet\n"); + struct hw_endpoint *ep = &epx; + assert(ep->active); hw_xfer_complete(ep, XFER_RESULT_SUCCESS); } else @@ -201,7 +200,6 @@ static void hcd_rp2040_irq(void) { handled |= USB_INTS_BUFF_STATUS_BITS; TU_LOG(2, "Buffer complete\n"); - // print_bufctrl32(*epx.buffer_control); hw_handle_buff_status(); } @@ -231,7 +229,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; - print_bufctrl32(*epx.buffer_control); + TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*epx.buffer_control), tu_u32_high16(*epx.buffer_control)); panic("Data Seq Error \n"); } @@ -414,10 +412,28 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) // Close all opened endpoint belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - (void) dev_addr; + pico_trace("hcd_device_close %d\n", dev_addr); + (void) rhport; - pico_trace("hcd_device_close %d\n", dev_addr); + if (dev_addr == 0) return; + + for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) + { + hw_endpoint_t* ep = &ep_pool[i]; + + if (ep->dev_addr == dev_addr && ep->configured) + { + // in case it is an interrupt endpoint, disable it + usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); + usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; + + // unconfigure the endpoint + ep->configured = false; + *ep->endpoint_control = 0; + *ep->buffer_control = 0; + hw_endpoint_reset_transfer(ep); + } + } } uint32_t hcd_frame_number(uint8_t rhport) @@ -455,7 +471,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const _hw_endpoint_init(ep, dev_addr, ep_desc->bEndpointAddress, - ep_desc->wMaxPacketSize.size, + tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer, ep_desc->bInterval); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 43554d28b..c9e2f6b26 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -38,7 +38,7 @@ const char *ep_dir_string[] = { "in", }; -static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { +static inline void _hw_endpoint_lock_update(__unused struct hw_endpoint * ep, __unused int delta) { // todo add critsec as necessary to prevent issues between worker and IRQ... // note that this is perhaps as simple as disabling IRQs because it would make // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. @@ -67,7 +67,6 @@ void rp2040_usb_init(void) void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { - ep->stalled = false; ep->active = false; ep->remaining_len = 0; ep->xferred_len = 0; @@ -108,7 +107,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m static uint32_t prepare_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) { uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); - ep->remaining_len -= buflen; + ep->remaining_len = (uint16_t)(ep->remaining_len - buflen); uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; @@ -171,8 +170,7 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) *ep->endpoint_control = ep_ctrl; - TU_LOG(3, "Prepare Buffer Control:\r\n"); - print_bufctrl32(buf_ctrl); + TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address @@ -216,7 +214,7 @@ static uint16_t sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - ep->xferred_len += xferred_bytes; + ep->xferred_len = (uint16_t)(ep->xferred_len + xferred_bytes); }else { // If we have received some data, so can increase the length @@ -224,14 +222,14 @@ static uint16_t sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) assert(buf_ctrl & USB_BUF_CTRL_FULL); memcpy(ep->user_buf, ep->hw_data_buf + buf_id*64, xferred_bytes); - ep->xferred_len += xferred_bytes; + ep->xferred_len = (uint16_t)(ep->xferred_len + xferred_bytes); ep->user_buf += xferred_bytes; } // Short packet if (xferred_bytes < ep->wMaxPacketSize) { - pico_trace("Short rx transfer on buffer %d with %u bytes\n", buf_id, xferred_bytes); + pico_trace(" Short packet on buffer %d with %u bytes\n", buf_id, xferred_bytes); // Reduce total length as this is last packet ep->remaining_len = 0; } @@ -244,9 +242,8 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // Update hw endpoint struct with info from hardware // after a buff status interrupt - uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - TU_LOG(3, "_hw_endpoint_xfer_sync:\r\n"); - print_bufctrl32(buf_ctrl); + uint32_t __unused buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + TU_LOG(3, " Sync BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); // always sync buffer 0 uint16_t buf0_bytes = sync_ep_buffer(ep, 0); @@ -284,7 +281,7 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) usb_hw->abort &= ~TU_BIT(ep_id); TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr); - print_bufctrl32(buf_ctrl); + TU_LOG(3, " BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl)); #endif } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 5570a731a..a9cf1dd07 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -21,7 +21,7 @@ #define pico_trace(...) TU_LOG(3, __VA_ARGS__) // Hardware information per endpoint -struct hw_endpoint +typedef struct hw_endpoint { // Is this a valid struct bool configured; @@ -42,9 +42,6 @@ struct hw_endpoint // Buffer pointer in usb dpram uint8_t *hw_data_buf; - // Have we been stalled TODO remove later - bool stalled; - // Current transfer information bool active; uint16_t remaining_len; @@ -66,7 +63,7 @@ struct hw_endpoint // If interrupt endpoint uint8_t interrupt_num; #endif -}; +} hw_endpoint_t; void rp2040_usb_init(void); @@ -96,52 +93,4 @@ static inline uintptr_t hw_data_offset(uint8_t *buf) extern const char *ep_dir_string[]; -typedef union TU_ATTR_PACKED -{ - uint16_t u16; - struct TU_ATTR_PACKED - { - uint16_t xfer_len : 10; - uint16_t available : 1; - uint16_t stall : 1; - uint16_t reset_bufsel : 1; - uint16_t data_toggle : 1; - uint16_t last_buf : 1; - uint16_t full : 1; - }; -} rp2040_buffer_control_t; - -TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct"); - -#if CFG_TUSB_DEBUG >= 3 -static inline void print_bufctrl16(uint32_t u16) -{ - rp2040_buffer_control_t bufctrl = { - .u16 = u16 - }; - - TU_LOG(3, "len = %u, available = %u, full = %u, last = %u, stall = %u, reset = %u, toggle = %u\r\n", - bufctrl.xfer_len, bufctrl.available, bufctrl.full, bufctrl.last_buf, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle); -} - -static inline void print_bufctrl32(uint32_t u32) -{ - uint16_t u16; - - u16 = u32 >> 16; - TU_LOG(3, " Buffer Control 1 0x%x: ", u16); - print_bufctrl16(u16); - - u16 = u32 & 0x0000ffff; - TU_LOG(3, " Buffer Control 0 0x%x: ", u16); - print_bufctrl16(u16); -} - -#else - -#define print_bufctrl16(u16) -#define print_bufctrl32(u32) - -#endif - #endif diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 095dcc136..ae7d2fd0c 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -259,7 +259,7 @@ static inline void pipe_wait_for_ready(unsigned num) static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) { - hw_fifo_t *reg = (hw_fifo_t*)fifo; + volatile hw_fifo_t *reg = (volatile hw_fifo_t*) fifo; uintptr_t addr = (uintptr_t)buf; while (len >= 2) { reg->u16 = *(const uint16_t *)addr; @@ -275,7 +275,7 @@ static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) { uint8_t *p = (uint8_t*)buf; - uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ + volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */ while (len--) *p++ = *reg; } @@ -695,7 +695,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; - const unsigned mps = tu_le16toh(ep_desc->wMaxPacketSize.size); + const unsigned mps = tu_edpt_packet_size(ep_desc); if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { /* USBa supports up to 256 bytes */ return false; @@ -711,7 +711,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USB0.PIPESEL.WORD = num; USB0.PIPEMAXP.WORD = mps; volatile uint16_t *ctr = get_pipectr(num); - *ctr = USB_PIPECTR_ACLRM; + *ctr = USB_PIPECTR_ACLRM | USB_PIPECTR_SQCLR; *ctr = 0; unsigned cfg = (dir << 4) | epn; if (xfer == TUSB_XFER_BULK) { @@ -733,6 +733,18 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +void dcd_edpt_close_all(uint8_t rhport) +{ + unsigned i = TU_ARRAY_SIZE(_dcd.pipe); + dcd_int_disable(rhport); + while (--i) { /* Close all pipes except 0 */ + const unsigned ep_addr = _dcd.pipe[i].ep; + if (!ep_addr) continue; + dcd_edpt_close(rhport, ep_addr); + } + dcd_int_enable(rhport); +} + void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void)rhport; diff --git a/src/portable/silabs/efm32/dcd_efm32.c b/src/portable/silabs/efm32/dcd_efm32.c deleted file mode 100644 index bd1f32e6b..000000000 --- a/src/portable/silabs/efm32/dcd_efm32.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Rafael Silva (@perigoso) - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED && ( \ - (CFG_TUSB_MCU == OPT_MCU_EFM32GG) || \ - (CFG_TUSB_MCU == OPT_MCU_EFM32GG11) || \ - (CFG_TUSB_MCU == OPT_MCU_EFM32GG12) ) - -/* Silabs */ -#include "em_device.h" - -#include "device/dcd.h" - -/* - * Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) - * We disable SOF for now until needed later on - */ -#define USE_SOF 0 - -/* - * Number of endpoints - * 12 software-configurable endpoints (6 IN, 6 OUT) in addition to endpoint 0 - */ -#define EP_COUNT 7 - -/* FIFO size in bytes */ -#define EP_FIFO_SIZE 2048 - -/* Max number of IN EP FIFOs */ -#define EP_FIFO_NUM 7 - -/* */ -typedef struct { - uint8_t *buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; -} xfer_ctl_t; - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_COUNT][2]; - -/* Keep count of how many FIFOs are in use */ -static uint8_t _allocated_fifos = 1; /* FIFO0 is always in use */ - -static volatile uint32_t* tx_fifo[EP_FIFO_NUM] = { - USB->FIFO0D, - USB->FIFO1D, - USB->FIFO2D, - USB->FIFO3D, - USB->FIFO4D, - USB->FIFO5D, - USB->FIFO6D, -}; - -/* Register Helpers */ -#define DCTL_WO_BITMASK (USB_DCTL_CGOUTNAK | USB_DCTL_SGOUTNAK | USB_DCTL_CGNPINNAK | USB_DCTL_SGNPINNAK) -#define GUSBCFG_WO_BITMASK (USB_GUSBCFG_CORRUPTTXPKT) -#define DEPCTL_WO_BITMASK (USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF) - -/* Will either return an unused FIFO number, or 0 if all are used. */ -static uint8_t get_free_fifo(void) -{ - if(_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -/* -static void flush_rx_fifo(void) -{ - USB->GRSTCTL = USB_GRSTCTL_RXFFLSH; - while(USB->GRSTCTL & USB_GRSTCTL_RXFFLSH); -} -*/ - -static void flush_tx_fifo(uint8_t fifo_num) -{ - USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | (fifo_num << _USB_GRSTCTL_TXFNUM_SHIFT); - while(USB->GRSTCTL & USB_GRSTCTL_TXFFLSH); -} - -/* Setup the control endpoint 0. */ -static void bus_reset(void) -{ - USB->DOEP0CTL |= USB_DIEP_CTL_SNAK; - for(uint8_t i = 0; i < EP_COUNT - 1; i++) - { - USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK; - } - - /* reset address */ - USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK; - - USB->DAINTMSK |= USB_DAINTMSK_OUTEPMSK0 | USB_DAINTMSK_INEPMSK0; - USB->DOEPMSK |= USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK; - USB->DIEPMSK |= USB_DIEPMSK_TIMEOUTMSK | USB_DIEPMSK_XFERCOMPLMSK; - - /* - * - All EP OUT shared a unique OUT FIFO which uses - * * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - * * 2 locations for OUT endpoint control words. - * * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - * * 1 location for global NAK (not required/used here). - * * It is recommended to allocate 2 times the largest packet size, therefore - * Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - */ - flush_tx_fifo(_USB_GRSTCTL_TXFNUM_FALL); // Flush All - USB->GRXFSIZ = 52; - - /* Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) */ - USB->GNPTXFSIZ = (16 << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT) | (USB->GRXFSIZ & _USB_GNPTXFSIZ_NPTXFSTADDR_MASK); - - /* Ready to receive SETUP packet */ - USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT); - - USB->GINTMSK |= USB_GINTMSK_IEPINTMSK | USB_GINTMSK_OEPINTMSK; -} - -static void enum_done_processing(void) -{ - /* Maximum packet size for EP 0 is set for both directions by writing DIEPCTL */ - if((USB->DSTS & _USB_DSTS_ENUMSPD_MASK) == USB_DSTS_ENUMSPD_FS) - { - /* Full Speed (PHY on 48 MHz) */ - USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_64B; /* Maximum Packet Size 64 bytes */ - USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */ - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } - else - { - /* Low Speed (PHY on 6 MHz) */ - USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_8B; /* Maximum Packet Size 64 bytes */ - USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */ - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API */ -/*------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - (void) rhport; - - /* Reset Core */ - USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK; - USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE); - - /* Core Soft Reset */ - USB->GRSTCTL |= USB_GRSTCTL_CSFTRST; - while(USB->GRSTCTL & USB_GRSTCTL_CSFTRST); - - while(!(USB->GRSTCTL & USB_GRSTCTL_AHBIDLE)); - - /* Enable PHY pins */ - USB->ROUTE = USB_ROUTE_PHYPEN; - - dcd_disconnect(rhport); - - /* - * Set device speed (Full speed PHY) - * Stall on non-zero len status OUT packets (ctrl transfers) - * periodic frame interval to 80% - */ - USB->DCFG = (USB->DCFG & ~(_USB_DCFG_DEVSPD_MASK | _USB_DCFG_PERFRINT_MASK)) | USB_DCFG_DEVSPD_FS | USB_DCFG_NZSTSOUTHSHK; - - /* Enable Global Interrupts */ - USB->GAHBCFG = (USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK) | USB_GAHBCFG_GLBLINTRMSK; - - /* Force Device Mode */ - USB->GUSBCFG = (USB->GUSBCFG & ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE)) | USB_GUSBCFG_FORCEDEVMODE; - - /* No Overrides */ - USB->GOTGCTL &= ~(USB_GOTGCTL_BVALIDOVVAL | USB_GOTGCTL_BVALIDOVEN | USB_GOTGCTL_VBVALIDOVVAL); - - /* Ignore frame numbers on ISO transfers. */ - USB->DCTL = (USB->DCTL & ~DCTL_WO_BITMASK) | USB_DCTL_IGNRFRMNUM; - - /* Setting SNAKs */ - USB->DOEP0CTL |= USB_DIEP_CTL_SNAK; - for(uint8_t i = 0; i < EP_COUNT - 1; i++) - { - USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK; - } - - /* D. Interruption masking */ - /* Disable all device interrupts */ - USB->DIEPMSK = 0; - USB->DOEPMSK = 0; - USB->DAINTMSK = 0; - USB->DIEPEMPMSK = 0; - USB->GINTMSK = 0; - USB->GOTGINT = ~0U; /* clear OTG ints */ - USB->GINTSTS = ~0U; /* clear pending ints */ - USB->GINTMSK = USB_GINTMSK_MODEMISMSK | - #if USE_SOF - USB_GINTMSK_SOFMSK | - #endif - USB_GINTMSK_ERLYSUSPMSK | - USB_GINTMSK_USBSUSPMSK | - USB_GINTMSK_USBRSTMSK | - USB_GINTMSK_ENUMDONEMSK | - USB_GINTMSK_RESETDETMSK | - USB_GINTMSK_DISCONNINTMSK; - - NVIC_ClearPendingIRQ(USB_IRQn); - - dcd_connect(rhport); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void) rhport; - - USB->DCFG = (USB->DCFG & ~_USB_DCFG_DEVADDR_MASK) | (dev_addr << _USB_DCFG_DEVADDR_SHIFT); - - /* Response with status after changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void) rhport; -} - -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - - /* connect by enabling internal pull-up resistor on D+/D- */ - USB->DCTL &= ~(DCTL_WO_BITMASK | USB_DCTL_SFTDISCON); -} - -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - - /* disconnect by disabling internal pull-up resistor on D+/D- */ - USB->DCTL = (USB->DCTL & ~(DCTL_WO_BITMASK)) | USB_DCTL_SFTDISCON; -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint Port */ -/*------------------------------------------------------------------*/ -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if(dir == TUSB_DIR_IN) - { - if(epnum == 0) - { - USB->DIEP0CTL = (USB->DIEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_SNAK | USB_DIEP0CTL_STALL; - - flush_tx_fifo(_USB_GRSTCTL_TXFNUM_F0); - } - else - { - /* Only disable currently enabled non-control endpoint */ - if(USB->DIEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA) - { - USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL; - while(!(USB->DIEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD)); - USB->DIEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD; - } - else - { - USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL; - } - - /* Flush the FIFO */ - uint8_t const fifo_num = ((USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_TXFNUM_MASK) >> _USB_DIEP_CTL_TXFNUM_SHIFT); - flush_tx_fifo(fifo_num); - } - } - else - { - if(epnum == 0) - { - USB->DOEP0CTL = (USB->DOEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_STALL; - } - else - { - /* Only disable currently enabled non-control endpoint */ - if(USB->DOEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA) - { - /* Asserting GONAK is required to STALL an OUT endpoint. */ - USB->DCTL |= USB_DCTL_SGOUTNAK; - while(!(USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF)); - - /* Disable the endpoint. Note that only STALL and not SNAK is set here. */ - USB->DOEP[epnum - 1].CTL = (USB->DOEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_STALL; - while(USB->DOEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD); - USB->DOEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD; - - /* Allow other OUT endpoints to keep receiving. */ - USB->DCTL |= USB_DCTL_CGOUTNAK; - } - else - { - USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_STALL; - } - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if(dir == TUSB_DIR_IN) - { - if(epnum == 0) - { - USB->DIEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP0CTL_STALL); - } - else - { - USB->DIEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP_CTL_STALL); - - /* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */ - uint8_t eptype = (USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_EPTYPE_MASK) >> _USB_DIEP_CTL_EPTYPE_SHIFT; - - if((eptype == _USB_DIEP_CTL_EPTYPE_BULK) || (eptype == _USB_DIEP_CTL_EPTYPE_INT)) - { - USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_SETD0PIDEF; - } - } - } - else - { - if(epnum == 0) - { - USB->DOEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP0CTL_STALL); - } - else - { - USB->DOEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP_CTL_STALL); - - /* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */ - uint8_t eptype = (USB->DOEP[epnum - 1].CTL & _USB_DOEP_CTL_EPTYPE_MASK) >> _USB_DOEP_CTL_EPTYPE_SHIFT; - - if((eptype == _USB_DOEP_CTL_EPTYPE_BULK) || (eptype == _USB_DOEP_CTL_EPTYPE_INT)) - { - USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_SETD0PIDEF; - } - } - } -} - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - - TU_ASSERT(p_endpoint_desc->wMaxPacketSize.size <= 64); - TU_ASSERT(epnum < EP_COUNT); - TU_ASSERT(epnum != 0); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = p_endpoint_desc->wMaxPacketSize.size; - - if(dir == TUSB_DIR_OUT) - { - USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_USBACTEP | - (p_endpoint_desc->bmAttributes.xfer << _USB_DOEP_CTL_EPTYPE_SHIFT) | - (p_endpoint_desc->wMaxPacketSize.size << _USB_DOEP_CTL_MPS_SHIFT); - USB->DAINTMSK |= (1 << (_USB_DAINTMSK_OUTEPMSK0_SHIFT + epnum)); - } - else - { - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - USB->DIEP[epnum - 1].CTL &= ~(_USB_DIEP_CTL_TXFNUM_MASK | _USB_DIEP_CTL_EPTYPE_MASK | USB_DIEP_CTL_SETD0PIDEF | _USB_DIEP_CTL_MPS_MASK); - USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_USBACTEP | - (fifo_num << _USB_DIEP_CTL_TXFNUM_SHIFT) | - (p_endpoint_desc->bmAttributes.xfer << _USB_DIEP_CTL_EPTYPE_SHIFT) | - ((p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) ? USB_DIEP_CTL_SETD0PIDEF : 0) | - (p_endpoint_desc->wMaxPacketSize.size << 0); - - USB->DAINTMSK |= (1 << epnum); - - /* Both TXFD and TXSA are in unit of 32-bit words. */ - /* IN FIFO 0 was configured during enumeration, hence the "+ 16". */ - uint16_t const allocated_size = (USB->GRXFSIZ & _USB_GRXFSIZ_RXFDEP_MASK) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - /* DIEPTXF starts at FIFO #1. */ - volatile uint32_t* usb_dieptxf = &USB->DIEPTXF1; - usb_dieptxf[epnum - 1] = (fifo_size << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT) | fifo_offset; - } - return true; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if(short_packet_size > 0 || (total_bytes == 0)) - { - num_packets++; - } - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if(dir == TUSB_DIR_IN) - { - if(epnum == 0) - { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB->DIEP0TSIZ = (num_packets << _USB_DIEP0TSIZ_PKTCNT_SHIFT) | total_bytes; - USB->DIEP0CTL |= USB_DIEP0CTL_EPENA | USB_DIEP0CTL_CNAK; // Enable | CNAK - } - else - { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB->DIEP[epnum - 1].TSIZ = (num_packets << _USB_DIEP_TSIZ_PKTCNT_SHIFT) | total_bytes; - USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_EPENA | USB_DIEP_CTL_CNAK; // Enable | CNAK - } - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) - { - USB->DIEPEMPMSK |= (1 << epnum); - } - } - else - { - if(epnum == 0) - { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT); - USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK; - } - else - { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB->DOEP[epnum - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT); - USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK; - } - } - return true; -} - -/*------------------------------------------------------------------*/ -/* IRQ */ -/*------------------------------------------------------------------*/ -void dcd_int_enable(uint8_t rhport) -{ - (void) rhport; - - NVIC_EnableIRQ(USB_IRQn); -} - -void dcd_int_disable(uint8_t rhport) -{ - (void) rhport; - - NVIC_DisableIRQ(USB_IRQn); -} - -static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size) -{ - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if(remaining <= xfer->max_size) - { - /* Avoid buffer overflow. */ - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } - else - { - /* Room for full packet, choose recv_size based on what the microcontroller claims. */ - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - /* Do not assume xfer buffer is aligned. */ - uint8_t *base = (xfer->buffer + xfer->queued_len); - - /* This for loop always runs at least once- skip if less than 4 bytes to collect. */ - if(to_recv_size >= 4) - { - for(uint16_t i = 0; i < to_recv_size_aligned; i += 4) - { - uint32_t tmp = (*USB->FIFO0D); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - /* Do not read invalid bytes from RX FIFO. */ - if(to_recv_rem != 0) - { - uint32_t tmp = (*USB->FIFO0D); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if(to_recv_rem > 1) - { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if(to_recv_rem > 2) - { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - - xfer->queued_len += xfer_size; - - /* Per USB spec, a short OUT packet (including length 0) is always */ - /* indicative of the end of a transfer (at least for ctl, bulk, int). */ - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, uint8_t fifo_num) -{ - uint16_t remaining; - if(fifo_num == 0) - { - remaining = (USB->DIEP0TSIZ & 0x7FFFFU) >> _USB_DIEP0TSIZ_XFERSIZE_SHIFT; - } - else - { - remaining = (USB->DIEP[fifo_num - 1].TSIZ & 0x7FFFFU) >> _USB_DIEP_TSIZ_XFERSIZE_SHIFT; - } - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - /* Buffer might not be aligned to 32b, so we need to force alignment by copying to a temp var. */ - uint8_t *base = (xfer->buffer + xfer->queued_len); - - /* This for loop always runs at least once- skip if less than 4 bytes to send off. */ - if(to_xfer_size >= 4) - { - for(uint16_t i = 0; i < to_xfer_size_aligned; i += 4) - { - uint32_t tmp = base[i] | (base[i + 1] << 8) | (base[i + 2] << 16) | (base[i + 3] << 24); - *tx_fifo[fifo_num] = tmp; - } - } - - /* Do not read beyond end of buffer if not divisible by 4. */ - if(to_xfer_rem != 0) - { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if(to_xfer_rem > 1) - { - tmp |= (last_32b_bound[1] << 8); - } - if(to_xfer_rem > 2) - { - tmp |= (last_32b_bound[2] << 16); - } - - *tx_fifo[fifo_num] = tmp; - } -} - -static void read_rx_fifo(void) -{ - /* - * Pop control word off FIFO (completed xfers will have 2 control words, - * we only pop one ctl word each interrupt). - */ - uint32_t const ctl_word = USB->GRXSTSP; - uint8_t const pktsts = (ctl_word & _USB_GRXSTSP_PKTSTS_MASK) >> _USB_GRXSTSP_PKTSTS_SHIFT; - uint8_t const epnum = (ctl_word & _USB_GRXSTSP_CHNUM_MASK ) >> _USB_GRXSTSP_CHNUM_SHIFT; - uint16_t const bcnt = (ctl_word & _USB_GRXSTSP_BCNT_MASK ) >> _USB_GRXSTSP_BCNT_SHIFT; - - switch(pktsts) - { - case 0x01: /* Global OUT NAK (Interrupt) */ - break; - - case 0x02: - { - /* Out packet recvd */ - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: - /* Out packet done (Interrupt) */ - break; - - case 0x04: - /* Step 2: Setup transaction completed (Interrupt) */ - /* After this event, OEPINT interrupt will occur with SETUP bit set */ - if(epnum == 0) - { - USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT); - } - - break; - - case 0x06: - { - /* Step1: Setup data packet received */ - - /* - * We can receive up to three setup packets in succession, but - * only the last one is valid. Therefore we just overwrite it - */ - _setup_packet[0] = (*USB->FIFO0D); - _setup_packet[1] = (*USB->FIFO0D); - } - break; - - default: - /* Invalid, breakpoint. */ - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - - for(uint8_t n = 0; n < EP_COUNT; n++) - { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if(n == 0) - { - if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n))) - { - // SETUP packet Setup Phase done. - if((USB->DOEP0INT & USB_DOEP0INT_SETUP)) - { - USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD | USB_DOEP0INT_SETUP; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if(USB->DOEP0INT & USB_DOEP0INT_XFERCOMPL) - { - USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL; - - // Transfer complete if short packet or total len is transferred - if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) - { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } - else - { - // Schedule another packet to be received. - USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT); - USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK; - } - } - } - } - else - { - if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n))) - { - // SETUP packet Setup Phase done. - if((USB->DOEP[n - 1].INT & USB_DOEP_INT_SETUP)) - { - USB->DOEP[n - 1].INT = USB_DOEP_INT_STUPPKTRCVD | USB_DOEP_INT_SETUP; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if(USB->DOEP[n - 1].INT & USB_DOEP_INT_XFERCOMPL) - { - USB->DOEP[n - 1].INT = USB_DOEP_INT_XFERCOMPL; - - // Transfer complete if short packet or total len is transferred - if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) - { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } - else - { - // Schedule another packet to be received. - USB->DOEP[n - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT); - USB->DOEP[n - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK; - } - } - } - } - } -} - -static void handle_epin_ints(void) -{ - - for(uint32_t n = 0; n < EP_COUNT; n++) - { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if(n == 0) - { - if(USB->DAINT & (1 << n)) - { - /* IN XFER complete (entire xfer). */ - if(USB->DIEP0INT & USB_DIEP0INT_XFERCOMPL) - { - USB->DIEP0INT = USB_DIEP0INT_XFERCOMPL; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - /* XFER FIFO empty */ - if(USB->DIEP0INT & USB_DIEP0INT_TXFEMP) - { - USB->DIEP0INT = USB_DIEP0INT_TXFEMP; - transmit_packet(xfer, n); - - /* Turn off TXFE if all bytes are written. */ - if(xfer->queued_len == xfer->total_len) - { - USB->DIEPEMPMSK &= ~(1 << n); - } - } - - /* XFER Timeout */ - if(USB->DIEP0INT & USB_DIEP0INT_TIMEOUT) - { - /* Clear interrupt or enpoint will hang. */ - USB->DIEP0INT = USB_DIEP0INT_TIMEOUT; - } - } - } - else - { - if(USB->DAINT & (1 << n)) - { - /* IN XFER complete (entire xfer). */ - if(USB->DIEP[n - 1].INT & USB_DIEP_INT_XFERCOMPL) - { - USB->DIEP[n - 1].INT = USB_DIEP_INT_XFERCOMPL; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - /* XFER FIFO empty */ - if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TXFEMP) - { - USB->DIEP[n - 1].INT = USB_DIEP_INT_TXFEMP; - transmit_packet(xfer, n); - - /* Turn off TXFE if all bytes are written. */ - if(xfer->queued_len == xfer->total_len) - { - USB->DIEPEMPMSK &= ~(1 << n); - } - } - - /* XFER Timeout */ - if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TIMEOUT) - { - /* Clear interrupt or enpoint will hang. */ - USB->DIEP[n - 1].INT = USB_DIEP_INT_TIMEOUT; - } - } - } - } -} - -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; - - const uint32_t int_status = USB->GINTSTS; - - /* USB Reset */ - if(int_status & USB_GINTSTS_USBRST) - { - /* start of reset */ - USB->GINTSTS = USB_GINTSTS_USBRST; - /* FIFOs will be reassigned when the endpoints are reopen */ - _allocated_fifos = 1; - bus_reset(); - } - - /* Reset detected Interrupt */ - if(int_status & USB_GINTSTS_RESETDET) - { - USB->GINTSTS = USB_GINTSTS_RESETDET; - bus_reset(); - } - - /* Enumeration Done */ - if(int_status & USB_GINTSTS_ENUMDONE) - { - /* This interrupt is considered the end of reset. */ - USB->GINTSTS = USB_GINTSTS_ENUMDONE; - enum_done_processing(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); - } - - /* OTG Interrupt */ - if(int_status & USB_GINTSTS_OTGINT) - { - /* OTG INT bit is read-only */ - - uint32_t const otg_int = USB->GOTGINT; - - if(otg_int & USB_GOTGINT_SESENDDET) - { - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); - } - - USB->GOTGINT = otg_int; - } - - #if USE_SOF - if(int_status & USB_GINTSTS_SOF) - { - USB->GINTSTS = USB_GINTSTS_SOF; - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } - #endif - - /* RxFIFO Non-Empty */ - if(int_status & USB_GINTSTS_RXFLVL) - { - /* RXFLVL bit is read-only */ - - /* Mask out RXFLVL while reading data from FIFO */ - USB->GINTMSK &= ~USB_GINTMSK_RXFLVLMSK; - read_rx_fifo(); - USB->GINTMSK |= USB_GINTMSK_RXFLVLMSK; - } - - /* OUT Endpoints Interrupt */ - if(int_status & USB_GINTMSK_OEPINTMSK) - { - /* OEPINT is read-only */ - handle_epout_ints(); - } - - /* IN Endpoints Interrupt */ - if(int_status & USB_GINTMSK_IEPINTMSK) - { - /* IEPINT bit read-only */ - handle_epin_ints(); - } - - /* unhandled */ - USB->GINTSTS |= USB_GINTSTS_CURMOD | - USB_GINTSTS_MODEMIS | - USB_GINTSTS_OTGINT | - USB_GINTSTS_NPTXFEMP | - USB_GINTSTS_GINNAKEFF | - USB_GINTSTS_GOUTNAKEFF | - USB_GINTSTS_ERLYSUSP | - USB_GINTSTS_USBSUSP | - USB_GINTSTS_ISOOUTDROP | - USB_GINTSTS_EOPF | - USB_GINTSTS_EPMIS | - USB_GINTSTS_INCOMPISOIN | - USB_GINTSTS_INCOMPLP | - USB_GINTSTS_FETSUSP | - USB_GINTSTS_PTXFEMP; -} - -#endif diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 834976468..dfe409383 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -134,7 +134,7 @@ static int _dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev if (usbdcd_driver.setup_processed) { usbdcd_driver.setup_processed = false; - dcd_event_setup_received(0, (uint8_t *) ctrl, true); + dcd_event_setup_received(0, (uint8_t const *) ctrl, true); } else { @@ -257,6 +257,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); uint8_t xfrtype = 0; + uint16_t const ep_mps = tu_edpt_packet_size(p_endpoint_desc); + struct usb_epdesc_s epdesc; if (epnum >= CXD56_EPNUM) @@ -287,7 +289,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]); if (usbdcd_driver.req[epnum] != NULL) { - usbdcd_driver.req[epnum]->len = p_endpoint_desc->wMaxPacketSize.size; + usbdcd_driver.req[epnum]->len = ep_mps; } else { @@ -300,8 +302,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) epdesc.type = p_endpoint_desc->bDescriptorType; epdesc.addr = p_endpoint_desc->bEndpointAddress; epdesc.attr = xfrtype; - epdesc.mxpacketsize[0] = LSBYTE(p_endpoint_desc->wMaxPacketSize.size); - epdesc.mxpacketsize[1] = MSBYTE(p_endpoint_desc->wMaxPacketSize.size); + epdesc.mxpacketsize[0] = LSBYTE(ep_mps); + epdesc.mxpacketsize[1] = MSBYTE(ep_mps); epdesc.interval = p_endpoint_desc->bInterval; if (EP_CONFIGURE(usbdcd_driver.ep[epnum], &epdesc, false) < 0) @@ -312,6 +314,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index eeba7204f..177a7ad2a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -109,13 +109,10 @@ #define STM32F1_FSDEV #endif -#if (TUSB_OPT_DEVICE_ENABLED) && ( \ - (CFG_TUSB_MCU == OPT_MCU_STM32F0 ) || \ - (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_FSDEV)) || \ - (CFG_TUSB_MCU == OPT_MCU_STM32F3 ) || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L1 ) \ - ) +#if TUSB_OPT_DEVICE_ENABLED && \ + ( TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F3, OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32G4) || \ + (TU_CHECK_MCU(OPT_MCU_STM32F1) && defined(STM32F1_FSDEV)) \ + ) // In order to reduce the dependance on HAL, we undefine this. // Some definitions are copied to our private include file. @@ -299,8 +296,10 @@ void dcd_int_enable (uint8_t rhport) __ISB(); #if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_EnableIRQ(USB_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 NVIC_EnableIRQ(USB_LP_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from // shared USB/CAN IRQs to separate CAN and USB IRQs. @@ -323,6 +322,12 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + NVIC_EnableIRQ(USB_HP_IRQn); + NVIC_EnableIRQ(USB_LP_IRQn); + NVIC_EnableIRQ(USBWakeUp_IRQn); + #else #error Unknown arch in USB driver #endif @@ -359,6 +364,12 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + NVIC_DisableIRQ(USB_HP_IRQn); + NVIC_DisableIRQ(USB_LP_IRQn); + NVIC_DisableIRQ(USBWakeUp_IRQn); + #else #error Unknown arch in USB driver #endif @@ -394,7 +405,7 @@ static const tusb_desc_endpoint_t ep0OUT_desc = .bEndpointAddress = 0x00, .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, .bInterval = 0 }; @@ -405,7 +416,7 @@ static const tusb_desc_endpoint_t ep0IN_desc = .bEndpointAddress = 0x80, .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, .bInterval = 0 }; @@ -741,7 +752,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc (void)rhport; uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - const uint16_t epMaxPktSize = p_endpoint_desc->wMaxPacketSize.size; + const uint16_t epMaxPktSize = tu_edpt_packet_size(p_endpoint_desc); uint16_t pma_addr; uint32_t wType; @@ -778,19 +789,19 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc // or being double-buffered (bulk endpoints) pcd_clear_ep_kind(USB,0); - pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); + pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, epMaxPktSize); if(dir == TUSB_DIR_IN) { *pcd_ep_tx_address_ptr(USB, epnum) = pma_addr; - pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); + pcd_set_ep_tx_cnt(USB, epnum, epMaxPktSize); pcd_clear_tx_dtog(USB, epnum); pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK); } else { *pcd_ep_rx_address_ptr(USB, epnum) = pma_addr; - pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); + pcd_set_ep_rx_cnt(USB, epnum, epMaxPktSize); pcd_clear_rx_dtog(USB, epnum); pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); } @@ -800,6 +811,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + /** * Close an endpoint. * diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index eca8bf575..596f7be6c 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -87,6 +87,10 @@ #include "stm32l1xx.h" #define PMA_LENGTH (512u) +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + #include "stm32g4xx.h" + #define PMA_LENGTH (1024u) + #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 8a998aa3a..4782ead8c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -96,6 +96,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 #include "synopsys_common.h" +// for remote wakeup delay +#define __NOP() __asm volatile ("nop") + // These numbers are the same for the whole GD32VF103 family. #define OTG_FS_IRQn 86 #define EP_MAX_FS 4 @@ -213,17 +216,18 @@ static void bus_reset(uint8_t rhport) tu_memclr(xfer_status, sizeof(xfer_status)); _out_ep_closed = false; + // clear device address + dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; + + // 1. NAK for all OUT endpoints for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; } - // clear device address - dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; - - // TODO should probably assign value when reset rather than OR - dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); - dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; + // 2. Un-mask interrupt bits + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + dev->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + dev->DIEPMSK = USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture @@ -307,8 +311,6 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) // Turnaround timeout depends on the MCU clock uint32_t turnaround; - TU_LOG_INT(2, SystemCoreClock); - if ( SystemCoreClock >= 32000000U ) turnaround = 0x6U; else if ( SystemCoreClock >= 27500000U ) @@ -368,7 +370,7 @@ static bool USB_HS_PHYCInit(void) { USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE; - // Enable LDO + // Enable LDO: Note STM32F72/3xx Reference Manual rev 3 June 2018 incorrectly defined this bit as Disabled !! usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; // Wait until LDO ready @@ -556,13 +558,34 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } +static void remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while ( count-- ) + { + __NOP(); + } +} + void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - // TODO must manually clear this bit after 1-15 ms - // USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - // dev->DCTL |= USB_OTG_DCTL_RWUSIG; + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + // set remote wakeup + dev->DCTL |= USB_OTG_DCTL_RWUSIG; + + // enable SOF to detect bus resume + usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_SOFM; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + remote_wakeup_delay(); + + dev->DCTL &= ~USB_OTG_DCTL_RWUSIG; } void dcd_connect(uint8_t rhport) @@ -599,10 +622,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = desc_edpt->wMaxPacketSize.size; + xfer->max_size = tu_edpt_packet_size(desc_edpt); xfer->interval = desc_edpt->bInterval; - uint16_t const fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // Round up to next full word + uint16_t const fifo_size = (xfer->max_size + 3) / 4; // Round up to next full word if(dir == TUSB_DIR_OUT) { @@ -618,9 +641,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) usb_otg->GRXFSIZ = sz; } - out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); + out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << USB_OTG_DOEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); } @@ -661,8 +685,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); } @@ -670,6 +694,34 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +// Close all non-control endpoints, cancel all pending transfers if any. +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + +// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // Disable non-control interrupt + dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].DOEPCTL = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].DIEPCTL = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + // reset allocated fifo IN + _allocated_fifo_words_tx = 16; +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -829,22 +881,13 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + // Clear stall and reset data toggle if(dir == TUSB_DIR_IN) { in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; - - uint8_t eptype = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP_Msk) >> USB_OTG_DIEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. - if(eptype == 2 || eptype == 3) { - in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; - } + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; } else { out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; - - uint8_t eptype = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP_Msk) >> USB_OTG_DOEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. - if(eptype == 2 || eptype == 3) { - out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; - } + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; } } @@ -933,7 +976,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ if (xfer->ff) { // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, bcnt); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *)(uintptr_t) rx_fifo, bcnt); } else { @@ -1053,7 +1096,7 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT if (xfer->ff) { usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, packet_size); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *)(uintptr_t) tx_fifo, packet_size); } else { @@ -1081,7 +1124,7 @@ void dcd_int_handler(uint8_t rhport) USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - uint32_t int_status = usb_otg->GINTSTS; + uint32_t const int_status = usb_otg->GINTSTS & usb_otg->GINTMSK; if(int_status & USB_OTG_GINTSTS_USBRST) { @@ -1114,6 +1157,9 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } + // TODO check USB_OTG_GINTSTS_DISCINT for disconnect detection + // if(int_status & USB_OTG_GINTSTS_DISCINT) + if(int_status & USB_OTG_GINTSTS_OTGINT) { // OTG INT bit is read-only @@ -1127,13 +1173,15 @@ void dcd_int_handler(uint8_t rhport) usb_otg->GOTGINT = otg_int; } -#if USE_SOF if(int_status & USB_OTG_GINTSTS_SOF) { usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + + // Disable SOF interrupt since currently only used for remote wakeup detection + usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } -#endif // RxFIFO non-empty interrupt handling. if(int_status & USB_OTG_GINTSTS_RXFLVL) @@ -1147,8 +1195,7 @@ void dcd_int_handler(uint8_t rhport) do { handle_rxflvl_ints(rhport, out_ep); - int_status = usb_otg->GINTSTS; - } while(int_status & USB_OTG_GINTSTS_RXFLVL); + } while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL); // Manage RX FIFO size if (_out_ep_closed) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c new file mode 100644 index 000000000..bb21b3dcd --- /dev/null +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -0,0 +1,1311 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 William D. Jones + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Jan Duempelmann + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" +#include "device/dcd_attr.h" + +#if TUSB_OPT_DEVICE_ENABLED && \ + ( defined(DCD_ATTR_DWC2_STM32) || \ + TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_GD32VF103) || \ + TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711, OPT_MCU_XMC4000) ) + +#include "device/dcd.h" +#include "dwc2_type.h" + +#if defined(DCD_ATTR_DWC2_STM32) + #include "dwc2_stm32.h" +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #include "dwc2_esp32.h" +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) + #include "dwc2_gd32.h" +#elif TU_CHECK_MCU(OPT_MCU_BCM2711) + #include "dwc2_bcm.h" +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) + #include "dwc2_efm32.h" +#elif TU_CHECK_MCU(OPT_MCU_XMC4000) + #include "dwc2_xmc.h" +#else + #error "Unsupported MCUs" +#endif + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +// DWC2 registers +#define DWC2_REG(_port) ((dwc2_regs_t*) DWC2_REG_BASE) + +// Debug level for DWC2 +#define DWC2_DEBUG 2 + +#ifndef dcache_clean +#define dcache_clean(_addr, _size) +#endif + +#ifndef dcache_invalidate +#define dcache_invalidate(_addr, _size) +#endif + +#ifndef dcache_clean_invalidate +#define dcache_clean_invalidate(_addr, _size) +#endif + + +static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; + +typedef struct { + uint8_t * buffer; + tu_fifo_t * ff; + uint16_t total_len; + uint16_t max_size; + uint8_t interval; +} xfer_ctl_t; + +static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; +#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) + +// EP0 transfers are limited to 1 packet - larger sizes has to be split +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type + +// TX FIFO RAM allocation so far in words - RX FIFO size is readily available from dwc2->grxfsiz +static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) +static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) + +// Calculate the RX FIFO size according to recommendations from reference manual +static inline uint16_t calc_rx_ff_size(uint16_t ep_size) +{ + return 15 + 2*(ep_size/4) + 2*DWC2_EP_MAX; +} + +static void update_grxfsiz(uint8_t rhport) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + // Determine largest EP size for RX FIFO + uint16_t max_epsize = 0; + for (uint8_t epnum = 0; epnum < DWC2_EP_MAX; epnum++) + { + max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size); + } + + // Update size of RX FIFO + dwc2->grxfsiz = calc_rx_ff_size(max_epsize); +} + +// Setup the control endpoint 0. +static void bus_reset(uint8_t rhport) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + tu_memclr(xfer_status, sizeof(xfer_status)); + _out_ep_closed = false; + + // clear device address + dwc2->dcfg &= ~DCFG_DAD_Msk; + + // 1. NAK for all OUT endpoints + for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ ) + { + dwc2->epout[n].doepctl |= DOEPCTL_SNAK; + } + + // 2. Set up interrupt mask + dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); + dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; + dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start. + // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located + // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard + // configuration done below. + // + // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed. + // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a + // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually + // opened when the host sends an additional command: setInterface. At this point in time + // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size + // an additional memory + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // - 13 for setup packets + control words (up to 3 setup packets). + // - 1 for global NAK (not required/used here). + // - Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1" + // - 2 for each used OUT endpoint + // + // Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum + // - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x DWC2_EP_MAX = 47 + 2 x DWC2_EP_MAX + // - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x DWC2_EP_MAX = 271 + 2 x DWC2_EP_MAX + // + // NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge + // of the overall picture yet. We will use the worst scenario: largest possible + DWC2_EP_MAX + // + // For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO + // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to + // overwrite this. + + dwc2->grxfsiz = calc_rx_ff_size(TUD_OPT_HIGH_SPEED ? 512 : 64); + + _allocated_fifo_words_tx = 16; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); + + // Fixed control EP0 size to 64 bytes + dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN ].max_size = 64; + + dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); + + dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; +} + +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + // EP0 is limited to one packet each xfer + // We use multiple transaction of xfer->max_size length to get a whole transfer done + if ( epnum == 0 ) + { + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, dir); + total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); + ep0_pending[dir] -= total_bytes; + } + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. + if ( dir == TUSB_DIR_IN ) + { + dwc2_epin_t* epin = dwc2->epin; + + // A full IN transfer (multiple packets, possibly) triggers XFRC. + epin[epnum].dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); + + epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; + + // For ISO endpoint set correct odd/even bit for next frame. + if ( (epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1 ) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); + epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); + } + // Enable fifo empty interrupt only if there are something to put in the fifo. + if ( total_bytes != 0 ) + { + dwc2->diepempmsk |= (1 << epnum); + } + } + else + { + dwc2_epout_t* epout = dwc2->epout; + + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + epout[epnum].doeptsiz &= ~(DOEPTSIZ_PKTCNT_Msk | DOEPTSIZ_XFRSIZ); + epout[epnum].doeptsiz |= (num_packets << DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk); + + epout[epnum].doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; + if ( (epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && + XFER_CTL_BASE(epnum, dir)->interval == 1 ) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); + epout[epnum].doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); + } + } +} + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +#if CFG_TUSB_DEBUG >= DWC2_DEBUG +void print_dwc2_info(dwc2_regs_t * dwc2) +{ + dwc2_ghwcfg2_t const * hw_cfg2 = &dwc2->ghwcfg2_bm; + dwc2_ghwcfg3_t const * hw_cfg3 = &dwc2->ghwcfg3_bm; + dwc2_ghwcfg4_t const * hw_cfg4 = &dwc2->ghwcfg4_bm; + +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); + TU_LOG_HEX(DWC2_DEBUG, dwc2->guid); + TU_LOG_HEX(DWC2_DEBUG, dwc2->gsnpsid); + TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg1); + + // HW configure 2 + TU_LOG(DWC2_DEBUG, "\r\n"); + TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg2); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->op_mode ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->arch ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->point2point ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->hs_phy_type ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->fs_phy_type ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_dev_ep ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_host_ch ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->period_channel_support ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->enable_dynamic_fifo ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->mul_cpu_int ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->nperiod_tx_q_depth ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->host_period_tx_q_depth ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->dev_token_q_depth ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg2->otg_enable_ic_usb ); + + // HW configure 3 + TU_LOG(DWC2_DEBUG, "\r\n"); + TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg3); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->xfer_size_width ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->packet_size_width ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->i2c_enable ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->vendor_ctrl_itf ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->optional_feature_removed ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->synch_reset ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_adp_support ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable_hsic ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->battery_charger_support ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->lpm_mode ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg3->total_fifo_size ); + + // HW configure 4 + TU_LOG(DWC2_DEBUG, "\r\n"); + TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg4); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_period_in_ep ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->power_optimized ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ahb_freq_min ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->hibernation ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->service_interval_mode ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ipg_isoc_en ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->acg_enable ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->utmi_phy_data_width ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dev_ctrl_ep_num ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->iddg_filter_enabled ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->vbus_valid_filter_enabled ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->a_valid_filter_enabled ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->b_valid_filter_enabled ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dedicated_fifos ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_in_eps ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_desc_enable ); + TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_dynamic ); +} +#endif + +static void reset_core(dwc2_regs_t * dwc2) +{ + // reset core + dwc2->grstctl |= GRSTCTL_CSRST; + + // wait for reset bit is cleared + // TODO version 4.20a should wait for RESET DONE mask + while (dwc2->grstctl & GRSTCTL_CSRST) { } + + // wait for AHB master IDLE + while ( !(dwc2->grstctl & GRSTCTL_AHBIDL) ) { } + + // wait for device mode ? +} + +static bool phy_hs_supported(dwc2_regs_t * dwc2) +{ + // note: esp32 incorrect report its hs_phy_type as utmi + return TUD_OPT_HIGH_SPEED && dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE; +} + +static void phy_fs_init(dwc2_regs_t * dwc2) +{ + TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n"); + + // Select FS PHY + dwc2->gusbcfg |= GUSBCFG_PHYSEL; + + // MCU specific PHY init before reset + dwc2_phy_init(dwc2, HS_PHY_TYPE_NONE); + + // Reset core after selecting PHY + reset_core(dwc2); + + // USB turnaround time is critical for certification where long cables and 5-Hubs are used. + // So if you need the AHB to run at less than 30 MHz, and if USB turnaround time is not critical, + // these bits can be programmed to a larger value. Default is 5 + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos); + + // MCU specific PHY update post reset + dwc2_phy_update(dwc2, HS_PHY_TYPE_NONE); + + // set max speed + dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos); +} + +static void phy_hs_init(dwc2_regs_t * dwc2) +{ + uint32_t gusbcfg = dwc2->gusbcfg; + + // De-select FS PHY + gusbcfg &= ~GUSBCFG_PHYSEL; + + if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) + { + TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n"); + + // Select ULPI + gusbcfg |= GUSBCFG_ULPI_UTMI_SEL; + + // ULPI 8-bit interface, single data rate + gusbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); + + // default internal VBUS Indicator and Drive + gusbcfg &= ~(GUSBCFG_ULPIEVBUSD | GUSBCFG_ULPIEVBUSI); + + // Disable FS/LS ULPI + gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM); + }else + { + TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n"); + + // Select UTMI+ with 8-bit interface + gusbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); + + // Set 16-bit interface if supported + if (dwc2->ghwcfg4_bm.utmi_phy_data_width) gusbcfg |= GUSBCFG_PHYIF16; + } + + // Apply config + dwc2->gusbcfg = gusbcfg; + + // mcu specific phy init + dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); + + // Reset core after selecting PHY + reset_core(dwc2); + + // Set turn-around, must after core reset otherwise it will be clear + // - 9 if using 8-bit PHY interface + // - 5 if using 16-bit PHY interface + gusbcfg &= ~GUSBCFG_TRDT_Msk; + gusbcfg |= (dwc2->ghwcfg4_bm.utmi_phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; + dwc2->gusbcfg = gusbcfg; + + // MCU specific PHY update post reset + dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); + + // Set max speed + uint32_t dcfg = dwc2->dcfg; + dcfg &= ~DCFG_DSPD_Msk; + dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + + // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required + // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) + if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) dcfg |= DCFG_XCVRDLY; + + dwc2->dcfg = dcfg; +} + +static bool check_dwc2(dwc2_regs_t * dwc2) +{ +#if CFG_TUSB_DEBUG >= DWC2_DEBUG + print_dwc2_info(dwc2); +#endif + + // For some reasons: GD32VF103 snpsid and all hwcfg register are always zero (skip it) +#if !TU_CHECK_MCU(OPT_MCU_GD32VF103) + uint32_t const gsnpsid = dwc2->gsnpsid & GSNPSID_ID_MASK; + TU_ASSERT(gsnpsid == DWC2_OTG_ID || gsnpsid == DWC2_FS_IOT_ID || gsnpsid == DWC2_HS_IOT_ID); +#endif + + return true; +} + +void dcd_init (uint8_t rhport) +{ + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + // Check Synopsys ID register, failed if controller clock/power is not enabled + TU_VERIFY(check_dwc2(dwc2), ); + + dcd_disconnect(rhport); + + // max number of endpoints & total_fifo_size are: + // hw_cfg2->num_dev_ep, hw_cfg2->total_fifo_size + + if( phy_hs_supported(dwc2) ) + { + // Highspeed + phy_hs_init(dwc2); + }else + { + // core does not support highspeed or hs-phy is not present + phy_fs_init(dwc2); + } + + // Restart PHY clock + dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); + + /* Set HS/FS Timeout Calibration to 7 (max available value). + * The number of PHY clocks that the application programs in + * this field is added to the high/full speed interpacket timeout + * duration in the core to account for any additional delays + * introduced by the PHY. This can be required, because the delay + * introduced by the PHY in generating the linestate condition + * can vary from one PHY to another. + */ + dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); + + // Force device mode + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; + + // Clear A override, force B Valid + dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; + + // If USB host misbehaves during status portion of control xfer + // (non zero-length packet), send STALL back and discard. + dwc2->dcfg |= DCFG_NZLSOHSK; + + // Clear all interrupts + dwc2->gintsts |= dwc2->gintsts; + dwc2->gotgint |= dwc2->gotgint; + + // Required as part of core initialization. + // TODO: How should mode mismatch be handled? It will cause + // the core to stop working/require reset. + dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_MMISM | GINTMSK_RXFLVLM | + GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; + + // Enable global interrupt + dwc2->gahbcfg |= GAHBCFG_GINT; + + // make sure we are in device mode +// TU_ASSERT(!(dwc2->gintsts & GINTSTS_CMOD), ); + +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg); + + dcd_connect(rhport); +} + +void dcd_int_enable (uint8_t rhport) +{ + dwc2_dcd_int_enable(rhport); +} + +void dcd_int_disable (uint8_t rhport) +{ + dwc2_dcd_int_disable(rhport); +} + +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); + + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + // set remote wakeup + dwc2->dctl |= DCTL_RWUSIG; + + // enable SOF to detect bus resume + dwc2->gintsts = GINTSTS_SOF; + dwc2->gintmsk |= GINTMSK_SOFM; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + dwc2_remote_wakeup_delay(); + + dwc2->dctl &= ~DCTL_RWUSIG; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2->dctl &= ~DCTL_SDIS; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2->dctl |= DCTL_SDIS; +} + + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(epnum < DWC2_EP_MAX); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + xfer->interval = desc_edpt->bInterval; + + uint16_t const fifo_size = tu_div_ceil(xfer->max_size, 4); + + if(dir == TUSB_DIR_OUT) + { + // Calculate required size of RX FIFO + uint16_t const sz = calc_rx_ff_size(4*fifo_size); + + // If size_rx needs to be extended check if possible and if so enlarge it + if (dwc2->grxfsiz < sz) + { + TU_ASSERT(sz + _allocated_fifo_words_tx <= DWC2_EP_FIFO_SIZE/4); + + // Enlarge RX FIFO + dwc2->grxfsiz = sz; + } + + dwc2->epout[epnum].doepctl |= (1 << DOEPCTL_USBAEP_Pos) | + (desc_edpt->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DOEPCTL_MPSIZ_Pos); + + dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); + } + else + { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // In FIFO is allocated by following rules: + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + // Check if free space is available + TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= DWC2_EP_FIFO_SIZE/4); + + _allocated_fifo_words_tx += fifo_size; + + TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %u", fifo_size*4, DWC2_EP_FIFO_SIZE-_allocated_fifo_words_tx*4); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); + + dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) | + (epnum << DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DIEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DIEPCTL_MPSIZ_Pos); + + dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum)); + } + + return true; +} + +// Close all non-control endpoints, cancel all pending transfers if any. +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + // Disable non-control interrupt + dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); + + for(uint8_t n = 1; n < DWC2_EP_MAX; n++) + { + // disable OUT endpoint + dwc2->epout[n].doepctl = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + dwc2->epin[n].diepctl = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + // reset allocated fifo IN + _allocated_fifo_words_tx = 16; +} + +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; + + // EP0 can only handle one packet + if(epnum == 0) + { + ep0_pending[dir] = total_bytes; + + // Schedule the first transaction for EP0 transfer + edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); + } + else + { + uint16_t num_packets = (total_bytes / xfer->max_size); + uint16_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if ( (short_packet_size > 0) || (total_bytes == 0) ) num_packets++; + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + } + + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint16_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if ( short_packet_size > 0 || (total_bytes == 0) ) num_packets++; + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + +static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) +{ + (void) rhport; + + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if ( dir == TUSB_DIR_IN ) + { + dwc2_epin_t* epin = dwc2->epin; + + // Only disable currently enabled non-control endpoint + if ( (epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA) ) + { + epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + } + else + { + // Stop transmitting packets and NAK IN xfers. + epin[epnum].diepctl |= DIEPCTL_SNAK; + while ( (epin[epnum].diepint & DIEPINT_INEPNE) == 0 ) {} + + // Disable the endpoint. + epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + while ( (epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0 ) {} + + epin[epnum].diepint = DIEPINT_EPDISD; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + dwc2->grstctl |= (epnum << GRSTCTL_TXFNUM_Pos); + dwc2->grstctl |= GRSTCTL_TXFFLSH; + while ( (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) != 0 ) {} + } + else + { + dwc2_epout_t* epout = dwc2->epout; + + // Only disable currently enabled non-control endpoint + if ( (epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA) ) + { + epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; + } + else + { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + dwc2->dctl |= DCTL_SGONAK; + while ( (dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0 ) {} + + // Ditto here- disable the endpoint. + epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + while ( (epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0 ) {} + + epout[epnum].doepint = DOEPINT_EPDISD; + + // Allow other OUT endpoints to keep receiving. + dwc2->dctl |= DCTL_CGONAK; + } + } +} + +/** + * Close an endpoint. + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_edpt_disable(rhport, ep_addr, false); + + // Update max_size + xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation + + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos; + // For now only the last opened endpoint can be closed without fuss. + TU_ASSERT(fifo_start == DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,); + _allocated_fifo_words_tx -= fifo_size; + } + else + { + _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty + } +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + dcd_edpt_disable(rhport, ep_addr, true); +} + +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // Clear stall and reset data toggle + if ( dir == TUSB_DIR_IN ) + { + dwc2->epin[epnum].diepctl &= ~DIEPCTL_STALL; + dwc2->epin[epnum].diepctl |= DIEPCTL_SD0PID_SEVNFRM; + } + else + { + dwc2->epout[epnum].doepctl &= ~DOEPCTL_STALL; + dwc2->epout[epnum].doepctl |= DOEPCTL_SD0PID_SEVNFRM; + } +} + +/*------------------------------------------------------------------*/ + +// Read a single data packet from receive FIFO +static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + volatile const uint32_t * rx_fifo = dwc2->fifo[0]; + + // Reading full available 32 bit words from fifo + uint16_t full_words = len >> 2; + while(full_words--) + { + tu_unaligned_write32(dst, *rx_fifo); + dst += 4; + } + + // Read the remaining 1-3 bytes from fifo + uint8_t const bytes_rem = len & 0x03; + if ( bytes_rem != 0 ) + { + uint32_t const tmp = *rx_fifo; + dst[0] = tu_u32_byte0(tmp); + if ( bytes_rem > 1 ) dst[1] = tu_u32_byte1(tmp); + if ( bytes_rem > 2 ) dst[2] = tu_u32_byte2(tmp); + } +} + +// Write a single data packet to EPIN FIFO +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const * src, uint16_t len) +{ + (void) rhport; + + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + volatile uint32_t * tx_fifo = dwc2->fifo[fifo_num]; + + // Pushing full available 32 bit words to fifo + uint16_t full_words = len >> 2; + while(full_words--) + { + *tx_fifo = tu_unaligned_read32(src); + src += 4; + } + + // Write the remaining 1-3 bytes into fifo + uint8_t const bytes_rem = len & 0x03; + if ( bytes_rem ) + { + uint32_t tmp_word = src[0]; + if ( bytes_rem > 1 ) tmp_word |= (src[1] << 8); + if ( bytes_rem > 2 ) tmp_word |= (src[2] << 16); + + *tx_fifo = tmp_word; + } +} + +static void handle_rxflvl_irq(uint8_t rhport) +{ + dwc2_regs_t * dwc2 = DWC2_REG(rhport); + volatile uint32_t const * rx_fifo = dwc2->fifo[0]; + + // Pop control word off FIFO + uint32_t const ctl_word = dwc2->grxstsp; + uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk ) >> GRXSTSP_PKTSTS_Pos; + uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk ) >> GRXSTSP_EPNUM_Pos; + uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk ) >> GRXSTSP_BCNT_Pos; + + dwc2_epout_t* epout = &dwc2->epout[epnum]; + +//#if CFG_TUSB_DEBUG >= DWC2_DEBUG +// const char * pktsts_str[] = +// { +// "ASSERT", "Global NAK (ISR)", "Out Data Received", "Out Transfer Complete (ISR)", +// "Setup Complete (ISR)", "ASSERT", "Setup Data Received" +// }; +// TU_LOG_LOCATION(); +// TU_LOG(DWC2_DEBUG, " EP %02X, Byte Count %u, %s\r\n", epnum, bcnt, pktsts_str[pktsts]); +// TU_LOG(DWC2_DEBUG, " daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint); +//#endif + + switch ( pktsts ) + { + // Global OUT NAK: do nothign + case GRXSTS_PKTSTS_GLOBALOUTNAK: break; + + case GRXSTS_PKTSTS_SETUPRX: + // Setup packet received + + // We can receive up to three setup packets in succession, but + // only the last one is valid. + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); + break; + + case GRXSTS_PKTSTS_SETUPDONE: + // Setup packet done (Interrupt) + epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); + break; + + case GRXSTS_PKTSTS_OUTRX: + { + // Out packet received + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + + // Read packet off RxFIFO + if ( xfer->ff ) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt); + } + else + { + // Linear buffer + read_fifo_packet(rhport, xfer->buffer, bcnt); + + // Increment pointer to xfer data + xfer->buffer += bcnt; + } + + // Truncate transfer length in case of short packet + if ( bcnt < xfer->max_size ) + { + xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; + if ( epnum == 0 ) + { + xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + ep0_pending[TUSB_DIR_OUT] = 0; + } + } + } + break; + + // Out packet done (Interrupt) + case GRXSTS_PKTSTS_OUTDONE: + // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a + // May (or not) be 3.10a specific feature/bug or depending on MCU configuration + // XFRC complete is additionally generated when + // - setup packet is received + // - complete the data stage of control write is complete + if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) + { + uint32_t doepint = epout->doepint; + + if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) + { + // skip this "no-data" transfer complete event + // Note: STPKTRX will be clear later by setup received handler + uint32_t clear_flags = DOEPINT_XFRC; + + if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR; + + epout->doepint = clear_flags; + + // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n"); + } + } + break; + + default: // Invalid + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_irq (uint8_t rhport) +{ + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + + // DAINT for a given EP clears when DOEPINTx is cleared. + // OEPINT will be cleared when DAINT's out bits are cleared. + for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ ) + { + if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) ) + { + dwc2_epout_t* epout = &dwc2->epout[n]; + + uint32_t const doepint = epout->doepint; + + // SETUP packet Setup Phase done. + if ( doepint & DOEPINT_STUP ) + { + uint32_t clear_flag = DOEPINT_STUP; + + // STPKTRX is only available for version from 3_00a + if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) + { + clear_flag |= DOEPINT_STPKTRX; + } + + epout->doepint = clear_flag; + dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + } + + // OUT XFER complete + if ( epout->doepint & DOEPINT_XFRC ) + { + epout->doepint = DOEPINT_XFRC; + + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + // EP0 can only handle one packet + if ( (n == 0) && ep0_pending[TUSB_DIR_OUT] ) + { + // Schedule another packet to be received. + edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); + } + else + { + dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + } +} + +static void handle_epin_irq (uint8_t rhport) +{ + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + dwc2_epin_t* epin = dwc2->epin; + + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ ) + { + if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) ) + { + // IN XFER complete (entire xfer). + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + + if ( epin[n].diepint & DIEPINT_XFRC ) + { + epin[n].diepint = DIEPINT_XFRC; + + // EP0 can only handle one packet + if ( (n == 0) && ep0_pending[TUSB_DIR_IN] ) + { + // Schedule another packet to be transmitted. + edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); + } + else + { + dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + + // XFER FIFO empty + if ( (epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n)) ) + { + // diepint's TXFE bit is read-only, software cannot clear it. + // It will only be cleared by hardware when written bytes is more than + // - 64 bytes or + // - Half of TX FIFO size (configured by DIEPTXF) + + uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos; + + // Process every single packet (only whole packets can be written to fifo) + for ( uint16_t i = 0; i < remaining_packets; i++ ) + { + uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos; + + // Packet can not be larger than ep max size + uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size); + + // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current + // EP has to be checked if the buffer can take another WHOLE packet + if ( packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2) ) break; + + // Push packet to Tx-FIFO + if ( xfer->ff ) + { + volatile uint32_t *tx_fifo = dwc2->fifo[n]; + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size); + } + else + { + write_fifo_packet(rhport, n, xfer->buffer, packet_size); + + // Increment pointer to xfer data + xfer->buffer += packet_size; + } + } + + // Turn off TXFE if all bytes are written. + if ( ((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0 ) + { + dwc2->diepempmsk &= ~(1 << n); + } + } + } + } +} + +void dcd_int_handler(uint8_t rhport) +{ + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + + uint32_t const int_status = dwc2->gintsts & dwc2->gintmsk; + + if(int_status & GINTSTS_USBRST) + { + // USBRST is start of reset. + dwc2->gintsts = GINTSTS_USBRST; + bus_reset(rhport); + } + + if(int_status & GINTSTS_ENUMDNE) + { + // ENUMDNE is the end of reset where speed of the link is detected + + dwc2->gintsts = GINTSTS_ENUMDNE; + + tusb_speed_t speed; + switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) + { + case DSTS_ENUMSPD_HS: + speed = TUSB_SPEED_HIGH; + break; + + case DSTS_ENUMSPD_LS: + speed = TUSB_SPEED_LOW; + break; + + case DSTS_ENUMSPD_FS_HSPHY: + case DSTS_ENUMSPD_FS: + default: + speed = TUSB_SPEED_FULL; + break; + } + + dcd_event_bus_reset(rhport, speed, true); + } + + if(int_status & GINTSTS_USBSUSP) + { + dwc2->gintsts = GINTSTS_USBSUSP; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + if(int_status & GINTSTS_WKUINT) + { + dwc2->gintsts = GINTSTS_WKUINT; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + + // TODO check GINTSTS_DISCINT for disconnect detection + // if(int_status & GINTSTS_DISCINT) + + if(int_status & GINTSTS_OTGINT) + { + // OTG INT bit is read-only + uint32_t const otg_int = dwc2->gotgint; + + if (otg_int & GOTGINT_SEDET) + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + + dwc2->gotgint = otg_int; + } + + if(int_status & GINTSTS_SOF) + { + dwc2->gotgint = GINTSTS_SOF; + + // Disable SOF interrupt since currently only used for remote wakeup detection + dwc2->gintmsk &= ~GINTMSK_SOFM; + + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + + // RxFIFO non-empty interrupt handling. + if(int_status & GINTSTS_RXFLVL) + { + // RXFLVL bit is read-only + + // Mask out RXFLVL while reading data from FIFO + dwc2->gintmsk &= ~GINTMSK_RXFLVLM; + + // Loop until all available packets were handled + do + { + handle_rxflvl_irq(rhport); + } while(dwc2->gotgint & GINTSTS_RXFLVL); + + // Manage RX FIFO size + if (_out_ep_closed) + { + update_grxfsiz(rhport); + + // Disable flag + _out_ep_closed = false; + } + + dwc2->gintmsk |= GINTMSK_RXFLVLM; + } + + // OUT endpoint interrupt handling. + if(int_status & GINTSTS_OEPINT) + { + // OEPINT is read-only, clear using DOEPINTn + handle_epout_irq(rhport); + } + + // IN endpoint interrupt handling. + if(int_status & GINTSTS_IEPINT) + { + // IEPINT bit read-only, clear using DIEPINTn + handle_epin_irq(rhport); + } + + // // Check for Incomplete isochronous IN transfer + // if(int_status & GINTSTS_IISOIXFR) { + // printf(" IISOIXFR!\r\n"); + //// TU_LOG(DWC2_DEBUG, " IISOIXFR!\r\n"); + // } +} + +#endif diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h new file mode 100644 index 000000000..353bc21ee --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -0,0 +1,89 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DWC2_BCM_H_ +#define _TUSB_DWC2_BCM_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "broadcom/interrupts.h" +#include "broadcom/caches.h" + +#define DWC2_REG_BASE USB_OTG_GLOBAL_BASE +#define DWC2_EP_MAX 8 +#define DWC2_EP_FIFO_SIZE 4096 + +#define dcache_clean(_addr, _size) data_clean(_addr, _size) +#define dcache_invalidate(_addr, _size) data_invalidate(_addr, _size) +#define dcache_clean_invalidate(_addr, _size) data_clean_and_invalidate(_addr, _size) + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + BP_EnableIRQ(USB_IRQn); + __asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !? +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + BP_DisableIRQ(USB_IRQn); + __asm__ volatile("isb"); // needed if TIMER1 IRQ is not enabled !? +} + +static inline void dwc2_remote_wakeup_delay(void) +{ + // try to delay for 1 ms + // TODO implement later +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h new file mode 100644 index 000000000..ee4c3c715 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -0,0 +1,87 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Rafael Silva (@perigoso) + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _DWC2_EFM32_H_ +#define _DWC2_EFM32_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "em_device.h" + +// EFM32 has custom control register before DWC registers +#define DWC2_REG_BASE (USB_BASE + offsetof(USB_TypeDef, GOTGCTL)) +#define DWC2_EP_MAX 7 +#define DWC2_EP_FIFO_SIZE 2048 + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USB_IRQn); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_IRQn); +} + +static inline void dwc2_remote_wakeup_delay(void) +{ + // try to delay for 1 ms +// uint32_t count = SystemCoreClock / 1000; +// while ( count-- ) __NOP(); +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // Enable PHY + USB->ROUTE = USB_ROUTE_PHYPEN; +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // EFM32 Manual: turn around must be 5 (reset & default value) + // dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h new file mode 100644 index 000000000..78da277d5 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -0,0 +1,94 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef _DWC2_ESP32_H_ +#define _DWC2_ESP32_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "esp_intr_alloc.h" +#include "soc/periph_defs.h" +//#include "soc/usb_periph.h" + +#define DWC2_REG_BASE 0x60080000UL +#define DWC2_EP_MAX 5 // USB_OUT_EP_NUM +#define DWC2_EP_FIFO_SIZE 1024 + +// #define EP_FIFO_NUM 5 + +static intr_handle_t usb_ih; + +static void dcd_int_handler_wrap(void* arg) +{ + (void) arg; + dcd_int_handler(0); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, dcd_int_handler_wrap, NULL, &usb_ih); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + esp_intr_free(usb_ih); +} + +static inline void dwc2_remote_wakeup_delay(void) +{ + vTaskDelay(pdMS_TO_TICKS(1)); +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +#ifdef __cplusplus +} +#endif + +#endif /* _DWC2_ESP32_H_ */ diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h new file mode 100644 index 000000000..f8fa01ee0 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -0,0 +1,100 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef DWC2_GD32_H_ +#define DWC2_GD32_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define DWC2_REG_BASE 0x50000000UL +#define DWC2_EP_MAX 4 +#define DWC2_EP_FIFO_SIZE 1280 +#define RHPORT_IRQn 86 + +extern uint32_t SystemCoreClock; + +// The GD32VF103 is a RISC-V MCU, which implements the ECLIC Core-Local +// Interrupt Controller by Nuclei. It is nearly API compatible to the +// NVIC used by ARM MCUs. +#define ECLIC_INTERRUPT_ENABLE_BASE 0xD2001001UL + +TU_ATTR_ALWAYS_INLINE +static inline void __eclic_enable_interrupt (uint32_t irq) { + *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 1; +} + +TU_ATTR_ALWAYS_INLINE +static inline void __eclic_disable_interrupt (uint32_t irq){ + *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0; +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + __eclic_enable_interrupt(RHPORT_IRQn); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + __eclic_disable_interrupt(RHPORT_IRQn); +} + +static inline void dwc2_remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while ( count-- ) __asm volatile ("nop"); +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} + +#ifdef __cplusplus +} +#endif + +#endif /* DWC2_GD32_H_ */ diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h new file mode 100644 index 000000000..469045ac4 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -0,0 +1,205 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _DWC2_STM32_H_ +#define _DWC2_STM32_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// EP_MAX : Max number of bi-directional endpoints including EP0 +// EP_FIFO_SIZE : Size of dedicated USB SRAM +#if CFG_TUSB_MCU == OPT_MCU_STM32F1 + #include "stm32f1xx.h" + #define EP_MAX_FS 4 + #define EP_FIFO_SIZE_FS 1280 + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 + #include "stm32f2xx.h" + #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 + #include "stm32f4xx.h" + #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE + #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 + #include "stm32h7xx.h" + #define EP_MAX_FS 9 + #define EP_FIFO_SIZE_FS 4096 + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 + #include "stm32f7xx.h" + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + +#else + #error "Unsupported MCUs" +#endif + +// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS +#if TUD_OPT_RHPORT == 0 + #define DWC2_REG_BASE USB_OTG_FS_PERIPH_BASE + #define DWC2_EP_MAX EP_MAX_FS + #define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_FS + #define RHPORT_IRQn OTG_FS_IRQn + +#else + #define DWC2_REG_BASE USB_OTG_HS_PERIPH_BASE + #define DWC2_EP_MAX EP_MAX_HS + #define DWC2_EP_FIFO_SIZE EP_FIFO_SIZE_HS + #define RHPORT_IRQn OTG_HS_IRQn + +#endif + +extern uint32_t SystemCoreClock; + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(RHPORT_IRQn); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(RHPORT_IRQn); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_remote_wakeup_delay(void) +{ + // try to delay for 1 ms + uint32_t count = SystemCoreClock / 1000; + while ( count-- ) __NOP(); +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + if ( hs_phy_type == HS_PHY_TYPE_NONE ) + { + // Enable on-chip FS PHY + dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN; + }else + { + // Disable FS PHY + dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; + + // Enable on-chip HS PHY + if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) + { +#ifdef USB_HS_PHYC + // Enable UTMI HS PHY + dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN; + + // Enable LDO + USB_HS_PHYC->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; + + // Wait until LDO ready + while ( 0 == (USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} + + uint32_t phyc_pll = 0; + + // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS + switch ( HSE_VALUE ) + { + case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; + case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break; + case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break; + case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break; + case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break; + case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header + default: + TU_ASSERT(false, ); + } + USB_HS_PHYC->USB_HS_PHYC_PLL = phyc_pll; + + // Control the tuning interface of the High Speed PHY + // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver for F7 + USB_HS_PHYC->USB_HS_PHYC_TUNE |= 0x00000F13U; + + // Enable PLL internal PHY + USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; +#endif + } + } +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + // used to set turnaround time for fullspeed, nothing to do in highspeed mode + if ( hs_phy_type == HS_PHY_TYPE_NONE ) + { + // Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual + uint32_t turnaround; + + if ( SystemCoreClock >= 32000000u ) + turnaround = 0x6u; + else if ( SystemCoreClock >= 27500000u ) + turnaround = 0x7u; + else if ( SystemCoreClock >= 24000000u ) + turnaround = 0x8u; + else if ( SystemCoreClock >= 21800000u ) + turnaround = 0x9u; + else if ( SystemCoreClock >= 20000000u ) + turnaround = 0xAu; + else if ( SystemCoreClock >= 18500000u ) + turnaround = 0xBu; + else if ( SystemCoreClock >= 17200000u ) + turnaround = 0xCu; + else if ( SystemCoreClock >= 16000000u ) + turnaround = 0xDu; + else if ( SystemCoreClock >= 15000000u ) + turnaround = 0xEu; + else + turnaround = 0xFu; + + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos); + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* _DWC2_STM32_H_ */ diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h new file mode 100644 index 000000000..dbef20314 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -0,0 +1,1730 @@ +/** + * @author MCD Application Team + * Ha Thach (tinyusb.org) + * + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + */ + +#ifndef _TUSB_DWC2_TYPES_H_ +#define _TUSB_DWC2_TYPES_H_ + +#include "stdint.h" + +/* DWC OTG HW Release versions */ +#define DWC2_CORE_REV_2_71a 0x4f54271a +#define DWC2_CORE_REV_2_72a 0x4f54272a +#define DWC2_CORE_REV_2_80a 0x4f54280a +#define DWC2_CORE_REV_2_90a 0x4f54290a +#define DWC2_CORE_REV_2_91a 0x4f54291a +#define DWC2_CORE_REV_2_92a 0x4f54292a +#define DWC2_CORE_REV_2_94a 0x4f54294a +#define DWC2_CORE_REV_3_00a 0x4f54300a +#define DWC2_CORE_REV_3_10a 0x4f54310a +#define DWC2_CORE_REV_4_00a 0x4f54400a +#define DWC2_CORE_REV_4_20a 0x4f54420a +#define DWC2_FS_IOT_REV_1_00a 0x5531100a +#define DWC2_HS_IOT_REV_1_00a 0x5532100a +#define DWC2_CORE_REV_MASK 0x0000ffff + +/* DWC OTG HW Core ID */ +#define DWC2_OTG_ID 0x4f540000 +#define DWC2_FS_IOT_ID 0x55310000 +#define DWC2_HS_IOT_ID 0x55320000 + +#ifdef __cplusplus + extern "C" { +#endif + +#if 0 +// HS PHY +typedef struct +{ + volatile uint32_t HS_PHYC_PLL; // This register is used to control the PLL of the HS PHY. 000h */ + volatile uint32_t Reserved04; // Reserved 004h */ + volatile uint32_t Reserved08; // Reserved 008h */ + volatile uint32_t HS_PHYC_TUNE; // This register is used to control the tuning interface of the High Speed PHY. 00Ch */ + volatile uint32_t Reserved10; // Reserved 010h */ + volatile uint32_t Reserved14; // Reserved 014h */ + volatile uint32_t HS_PHYC_LDO; // This register is used to control the regulator (LDO). 018h */ +} HS_PHYC_GlobalTypeDef; +#endif + +enum { + HS_PHY_TYPE_NONE = 0 , // not supported + HS_PHY_TYPE_UTMI , // internal PHY (mostly) + HS_PHY_TYPE_ULPI , // external PHY + HS_PHY_TYPE_UTMI_ULPI , +}; + +enum { + FS_PHY_TYPE_NONE = 0, // not supported + FS_PHY_TYPE_DEDICATED, + FS_PHY_TYPE_UTMI, + FS_PHY_TYPE_ULPI, +}; + +typedef struct TU_ATTR_PACKED +{ + uint32_t op_mode : 3; // 0: HNP and SRP | 1: SRP | 2: non-HNP, non-SRP + uint32_t arch : 2; // 0: slave-only | 1: External DMA | 2: Internal DMA | 3: others + uint32_t point2point : 1; // 0: support hub and split | 1: no hub, no split + uint32_t hs_phy_type : 2; // 0: not supported | 1: UTMI+ | 2: ULPI | 3: UTMI+ and ULPI + uint32_t fs_phy_type : 2; // 0: not supported | 1: dedicated | 2: UTMI+ | 3: ULPI + uint32_t num_dev_ep : 4; // Number of device endpoints (not including EP0) + uint32_t num_host_ch : 4; // Number of host channel + uint32_t period_channel_support : 1; // Support Periodic OUT Host Channel + uint32_t enable_dynamic_fifo : 1; // Dynamic FIFO Sizing Enabled + uint32_t mul_cpu_int : 1; // Multi-Processor Interrupt Enabled + uint32_t reserved21 : 1; + uint32_t nperiod_tx_q_depth : 2; // Non-periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 + uint32_t host_period_tx_q_depth : 2; // Host periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 + uint32_t dev_token_q_depth : 5; // Device IN token sequence learning queue depth: 0-30 + uint32_t otg_enable_ic_usb : 1; // IC_USB mode specified for mode of operation +} dwc2_ghwcfg2_t; + +TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg2_t) == 4, "incorrect size"); + +typedef struct TU_ATTR_PACKED +{ + uint32_t xfer_size_width : 4; // Transfer size counter in bits = 11 + n (max 19 bits) + uint32_t packet_size_width : 3; // Packet size counter in bits = 4 + n (max 10 bits) + uint32_t otg_enable : 1; // 1 is OTG capable + uint32_t i2c_enable : 1; // I2C interface is available + uint32_t vendor_ctrl_itf : 1; // Vendor control interface is available + uint32_t optional_feature_removed : 1; // remove User ID, GPIO, SOF toggle & counter + uint32_t synch_reset : 1; // 0: async reset | 1: synch reset + uint32_t otg_adp_support : 1; // ADP logic is present along with HSOTG controller + uint32_t otg_enable_hsic : 1; // 1: HSIC-capable with shared UTMI PHY interface | 0: non-HSIC + uint32_t battery_charger_support : 1; // support battery charger + uint32_t lpm_mode : 1; // LPC mode + uint32_t total_fifo_size : 16; // DFIFO depth value in terms of 32-bit words +}dwc2_ghwcfg3_t; + +TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg3_t) == 4, "incorrect size"); + +typedef struct TU_ATTR_PACKED +{ + uint32_t num_dev_period_in_ep : 4; // Number of Device Periodic IN Endpoints + uint32_t power_optimized : 1; // Partial Power Down Enabled + uint32_t ahb_freq_min : 1; // 1: minimum of AHB frequency is less than 60 MHz + uint32_t hibernation : 1; // Hibernation feature is enabled + uint32_t reserved7 : 3; + uint32_t service_interval_mode : 1; // Service Interval supported + uint32_t ipg_isoc_en : 1; // IPG ISOC supported + uint32_t acg_enable : 1; // ACG enabled + uint32_t reserved13 : 1; + uint32_t utmi_phy_data_width : 2; // 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable + uint32_t dev_ctrl_ep_num : 4; // Number of Device control endpoints in addition to EP0 + uint32_t iddg_filter_enabled : 1; + uint32_t vbus_valid_filter_enabled : 1; + uint32_t a_valid_filter_enabled : 1; + uint32_t b_valid_filter_enabled : 1; + uint32_t dedicated_fifos : 1; // Dedicated tx fifo for device IN Endpoint is enabled + uint32_t num_dev_in_eps : 4; // Number of Device IN Endpoints including EP0 + uint32_t dma_desc_enable : 1; // scatter/gather DMA configuration + uint32_t dma_dynamic : 1; // Dynamic scatter/gather DMA +}dwc2_ghwcfg4_t; + +TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size"); + +// Host Channel +typedef struct +{ + volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics + volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control + volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt + volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask + volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size + volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address + uint32_t reserved518; // 518 + 20*ch + volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address +} dwc2_channel_t; + +// Endpoint IN +typedef struct +{ + volatile uint32_t diepctl; // 900 + 20*ep Device IN Endpoint Control + uint32_t reserved04; // 904 + volatile uint32_t diepint; // 908 + 20*ep Device IN Endpoint Interrupt + uint32_t reserved0c; // 90C + volatile uint32_t dieptsiz; // 910 + 20*ep Device IN Endpoint Transfer Size + volatile uint32_t diepdma; // 914 + 20*ep Device IN Endpoint DMA Address + volatile uint32_t dtxfsts; // 918 + 20*ep Device IN Endpoint Tx FIFO Status + uint32_t reserved1c; // 91C +} dwc2_epin_t; + +// Endpoint OUT +typedef struct +{ + volatile uint32_t doepctl; // B00 + 20*ep Device OUT Endpoint Control + uint32_t reserved04; // B04 + volatile uint32_t doepint; // B08 + 20*ep Device OUT Endpoint Interrupt + uint32_t reserved0c; // B0C + volatile uint32_t doeptsiz; // B10 + 20*ep Device OUT Endpoint Transfer Size + volatile uint32_t doepdma; // B14 + 20*ep Device OUT Endpoint DMA Address + uint32_t reserved18[2]; // B18..B1C +} dwc2_epout_t; + +typedef struct +{ + //------------- Core Global -------------// + volatile uint32_t gotgctl; // 000 OTG Control and Status + volatile uint32_t gotgint; // 004 OTG Interrupt + volatile uint32_t gahbcfg; // 008 AHB Configuration + volatile uint32_t gusbcfg; // 00c USB Configuration + volatile uint32_t grstctl; // 010 Reset + volatile uint32_t gintsts; // 014 Interrupt + volatile uint32_t gintmsk; // 018 Interrupt Mask + volatile uint32_t grxstsr; // 01c Receive Status Debug Read + volatile uint32_t grxstsp; // 020 Receive Status Read/Pop + volatile uint32_t grxfsiz; // 024 Receive FIFO Size +union { + volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size + volatile uint32_t gnptxfsiz; // 028 Non-periodic Transmit FIFO Size +}; + volatile uint32_t gnptxsts; // 02c Non-periodic Transmit FIFO/Queue Status + volatile uint32_t gi2cctl; // 030 I2C Address + volatile uint32_t gpvndctl; // 034 PHY Vendor Control +union { + volatile uint32_t ggpio; // 038 General Purpose IO + volatile uint32_t stm32_gccfg; // 038 STM32 General Core Configuration +}; + volatile uint32_t guid; // 03C User (Application programmable) ID + volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version + volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep) +union { + volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2 + dwc2_ghwcfg2_t ghwcfg2_bm; +}; +union { + volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3 + dwc2_ghwcfg3_t ghwcfg3_bm; +}; +union { + volatile uint32_t ghwcfg4; // 050 User Hardware Configuration4 + dwc2_ghwcfg4_t ghwcfg4_bm; +}; + volatile uint32_t glpmcfg; // 054 Core LPM Configuration + volatile uint32_t gpwrdn; // 058 Power Down + volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration + volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status + uint32_t reserved64[39]; // 064..0FF + volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size + volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size + uint32_t reserved140[176]; // 140..3FF + + //------------- Host -------------// + volatile uint32_t hcfg; // 400 Host Configuration + volatile uint32_t hfir; // 404 Host Frame Interval + volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining + uint32_t reserved40c; // 40C + volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status + volatile uint32_t haint; // 414 Host All Channels Interrupt + volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask + volatile uint32_t hflbaddr; // 41C Host Frame List Base Address + uint32_t reserved420[8]; // 420..43F + volatile uint32_t hprt; // 440 Host Port Control and Status + uint32_t reserved444[47]; // 444..4FF + + //------------- Host Channel -------------// + dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15 + uint32_t reserved700[64]; // 700..7FF + + //------------- Device -------------// + volatile uint32_t dcfg; // 800 Device Configuration + volatile uint32_t dctl; // 804 Device Control + volatile uint32_t dsts; // 808 Device Status (RO) + uint32_t reserved80c; // 80C + volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask + volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask + volatile uint32_t daint; // 818 Device All Endpoints Interrupt + volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask + volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1 + volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2 + volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time + volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time + volatile uint32_t dthrctl; // 830 Device threshold Control + volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask + volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt + volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt msk + volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask + volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask + uint32_t reserved8c0[16]; // 8C0..8FF + + //------------- Device Endpoint -------------// + dwc2_epin_t epin[16]; // 900..AFF IN Endpoints + dwc2_epout_t epout[16]; // B00..CFF OUT Endpoints + uint32_t reservedd00[64]; // D00..DFF + + //------------- Power Clock -------------// + volatile uint32_t pcgctl; // E00 Power and Clock Gating Control + volatile uint32_t pcgctl1; // E04 + uint32_t reservede08[126]; // E08..FFF + + //------------- FIFOs -------------// + // Word-accessed only using first pointer since it auto shift + volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO +} dwc2_regs_t; + +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, hcfg ) == 0x0400, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, channel) == 0x0500, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, dcfg ) == 0x0800, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, epin ) == 0x0900, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, epout ) == 0x0B00, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, pcgctl ) == 0x0E00, "incorrect size"); +TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); + +//--------------------------------------------------------------------+ +// Register Bit Definitions +//--------------------------------------------------------------------+ + +/******************** Bit definition for GOTGCTL register ********************/ +#define GOTGCTL_SRQSCS_Pos (0U) +#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 */ +#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success */ +#define GOTGCTL_SRQ_Pos (1U) +#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 */ +#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request */ +#define GOTGCTL_VBVALOEN_Pos (2U) +#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 */ +#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable */ +#define GOTGCTL_VBVALOVAL_Pos (3U) +#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 */ +#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value */ +#define GOTGCTL_AVALOEN_Pos (4U) +#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 */ +#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable */ +#define GOTGCTL_AVALOVAL_Pos (5U) +#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 */ +#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value */ +#define GOTGCTL_BVALOEN_Pos (6U) +#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 */ +#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable */ +#define GOTGCTL_BVALOVAL_Pos (7U) +#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 */ +#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value */ +#define GOTGCTL_HNGSCS_Pos (8U) +#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 */ +#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable */ +#define GOTGCTL_HNPRQ_Pos (9U) +#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 */ +#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request */ +#define GOTGCTL_HSHNPEN_Pos (10U) +#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 */ +#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable */ +#define GOTGCTL_DHNPEN_Pos (11U) +#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 */ +#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled */ +#define GOTGCTL_EHEN_Pos (12U) +#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 */ +#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable */ +#define GOTGCTL_CIDSTS_Pos (16U) +#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 */ +#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status */ +#define GOTGCTL_DBCT_Pos (17U) +#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 */ +#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time */ +#define GOTGCTL_ASVLD_Pos (18U) +#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 */ +#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid */ +#define GOTGCTL_BSESVLD_Pos (19U) +#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 */ +#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid */ +#define GOTGCTL_OTGVER_Pos (20U) +#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 */ +#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version */ + +/******************** Bit definition for HCFG register ********************/ +#define HCFG_FSLSPCS_Pos (0U) +#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 */ +#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select */ +#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 */ +#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 */ +#define HCFG_FSLSS_Pos (2U) +#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 */ +#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support */ + +/******************** Bit definition for PCGCR register ********************/ +#define PCGCR_STPPCLK_Pos (0U) +#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 */ +#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock */ +#define PCGCR_GATEHCLK_Pos (1U) +#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 */ +#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK */ +#define PCGCR_PHYSUSP_Pos (4U) +#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 */ +#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended */ + +/******************** Bit definition for GOTGINT register ********************/ +#define GOTGINT_SEDET_Pos (2U) +#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 */ +#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected */ +#define GOTGINT_SRSSCHG_Pos (8U) +#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 */ +#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change */ +#define GOTGINT_HNSSCHG_Pos (9U) +#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 */ +#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change */ +#define GOTGINT_HNGDET_Pos (17U) +#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 */ +#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected */ +#define GOTGINT_ADTOCHG_Pos (18U) +#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 */ +#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change */ +#define GOTGINT_DBCDNE_Pos (19U) +#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 */ +#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done */ +#define GOTGINT_IDCHNG_Pos (20U) +#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 */ +#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value */ + +/******************** Bit definition for DCFG register ********************/ +#define DCFG_DSPD_Pos (0U) +#define DCFG_DSPD_Msk (0x3UL << DCFG_DSPD_Pos) // 0x00000003 +#define DCFG_DSPD_HS 0 // Highspeed +#define DCFG_DSPD_FS_HSPHY 1 // Fullspeed on HS PHY +#define DCFG_DSPD_LS 2 // Lowspeed +#define DCFG_DSPD_FS 3 // Fullspeed on FS PHY + +#define DCFG_NZLSOHSK_Pos (2U) +#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 */ +#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake */ + +#define DCFG_DAD_Pos (4U) +#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 */ +#define DCFG_DAD DCFG_DAD_Msk // Device address */ +#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 */ +#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 */ +#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 */ +#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 */ +#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 */ +#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 */ +#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 */ + +#define DCFG_PFIVL_Pos (11U) +#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 */ +#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval */ +#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 */ +#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 */ + +#define DCFG_XCVRDLY_Pos (14U) +#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) /*!< 0x00004000 */ +#define DCFG_XCVRDLY DCFG_XCVRDLY_Msk // Enables delay between xcvr_sel and txvalid during device chirp + +#define DCFG_PERSCHIVL_Pos (24U) +#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 */ +#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval */ +#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 */ +#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 */ + +/******************** Bit definition for DCTL register ********************/ +#define DCTL_RWUSIG_Pos (0U) +#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 */ +#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling */ +#define DCTL_SDIS_Pos (1U) +#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 */ +#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect */ +#define DCTL_GINSTS_Pos (2U) +#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 */ +#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status */ +#define DCTL_GONSTS_Pos (3U) +#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 */ +#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status */ + +#define DCTL_TCTL_Pos (4U) +#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 */ +#define DCTL_TCTL DCTL_TCTL_Msk // Test control */ +#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 */ +#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 */ +#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 */ +#define DCTL_SGINAK_Pos (7U) +#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 */ +#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK */ +#define DCTL_CGINAK_Pos (8U) +#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 */ +#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK */ +#define DCTL_SGONAK_Pos (9U) +#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 */ +#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK */ +#define DCTL_CGONAK_Pos (10U) +#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 */ +#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK */ +#define DCTL_POPRGDNE_Pos (11U) +#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 */ +#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done */ + +/******************** Bit definition for HFIR register ********************/ +#define HFIR_FRIVL_Pos (0U) +#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF */ +#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval */ + +/******************** Bit definition for HFNUM register ********************/ +#define HFNUM_FRNUM_Pos (0U) +#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF */ +#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number */ +#define HFNUM_FTREM_Pos (16U) +#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 */ +#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining */ + +/******************** Bit definition for DSTS register ********************/ +#define DSTS_SUSPSTS_Pos (0U) +#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 */ +#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status */ +#define DSTS_ENUMSPD_Pos (1U) +#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 */ +#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed */ +#define DSTS_ENUMSPD_HS 0 // Highspeed +#define DSTS_ENUMSPD_FS_HSPHY 1 // Fullspeed on HS PHY +#define DSTS_ENUMSPD_LS 2 // Lowspeed +#define DSTS_ENUMSPD_FS 3 // Fullspeed on FS PHY + + +#define DSTS_EERR_Pos (3U) +#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 */ +#define DSTS_EERR DSTS_EERR_Msk // Erratic error */ +#define DSTS_FNSOF_Pos (8U) +#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 */ +#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF */ + +/******************** Bit definition for GAHBCFG register ********************/ +#define GAHBCFG_GINT_Pos (0U) +#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 */ +#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask */ +#define GAHBCFG_HBSTLEN_Pos (1U) +#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E */ +#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type */ +#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single */ +#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR */ +#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 */ +#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 */ +#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 */ +#define GAHBCFG_DMAEN_Pos (5U) +#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 */ +#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable */ +#define GAHBCFG_TXFELVL_Pos (7U) +#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 */ +#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level */ +#define GAHBCFG_PTXFELVL_Pos (8U) +#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 */ +#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level */ + +#define GSNPSID_ID_MASK TU_GENMASK(31, 16) + +/******************** Bit definition for GUSBCFG register ********************/ +#define GUSBCFG_TOCAL_Pos (0U) +#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 */ +#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration */ +#define GUSBCFG_PHYIF16_Pos (3U) +#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 */ +#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) */ +#define GUSBCFG_ULPI_UTMI_SEL_Pos (4U) +#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 */ +#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) */ +#define GUSBCFG_PHYSEL_Pos (6U) +#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 */ +#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ +#define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface. +#define GUSBCFG_SRPCAP_Pos (8U) +#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 */ +#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable */ +#define GUSBCFG_HNPCAP_Pos (9U) +#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 */ +#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable */ +#define GUSBCFG_TRDT_Pos (10U) +#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 */ +#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time */ +#define GUSBCFG_PHYLPCS_Pos (15U) +#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 */ +#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select */ +#define GUSBCFG_ULPIFSLS_Pos (17U) +#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 */ +#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select */ +#define GUSBCFG_ULPIAR_Pos (18U) +#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 */ +#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume */ +#define GUSBCFG_ULPICSM_Pos (19U) +#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 */ +#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM */ +#define GUSBCFG_ULPIEVBUSD_Pos (20U) +#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 */ +#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive */ +#define GUSBCFG_ULPIEVBUSI_Pos (21U) +#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 */ +#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator */ +#define GUSBCFG_TSDPS_Pos (22U) +#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 */ +#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection */ +#define GUSBCFG_PCCI_Pos (23U) +#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 */ +#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement */ +#define GUSBCFG_PTCI_Pos (24U) +#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 */ +#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through */ +#define GUSBCFG_ULPIIPD_Pos (25U) +#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 */ +#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable */ +#define GUSBCFG_FHMOD_Pos (29U) +#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 */ +#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode */ +#define GUSBCFG_FDMOD_Pos (30U) +#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 */ +#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode */ +#define GUSBCFG_CTXPKT_Pos (31U) +#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 */ +#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet */ + +/******************** Bit definition for GRSTCTL register ********************/ +#define GRSTCTL_CSRST_Pos (0U) +#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 */ +#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset */ +#define GRSTCTL_HSRST_Pos (1U) +#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 */ +#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset */ +#define GRSTCTL_FCRST_Pos (2U) +#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 */ +#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset */ +#define GRSTCTL_RXFFLSH_Pos (4U) +#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 */ +#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush */ +#define GRSTCTL_TXFFLSH_Pos (5U) +#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 */ +#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush */ +#define GRSTCTL_TXFNUM_Pos (6U) +#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 */ +#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number */ +#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 */ +#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 */ +#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 */ +#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 */ +#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 */ +#define GRSTCTL_CSFTRST_DONE_Pos (29) +#define GRSTCTL_CSFTRST_DONE (1u << GRSTCTL_CSFTRST_DONE_Pos) // Reset Done, only available from v4.20a +#define GRSTCTL_DMAREQ_Pos (30U) +#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 */ +#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal */ +#define GRSTCTL_AHBIDL_Pos (31U) +#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 */ +#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle */ + +/******************** Bit definition for DIEPMSK register ********************/ +#define DIEPMSK_XFRCM_Pos (0U) +#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 */ +#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPMSK_EPDM_Pos (1U) +#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 */ +#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPMSK_TOM_Pos (3U) +#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 */ +#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPMSK_ITTXFEMSK_Pos (4U) +#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 */ +#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPMSK_INEPNMM_Pos (5U) +#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 */ +#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPMSK_INEPNEM_Pos (6U) +#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 */ +#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPMSK_TXFURM_Pos (8U) +#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 */ +#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask */ +#define DIEPMSK_BIM_Pos (9U) +#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 */ +#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask */ + +/******************** Bit definition for HPTXSTS register ********************/ +#define HPTXSTS_PTXFSAVL_Pos (0U) +#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF */ +#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available */ +#define HPTXSTS_PTXQSAV_Pos (16U) +#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 */ +#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available */ +#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 */ +#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 */ +#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 */ +#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 */ +#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 */ +#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 */ +#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 */ +#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 */ + +#define HPTXSTS_PTXQTOP_Pos (24U) +#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 */ +#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue */ +#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 */ +#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 */ +#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 */ +#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 */ +#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 */ +#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 */ +#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 */ +#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 */ + +/******************** Bit definition for HAINT register ********************/ +#define HAINT_HAINT_Pos (0U) +#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF */ +#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts */ + +/******************** Bit definition for DOEPMSK register ********************/ +#define DOEPMSK_XFRCM_Pos (0U) +#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 */ +#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPMSK_EPDM_Pos (1U) +#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 */ +#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPMSK_AHBERRM_Pos (2U) +#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 */ +#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask */ +#define DOEPMSK_STUPM_Pos (3U) +#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 */ +#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask */ +#define DOEPMSK_OTEPDM_Pos (4U) +#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 */ +#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask */ +#define DOEPMSK_OTEPSPRM_Pos (5U) +#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 */ +#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask */ +#define DOEPMSK_B2BSTUP_Pos (6U) +#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 */ +#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask */ +#define DOEPMSK_OPEM_Pos (8U) +#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 */ +#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask */ +#define DOEPMSK_BOIM_Pos (9U) +#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 */ +#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask */ +#define DOEPMSK_BERRM_Pos (12U) +#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 */ +#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask */ +#define DOEPMSK_NAKM_Pos (13U) +#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 */ +#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask */ +#define DOEPMSK_NYETM_Pos (14U) +#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 */ +#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask */ + +/******************** Bit definition for GINTSTS register ********************/ +#define GINTSTS_CMOD_Pos (0U) +#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 */ +#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation */ +#define GINTSTS_MMIS_Pos (1U) +#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 */ +#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt */ +#define GINTSTS_OTGINT_Pos (2U) +#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 */ +#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt */ +#define GINTSTS_SOF_Pos (3U) +#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 */ +#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame */ +#define GINTSTS_RXFLVL_Pos (4U) +#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 */ +#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty */ +#define GINTSTS_NPTXFE_Pos (5U) +#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 */ +#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty */ +#define GINTSTS_GINAKEFF_Pos (6U) +#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 */ +#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective */ +#define GINTSTS_BOUTNAKEFF_Pos (7U) +#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 */ +#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective */ +#define GINTSTS_ESUSP_Pos (10U) +#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 */ +#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend */ +#define GINTSTS_USBSUSP_Pos (11U) +#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 */ +#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend */ +#define GINTSTS_USBRST_Pos (12U) +#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 */ +#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset */ +#define GINTSTS_ENUMDNE_Pos (13U) +#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 */ +#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done */ +#define GINTSTS_ISOODRP_Pos (14U) +#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 */ +#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt */ +#define GINTSTS_EOPF_Pos (15U) +#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 */ +#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt */ +#define GINTSTS_IEPINT_Pos (18U) +#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 */ +#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt */ +#define GINTSTS_OEPINT_Pos (19U) +#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 */ +#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt */ +#define GINTSTS_IISOIXFR_Pos (20U) +#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 */ +#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer */ +#define GINTSTS_PXFR_INCOMPISOOUT_Pos (21U) +#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 */ +#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer */ +#define GINTSTS_DATAFSUSP_Pos (22U) +#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 */ +#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended */ +#define GINTSTS_RSTDET_Pos (23U) +#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 */ +#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt */ +#define GINTSTS_HPRTINT_Pos (24U) +#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 */ +#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt */ +#define GINTSTS_HCINT_Pos (25U) +#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 */ +#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt */ +#define GINTSTS_PTXFE_Pos (26U) +#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 */ +#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty */ +#define GINTSTS_LPMINT_Pos (27U) +#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 */ +#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt */ +#define GINTSTS_CIDSCHG_Pos (28U) +#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 */ +#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change */ +#define GINTSTS_DISCINT_Pos (29U) +#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 */ +#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt */ +#define GINTSTS_SRQINT_Pos (30U) +#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 */ +#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt */ +#define GINTSTS_WKUINT_Pos (31U) +#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 */ +#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt */ + +/******************** Bit definition for GINTMSK register ********************/ +#define GINTMSK_MMISM_Pos (1U) +#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 */ +#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask */ +#define GINTMSK_OTGINT_Pos (2U) +#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 */ +#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask */ +#define GINTMSK_SOFM_Pos (3U) +#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 */ +#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask */ +#define GINTMSK_RXFLVLM_Pos (4U) +#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 */ +#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask */ +#define GINTMSK_NPTXFEM_Pos (5U) +#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 */ +#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask */ +#define GINTMSK_GINAKEFFM_Pos (6U) +#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 */ +#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask */ +#define GINTMSK_GONAKEFFM_Pos (7U) +#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 */ +#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask */ +#define GINTMSK_ESUSPM_Pos (10U) +#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 */ +#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask */ +#define GINTMSK_USBSUSPM_Pos (11U) +#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 */ +#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask */ +#define GINTMSK_USBRST_Pos (12U) +#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 */ +#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask */ +#define GINTMSK_ENUMDNEM_Pos (13U) +#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 */ +#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask */ +#define GINTMSK_ISOODRPM_Pos (14U) +#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 */ +#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask */ +#define GINTMSK_EOPFM_Pos (15U) +#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 */ +#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask */ +#define GINTMSK_EPMISM_Pos (17U) +#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 */ +#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask */ +#define GINTMSK_IEPINT_Pos (18U) +#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 */ +#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask */ +#define GINTMSK_OEPINT_Pos (19U) +#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 */ +#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask */ +#define GINTMSK_IISOIXFRM_Pos (20U) +#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 */ +#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask */ +#define GINTMSK_PXFRM_IISOOXFRM_Pos (21U) +#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 */ +#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask */ +#define GINTMSK_FSUSPM_Pos (22U) +#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 */ +#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask */ +#define GINTMSK_RSTDEM_Pos (23U) +#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 */ +#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask */ +#define GINTMSK_PRTIM_Pos (24U) +#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 */ +#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask */ +#define GINTMSK_HCIM_Pos (25U) +#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 */ +#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask */ +#define GINTMSK_PTXFEM_Pos (26U) +#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 */ +#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask */ +#define GINTMSK_LPMINTM_Pos (27U) +#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 */ +#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask */ +#define GINTMSK_CIDSCHGM_Pos (28U) +#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 */ +#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask */ +#define GINTMSK_DISCINT_Pos (29U) +#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 */ +#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask */ +#define GINTMSK_SRQIM_Pos (30U) +#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 */ +#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask */ +#define GINTMSK_WUIM_Pos (31U) +#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 */ +#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask */ + +/******************** Bit definition for DAINT register ********************/ +#define DAINT_IEPINT_Pos (0U) +#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF */ +#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits */ +#define DAINT_OEPINT_Pos (16U) +#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 */ +#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits */ + +/******************** Bit definition for HAINTMSK register ********************/ +#define HAINTMSK_HAINTM_Pos (0U) +#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF */ +#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask */ + +/******************** Bit definition for GRXSTSP register ********************/ +#define GRXSTSP_EPNUM_Pos (0U) +#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F */ +#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits */ +#define GRXSTSP_BCNT_Pos (4U) +#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 */ +#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_DPID_Pos (15U) +#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 */ +#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_PKTSTS_Pos (17U) +#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 */ +#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits */ + +#define GRXSTS_PKTSTS_GLOBALOUTNAK 1 +#define GRXSTS_PKTSTS_OUTRX 2 +#define GRXSTS_PKTSTS_HCHIN 2 +#define GRXSTS_PKTSTS_OUTDONE 3 +#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3 +#define GRXSTS_PKTSTS_SETUPDONE 4 +#define GRXSTS_PKTSTS_DATATOGGLEERR 5 +#define GRXSTS_PKTSTS_SETUPRX 6 +#define GRXSTS_PKTSTS_HCHHALTED 7 + + +/******************** Bit definition for DAINTMSK register ********************/ +#define DAINTMSK_IEPM_Pos (0U) +#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF */ +#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits */ +#define DAINTMSK_OEPM_Pos (16U) +#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 */ +#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits */ + +#if 0 +/******************** Bit definition for OTG register ********************/ +#define CHNUM_Pos (0U) +#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F */ +#define CHNUM CHNUM_Msk // Channel number */ +#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 */ +#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 */ +#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 */ +#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 */ +#define BCNT_Pos (4U) +#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 */ +#define BCNT BCNT_Msk // Byte count */ + +#define DPID_Pos (15U) +#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 */ +#define DPID DPID_Msk // Data PID */ +#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 */ +#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 */ + +#define PKTSTS_Pos (17U) +#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 */ +#define PKTSTS PKTSTS_Msk // Packet status */ +#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 */ +#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 */ +#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 */ +#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 */ + +#define EPNUM_Pos (0U) +#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F */ +#define EPNUM EPNUM_Msk // Endpoint number */ +#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 */ +#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 */ +#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 */ +#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 */ + +#define FRMNUM_Pos (21U) +#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 */ +#define FRMNUM FRMNUM_Msk // Frame number */ +#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 */ +#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 */ +#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 */ +#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 */ +#endif + +/******************** Bit definition for GRXFSIZ register ********************/ +#define GRXFSIZ_RXFD_Pos (0U) +#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF */ +#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth */ + +/******************** Bit definition for DVBUSDIS register ********************/ +#define DVBUSDIS_VBUSDT_Pos (0U) +#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF */ +#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time */ + +/******************** Bit definition for OTG register ********************/ +#define GNPTXFSIZ_NPTXFSA_Pos (0U) +#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << NPTXFSA_Pos) // 0x0000FFFF */ +#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address */ +#define GNPTXFSIZ_NPTXFD_Pos (16U) +#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << NPTXFD_Pos) // 0xFFFF0000 */ +#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth */ +#define DIEPTXF0_TX0FSA_Pos (0U) +#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << TX0FSA_Pos) // 0x0000FFFF */ +#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address */ +#define DIEPTXF0_TX0FD_Pos (16U) +#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << TX0FD_Pos) // 0xFFFF0000 */ +#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth */ + +/******************** Bit definition for DVBUSPULSE register ********************/ +#define DVBUSPULSE_DVBUSP_Pos (0U) +#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF */ +#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time */ + +/******************** Bit definition for GNPTXSTS register ********************/ +#define GNPTXSTS_NPTXFSAV_Pos (0U) +#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF */ +#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available */ + +#define GNPTXSTS_NPTQXSAV_Pos (16U) +#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 */ +#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available */ +#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 */ +#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 */ +#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 */ +#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 */ +#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 */ +#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 */ +#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 */ +#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 */ + +#define GNPTXSTS_NPTXQTOP_Pos (24U) +#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 */ +#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue */ +#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 */ +#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 */ +#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 */ +#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 */ +#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 */ +#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 */ +#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 */ + +/******************** Bit definition for DTHRCTL register ********************/ +#define DTHRCTL_NONISOTHREN_Pos (0U) +#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 */ +#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable */ +#define DTHRCTL_ISOTHREN_Pos (1U) +#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 */ +#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable */ + +#define DTHRCTL_TXTHRLEN_Pos (2U) +#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC */ +#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length */ +#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 */ +#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 */ +#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 */ +#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 */ +#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 */ +#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 */ +#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 */ +#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 */ +#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 */ +#define DTHRCTL_RXTHREN_Pos (16U) +#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 */ +#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable */ + +#define DTHRCTL_RXTHRLEN_Pos (17U) +#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 */ +#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length */ +#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 */ +#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 */ +#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 */ +#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 */ +#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 */ +#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 */ +#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 */ +#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 */ +#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 */ +#define DTHRCTL_ARPEN_Pos (27U) +#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 */ +#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable */ + +/******************** Bit definition for DIEPEMPMSK register ********************/ +#define DIEPEMPMSK_INEPTXFEM_Pos (0U) +#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF */ +#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits */ + +/******************** Bit definition for DEACHINT register ********************/ +#define DEACHINT_IEP1INT_Pos (1U) +#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 */ +#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit */ +#define DEACHINT_OEP1INT_Pos (17U) +#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 */ +#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit */ + +/******************** Bit definition for GCCFG register ********************/ +#define STM32_GCCFG_DCDET_Pos (0U) +#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 */ +#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status */ +#define STM32_GCCFG_PDET_Pos (1U) +#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 */ +#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status */ +#define STM32_GCCFG_SDET_Pos (2U) +#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 */ +#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status */ +#define STM32_GCCFG_PS2DET_Pos (3U) +#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 */ +#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status */ +#define STM32_GCCFG_PWRDWN_Pos (16U) +#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 */ +#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down */ +#define STM32_GCCFG_BCDEN_Pos (17U) +#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 */ +#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable */ +#define STM32_GCCFG_DCDEN_Pos (18U) +#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 */ +#define STM32_GCCFG_DCDEN STM32_GCCFG_DCDEN_Msk // Data contact detection (DCD) mode enable*/ +#define STM32_GCCFG_PDEN_Pos (19U) +#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 */ +#define STM32_GCCFG_PDEN STM32_GCCFG_PDEN_Msk // Primary detection (PD) mode enable*/ +#define STM32_GCCFG_SDEN_Pos (20U) +#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 */ +#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable */ +#define STM32_GCCFG_VBDEN_Pos (21U) +#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 */ +#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable */ +#define STM32_GCCFG_OTGIDEN_Pos (22U) +#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 */ +#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable */ +#define STM32_GCCFG_PHYHSEN_Pos (23U) +#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 */ +#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable */ + +/******************** Bit definition for DEACHINTMSK register ********************/ +#define DEACHINTMSK_IEP1INTM_Pos (1U) +#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 */ +#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit */ +#define DEACHINTMSK_OEP1INTM_Pos (17U) +#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 */ +#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit */ + +/******************** Bit definition for CID register ********************/ +#define CID_PRODUCT_ID_Pos (0U) +#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF */ +#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field */ + +/******************** Bit definition for GLPMCFG register ********************/ +#define GLPMCFG_LPMEN_Pos (0U) +#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 */ +#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable */ +#define GLPMCFG_LPMACK_Pos (1U) +#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 */ +#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable */ +#define GLPMCFG_BESL_Pos (2U) +#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C */ +#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token */ +#define GLPMCFG_REMWAKE_Pos (6U) +#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 */ +#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token */ +#define GLPMCFG_L1SSEN_Pos (7U) +#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 */ +#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable */ +#define GLPMCFG_BESLTHRS_Pos (8U) +#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 */ +#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold */ +#define GLPMCFG_L1DSEN_Pos (12U) +#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 */ +#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable */ +#define GLPMCFG_LPMRSP_Pos (13U) +#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 */ +#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response */ +#define GLPMCFG_SLPSTS_Pos (15U) +#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 */ +#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status */ +#define GLPMCFG_L1RSMOK_Pos (16U) +#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 */ +#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK */ +#define GLPMCFG_LPMCHIDX_Pos (17U) +#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 */ +#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index */ +#define GLPMCFG_LPMRCNT_Pos (21U) +#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 */ +#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count */ +#define GLPMCFG_SNDLPM_Pos (24U) +#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 */ +#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction */ +#define GLPMCFG_LPMRCNTSTS_Pos (25U) +#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 */ +#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status */ +#define GLPMCFG_ENBESL_Pos (28U) +#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 */ +#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency */ + +/******************** Bit definition for DIEPEACHMSK1 register ********************/ +#define DIEPEACHMSK1_XFRCM_Pos (0U) +#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ +#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPEACHMSK1_EPDM_Pos (1U) +#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 */ +#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPEACHMSK1_TOM_Pos (3U) +#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 */ +#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ +#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPEACHMSK1_INEPNMM_Pos (5U) +#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ +#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPEACHMSK1_INEPNEM_Pos (6U) +#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ +#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPEACHMSK1_TXFURM_Pos (8U) +#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ +#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask */ +#define DIEPEACHMSK1_BIM_Pos (9U) +#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 */ +#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DIEPEACHMSK1_NAKM_Pos (13U) +#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 */ +#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ + +/******************** Bit definition for HPRT register ********************/ +#define HPRT_PCSTS_Pos (0U) +#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 */ +#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status */ +#define HPRT_PCDET_Pos (1U) +#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 */ +#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected */ +#define HPRT_PENA_Pos (2U) +#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 */ +#define HPRT_PENA HPRT_PENA_Msk // Port enable */ +#define HPRT_PENCHNG_Pos (3U) +#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 */ +#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change */ +#define HPRT_POCA_Pos (4U) +#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 */ +#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active */ +#define HPRT_POCCHNG_Pos (5U) +#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 */ +#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change */ +#define HPRT_PRES_Pos (6U) +#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 */ +#define HPRT_PRES HPRT_PRES_Msk // Port resume */ +#define HPRT_PSUSP_Pos (7U) +#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 */ +#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend */ +#define HPRT_PRST_Pos (8U) +#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 */ +#define HPRT_PRST HPRT_PRST_Msk // Port reset */ + +#define HPRT_PLSTS_Pos (10U) +#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 */ +#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status */ +#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 */ +#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 */ +#define HPRT_PPWR_Pos (12U) +#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 */ +#define HPRT_PPWR HPRT_PPWR_Msk // Port power */ + +#define HPRT_PTCTL_Pos (13U) +#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 */ +#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control */ +#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 */ +#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 */ +#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 */ +#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 */ + +#define HPRT_PSPD_Pos (17U) +#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 */ +#define HPRT_PSPD HPRT_PSPD_Msk // Port speed */ +#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 */ +#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 */ + +/******************** Bit definition for DOEPEACHMSK1 register ********************/ +#define DOEPEACHMSK1_XFRCM_Pos (0U) +#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ +#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPEACHMSK1_EPDM_Pos (1U) +#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 */ +#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPEACHMSK1_TOM_Pos (3U) +#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 */ +#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask */ +#define DOEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ +#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DOEPEACHMSK1_INEPNMM_Pos (5U) +#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ +#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DOEPEACHMSK1_INEPNEM_Pos (6U) +#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ +#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DOEPEACHMSK1_TXFURM_Pos (8U) +#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ +#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask */ +#define DOEPEACHMSK1_BIM_Pos (9U) +#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 */ +#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DOEPEACHMSK1_BERRM_Pos (12U) +#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 */ +#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask */ +#define DOEPEACHMSK1_NAKM_Pos (13U) +#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 */ +#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ +#define DOEPEACHMSK1_NYETM_Pos (14U) +#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 */ +#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask */ + +/******************** Bit definition for HPTXFSIZ register ********************/ +#define HPTXFSIZ_PTXSA_Pos (0U) +#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF */ +#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address */ +#define HPTXFSIZ_PTXFD_Pos (16U) +#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 */ +#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth */ + +/******************** Bit definition for DIEPCTL register ********************/ +#define DIEPCTL_MPSIZ_Pos (0U) +#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF */ +#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size */ +#define DIEPCTL_USBAEP_Pos (15U) +#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 */ +#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint */ +#define DIEPCTL_EONUM_DPID_Pos (16U) +#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 */ +#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame */ +#define DIEPCTL_NAKSTS_Pos (17U) +#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 */ +#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status */ + +#define DIEPCTL_EPTYP_Pos (18U) +#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 */ +#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type */ +#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 */ +#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DIEPCTL_STALL_Pos (21U) +#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 */ +#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake */ + +#define DIEPCTL_TXFNUM_Pos (22U) +#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 */ +#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number */ +#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 */ +#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 */ +#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 */ +#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 */ +#define DIEPCTL_CNAK_Pos (26U) +#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 */ +#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK */ +#define DIEPCTL_SNAK_Pos (27U) +#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 */ +#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK */ +#define DIEPCTL_SD0PID_SEVNFRM_Pos (28U) +#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ +#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DIEPCTL_SODDFRM_Pos (29U) +#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 */ +#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame */ +#define DIEPCTL_EPDIS_Pos (30U) +#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 */ +#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable */ +#define DIEPCTL_EPENA_Pos (31U) +#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 */ +#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable */ + +/******************** Bit definition for HCCHAR register ********************/ +#define HCCHAR_MPSIZ_Pos (0U) +#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF */ +#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size */ + +#define HCCHAR_EPNUM_Pos (11U) +#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 */ +#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number */ +#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 */ +#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 */ +#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 */ +#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 */ +#define HCCHAR_EPDIR_Pos (15U) +#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 */ +#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction */ +#define HCCHAR_LSDEV_Pos (17U) +#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 */ +#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device */ + +#define HCCHAR_EPTYP_Pos (18U) +#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 */ +#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type */ +#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 */ +#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 */ + +#define HCCHAR_MC_Pos (20U) +#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 */ +#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) */ +#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 */ +#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 */ + +#define HCCHAR_DAD_Pos (22U) +#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 */ +#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address */ +#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 */ +#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 */ +#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 */ +#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 */ +#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 */ +#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 */ +#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 */ +#define HCCHAR_ODDFRM_Pos (29U) +#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 */ +#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame */ +#define HCCHAR_CHDIS_Pos (30U) +#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 */ +#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable */ +#define HCCHAR_CHENA_Pos (31U) +#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 */ +#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable */ + +/******************** Bit definition for HCSPLT register ********************/ + +#define HCSPLT_PRTADDR_Pos (0U) +#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F */ +#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address */ +#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 */ +#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 */ +#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 */ +#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 */ +#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 */ +#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 */ +#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 */ + +#define HCSPLT_HUBADDR_Pos (7U) +#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 */ +#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address */ +#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 */ +#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 */ +#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 */ +#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 */ +#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 */ +#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 */ +#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 */ + +#define HCSPLT_XACTPOS_Pos (14U) +#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 */ +#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS */ +#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 */ +#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 */ +#define HCSPLT_COMPLSPLT_Pos (16U) +#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 */ +#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split */ +#define HCSPLT_SPLITEN_Pos (31U) +#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 */ +#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable */ + +/******************** Bit definition for HCINT register ********************/ +#define HCINT_XFRC_Pos (0U) +#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 */ +#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed */ +#define HCINT_CHH_Pos (1U) +#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 */ +#define HCINT_CHH HCINT_CHH_Msk // Channel halted */ +#define HCINT_AHBERR_Pos (2U) +#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 */ +#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error */ +#define HCINT_STALL_Pos (3U) +#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 */ +#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt */ +#define HCINT_NAK_Pos (4U) +#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 */ +#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt */ +#define HCINT_ACK_Pos (5U) +#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 */ +#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt */ +#define HCINT_NYET_Pos (6U) +#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 */ +#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt */ +#define HCINT_TXERR_Pos (7U) +#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 */ +#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error */ +#define HCINT_BBERR_Pos (8U) +#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 */ +#define HCINT_BBERR HCINT_BBERR_Msk // Babble error */ +#define HCINT_FRMOR_Pos (9U) +#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 */ +#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun */ +#define HCINT_DTERR_Pos (10U) +#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 */ +#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error */ + +/******************** Bit definition for DIEPINT register ********************/ +#define DIEPINT_XFRC_Pos (0U) +#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 */ +#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DIEPINT_EPDISD_Pos (1U) +#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 */ +#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DIEPINT_AHBERR_Pos (2U) +#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 */ +#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction */ +#define DIEPINT_TOC_Pos (3U) +#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 */ +#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition */ +#define DIEPINT_ITTXFE_Pos (4U) +#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 */ +#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty */ +#define DIEPINT_INEPNM_Pos (5U) +#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 */ +#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch */ +#define DIEPINT_INEPNE_Pos (6U) +#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 */ +#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective */ +#define DIEPINT_TXFE_Pos (7U) +#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 */ +#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty */ +#define DIEPINT_TXFIFOUDRN_Pos (8U) +#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 */ +#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun */ +#define DIEPINT_BNA_Pos (9U) +#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 */ +#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt */ +#define DIEPINT_PKTDRPSTS_Pos (11U) +#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 */ +#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status */ +#define DIEPINT_BERR_Pos (12U) +#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 */ +#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt */ +#define DIEPINT_NAK_Pos (13U) +#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 */ +#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt */ + +/******************** Bit definition for HCINTMSK register ********************/ +#define HCINTMSK_XFRCM_Pos (0U) +#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 */ +#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask */ +#define HCINTMSK_CHHM_Pos (1U) +#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 */ +#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask */ +#define HCINTMSK_AHBERR_Pos (2U) +#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 */ +#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error */ +#define HCINTMSK_STALLM_Pos (3U) +#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 */ +#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask */ +#define HCINTMSK_NAKM_Pos (4U) +#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 */ +#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask */ +#define HCINTMSK_ACKM_Pos (5U) +#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 */ +#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask */ +#define HCINTMSK_NYET_Pos (6U) +#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 */ +#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask */ +#define HCINTMSK_TXERRM_Pos (7U) +#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 */ +#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask */ +#define HCINTMSK_BBERRM_Pos (8U) +#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 */ +#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask */ +#define HCINTMSK_FRMORM_Pos (9U) +#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 */ +#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask */ +#define HCINTMSK_DTERRM_Pos (10U) +#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 */ +#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask */ + +/******************** Bit definition for DIEPTSIZ register ********************/ + +#define DIEPTSIZ_XFRSIZ_Pos (0U) +#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ +#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DIEPTSIZ_PKTCNT_Pos (19U) +#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ +#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count */ +#define DIEPTSIZ_MULCNT_Pos (29U) +#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 */ +#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count */ + /******************** Bit definition for HCTSIZ register ********************/ +#define HCTSIZ_XFRSIZ_Pos (0U) +#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ +#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size */ +#define HCTSIZ_PKTCNT_Pos (19U) +#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 */ +#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count */ +#define HCTSIZ_DOPING_Pos (31U) +#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 */ +#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING */ +#define HCTSIZ_DPID_Pos (29U) +#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 */ +#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID */ +#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 */ +#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 */ + +/******************** Bit definition for DIEPDMA register ********************/ +#define DIEPDMA_DMAADDR_Pos (0U) +#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF */ +#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address */ + +/******************** Bit definition for HCDMA register ********************/ +#define HCDMA_DMAADDR_Pos (0U) +#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF */ +#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address */ + + /******************** Bit definition for DTXFSTS register ********************/ +#define DTXFSTS_INEPTFSAV_Pos (0U) +#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF */ +#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available */ + + /******************** Bit definition for DIEPTXF register ********************/ +#define DIEPTXF_INEPTXSA_Pos (0U) +#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF */ +#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address */ +#define DIEPTXF_INEPTXFD_Pos (16U) +#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 */ +#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth */ + +/******************** Bit definition for DOEPCTL register ********************/ +#define DOEPCTL_MPSIZ_Pos (0U) +#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF */ +#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size */ //Bit 1 */ +#define DOEPCTL_USBAEP_Pos (15U) +#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 */ +#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint */ +#define DOEPCTL_NAKSTS_Pos (17U) +#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 */ +#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status */ +#define DOEPCTL_SD0PID_SEVNFRM_Pos (28U) +#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ +#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DOEPCTL_SODDFRM_Pos (29U) +#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 */ +#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame */ +#define DOEPCTL_EPTYP_Pos (18U) +#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 */ +#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type */ +#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 */ +#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DOEPCTL_SNPM_Pos (20U) +#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 */ +#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode */ +#define DOEPCTL_STALL_Pos (21U) +#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 */ +#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake */ +#define DOEPCTL_CNAK_Pos (26U) +#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 */ +#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK */ +#define DOEPCTL_SNAK_Pos (27U) +#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 */ +#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK */ +#define DOEPCTL_EPDIS_Pos (30U) +#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 */ +#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable */ +#define DOEPCTL_EPENA_Pos (31U) +#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 */ +#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable */ + +/******************** Bit definition for DOEPINT register ********************/ +#define DOEPINT_XFRC_Pos (0U) +#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 */ +#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DOEPINT_EPDISD_Pos (1U) +#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 */ +#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DOEPINT_AHBERR_Pos (2U) +#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 */ +#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction */ +#define DOEPINT_STUP_Pos (3U) +#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 */ +#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done */ +#define DOEPINT_OTEPDIS_Pos (4U) +#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 */ +#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled */ +#define DOEPINT_OTEPSPR_Pos (5U) +#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 */ +#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write */ +#define DOEPINT_B2BSTUP_Pos (6U) +#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 */ +#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received */ +#define DOEPINT_OUTPKTERR_Pos (8U) +#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 */ +#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error */ +#define DOEPINT_NAK_Pos (13U) +#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 */ +#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device */ +#define DOEPINT_NYET_Pos (14U) +#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 */ +#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt */ +#define DOEPINT_STPKTRX_Pos (15U) +#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 */ +#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received */ + +/******************** Bit definition for DOEPTSIZ register ********************/ +#define DOEPTSIZ_XFRSIZ_Pos (0U) +#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ +#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DOEPTSIZ_PKTCNT_Pos (19U) +#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ +#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count */ + +#define DOEPTSIZ_STUPCNT_Pos (29U) +#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 */ +#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count */ +#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 */ +#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 */ + +/******************** Bit definition for PCGCTL register ********************/ +#define PCGCTL_IF_DEV_MODE TU_BIT(31) +#define PCGCTL_P2HD_PRT_SPD_MASK (0x3ul << 29) +#define PCGCTL_P2HD_PRT_SPD_SHIFT 29 +#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3ul << 27) +#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27 +#define PCGCTL_MAC_DEV_ADDR_MASK (0x7ful << 20) +#define PCGCTL_MAC_DEV_ADDR_SHIFT 20 +#define PCGCTL_MAX_TERMSEL TU_BIT(19) +#define PCGCTL_MAX_XCVRSELECT_MASK (0x3ul << 17) +#define PCGCTL_MAX_XCVRSELECT_SHIFT 17 +#define PCGCTL_PORT_POWER TU_BIT(16) +#define PCGCTL_PRT_CLK_SEL_MASK (0x3ul << 14) +#define PCGCTL_PRT_CLK_SEL_SHIFT 14 +#define PCGCTL_ESS_REG_RESTORED TU_BIT(13) +#define PCGCTL_EXTND_HIBER_SWITCH TU_BIT(12) +#define PCGCTL_EXTND_HIBER_PWRCLMP TU_BIT(11) +#define PCGCTL_ENBL_EXTND_HIBER TU_BIT(10) +#define PCGCTL_RESTOREMODE TU_BIT(9) +#define PCGCTL_RESETAFTSUSP TU_BIT(8) +#define PCGCTL_DEEP_SLEEP TU_BIT(7) +#define PCGCTL_PHY_IN_SLEEP TU_BIT(6) +#define PCGCTL_ENBL_SLEEP_GATING TU_BIT(5) +#define PCGCTL_RSTPDWNMODULE TU_BIT(3) +#define PCGCTL_PWRCLMP TU_BIT(2) +#define PCGCTL_GATEHCLK TU_BIT(1) +#define PCGCTL_STOPPCLK TU_BIT(0) + +#define PCGCTL1_TIMER (0x3ul << 1) +#define PCGCTL1_GATEEN TU_BIT(0) + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h new file mode 100644 index 000000000..4e6bebb01 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -0,0 +1,87 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Rafael Silva (@perigoso) + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _DWC2_XMC_H_ +#define _DWC2_XMC_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "xmc_device.h" + +// XMC has custom control register before DWC registers +#define DWC2_REG_BASE USB0_BASE +#define DWC2_EP_MAX 7 +#define DWC2_EP_FIFO_SIZE 2048 + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USB0_0_IRQn); +} + +TU_ATTR_ALWAYS_INLINE +static inline void dwc2_dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB0_0_IRQn); +} + +static inline void dwc2_remote_wakeup_delay(void) +{ + // try to delay for 1 ms +// uint32_t count = SystemCoreClock / 1000; +// while ( count-- ) __NOP(); +} + +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // Enable PHY + //USB->ROUTE = USB_ROUTE_PHYPEN; +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // XMC Manual: turn around must be 5 (reset & default value) + // dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/portable/synopsys/dwc2/hwcfg_list.md b/src/portable/synopsys/dwc2/hwcfg_list.md new file mode 100644 index 000000000..b5590da00 --- /dev/null +++ b/src/portable/synopsys/dwc2/hwcfg_list.md @@ -0,0 +1,777 @@ +# DWC2 Hardware Configuration Registers + +## Broadcom BCM2711 (Pi4) + +dwc2->guid = 2708A000 +dwc2->gsnpsid = 4F54280A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 228DDD50 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 1 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 7 +hw_cfg2->num_host_ch = 7 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 0 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = FF000E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 4080 + +dwc2->ghwcfg4 = 1FF00020 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 0 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 0 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 15 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## EFM32GG FS + +dwc2->guid = 0 +dwc2->gsnpsid = 4F54330A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 228F5910 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 6 +hw_cfg2->num_host_ch = 13 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 0 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 1F204E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 1 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 498 + +dwc2->ghwcfg4 = 1BF08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 13 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## ESP32-S2 Fullspeed + +dwc2->guid = 0 +dwc2->gsnpsid = 4F54400A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 224DD930 +hw_cfg2->op_mode = 2 +hw_cfg2->arch = 3 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 1 +hw_cfg2->fs_phy_type = 2 +hw_cfg2->num_dev_ep = 6 +hw_cfg2->num_host_ch = 9 +hw_cfg2->period_channel_support = 0 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 1 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 22 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = C804B5 +hw_cfg3->xfer_size_width = 10 +hw_cfg3->packet_size_width = 5 +hw_cfg3->otg_enable = 0 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 1 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 1 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 23130 + +dwc2->ghwcfg4 = D3F0A030 +hw_cfg4->num_dev_period_in_ep = 10 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 0 +hw_cfg4->hibernation = 1 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 1 +hw_cfg4->acg_enable = 1 +hw_cfg4->utmi_phy_data_width = 1 +hw_cfg4->dev_ctrl_ep_num = 10 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 0 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 0 +hw_cfg4->dedicated_fifos = 0 +hw_cfg4->num_dev_in_eps = 13 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 1 + +## STM32F407 and STM32F207 + +STM32F407 and STM32F207 are exactly the same + +### STM32F407 Fullspeed + +dwc2->guid = 1200 +dwc2->gsnpsid = 4F54281A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229DCD20 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 3 +hw_cfg2->num_host_ch = 7 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 20001E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = FF08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 7 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +### STM32F407 Highspeed + +dwc2->guid = 1100 +dwc2->gsnpsid = 4F54281A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229ED590 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 2 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 5 +hw_cfg2->num_host_ch = 11 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 3F403E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 1 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 1012 + +dwc2->ghwcfg4 = 17F00030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 0 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 11 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## STM32F411 Fullspeed + +dwc2->guid = 1200 +dwc2->gsnpsid = 4F54281A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229DCD20 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 3 +hw_cfg2->num_host_ch = 7 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 20001E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = FF08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 7 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## STM32F412 FS + +dwc2->guid = 2000 +dwc2->gsnpsid = 4F54320A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229ED520 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 5 +hw_cfg2->num_host_ch = 11 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 200D1E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = 17F08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 11 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## STM32F723 + +### STM32F723 HighSpeed + +dwc2->guid = 3100 +dwc2->gsnpsid = 4F54330A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229FE1D0 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 3 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 8 +hw_cfg2->num_host_ch = 15 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 3EED2E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 1 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 1006 + +dwc2->ghwcfg4 = 23F00030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 0 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 1 +hw_cfg4->dma_desc_enable = 1 +hw_cfg4->dma_dynamic = 0 + +### STM32F723 Fullspeed + +dwc2->guid = 3000 +dwc2->gsnpsid = 4F54330A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229ED520 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 5 +hw_cfg2->num_host_ch = 11 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 200D1E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = 17F08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 11 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## STM32F767 FS + +dwc2->guid = 2000 +dwc2->gsnpsid = 4F54320A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229ED520 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 5 +hw_cfg2->num_host_ch = 11 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 200D1E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = 17F08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 11 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## STM32H743 (both cores HS) + +dwc2->guid = 2300 +dwc2->gsnpsid = 4F54330A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229FE190 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 2 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 8 +hw_cfg2->num_host_ch = 15 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 3B8D2E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 1 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 952 + +dwc2->ghwcfg4 = E3F00030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 0 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 1 +hw_cfg4->dma_desc_enable = 1 +hw_cfg4->dma_dynamic = 1 + +## STM32L476 FS + +dwc2->guid = 2000 +dwc2->gsnpsid = 4F54310A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 229ED520 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 5 +hw_cfg2->num_host_ch = 11 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 1 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 200D1E8 +hw_cfg3->xfer_size_width = 8 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 1 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 1 +hw_cfg3->lpm_mode = 1 +hw_cfg3->total_fifo_size = 512 + +dwc2->ghwcfg4 = 17F08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 11 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## GD32VF103 Fullspeed + +dwc2->guid = 1000 +dwc2->gsnpsid = 0 +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 0 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 0 +hw_cfg2->point2point = 0 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 0 +hw_cfg2->num_dev_ep = 0 +hw_cfg2->num_host_ch = 0 +hw_cfg2->period_channel_support = 0 +hw_cfg2->enable_dynamic_fifo = 0 +hw_cfg2->mul_cpu_int = 0 +hw_cfg2->nperiod_tx_q_depth = 0 +hw_cfg2->host_period_tx_q_depth = 0 +hw_cfg2->dev_token_q_depth = 0 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 0 +hw_cfg3->xfer_size_width = 0 +hw_cfg3->packet_size_width = 0 +hw_cfg3->otg_enable = 0 +hw_cfg3->i2c_enable = 0 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 0 + +dwc2->ghwcfg4 = 0 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 0 +hw_cfg4->ahb_freq_min = 0 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 0 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 0 +hw_cfg4->vbus_valid_filter_enabled = 0 +hw_cfg4->a_valid_filter_enabled = 0 +hw_cfg4->b_valid_filter_enabled = 0 +hw_cfg4->dedicated_fifos = 0 +hw_cfg4->num_dev_in_eps = 0 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 0 + +## XMC4500 + +dwc2->guid = AEC000 +dwc2->gsnpsid = 4F54292A +dwc2->ghwcfg1 = 0 + +dwc2->ghwcfg2 = 228F5930 +hw_cfg2->op_mode = 0 +hw_cfg2->arch = 2 +hw_cfg2->point2point = 1 +hw_cfg2->hs_phy_type = 0 +hw_cfg2->fs_phy_type = 1 +hw_cfg2->num_dev_ep = 6 +hw_cfg2->num_host_ch = 13 +hw_cfg2->period_channel_support = 1 +hw_cfg2->enable_dynamic_fifo = 1 +hw_cfg2->mul_cpu_int = 0 +hw_cfg2->nperiod_tx_q_depth = 2 +hw_cfg2->host_period_tx_q_depth = 2 +hw_cfg2->dev_token_q_depth = 8 +hw_cfg2->otg_enable_ic_usb = 0 + +dwc2->ghwcfg3 = 27A01E5 +hw_cfg3->xfer_size_width = 5 +hw_cfg3->packet_size_width = 6 +hw_cfg3->otg_enable = 1 +hw_cfg3->i2c_enable = 1 +hw_cfg3->vendor_ctrl_itf = 0 +hw_cfg3->optional_feature_removed = 0 +hw_cfg3->synch_reset = 0 +hw_cfg3->otg_adp_support = 0 +hw_cfg3->otg_enable_hsic = 0 +hw_cfg3->battery_charger_support = 0 +hw_cfg3->lpm_mode = 0 +hw_cfg3->total_fifo_size = 634 + +dwc2->ghwcfg4 = DBF08030 +hw_cfg4->num_dev_period_in_ep = 0 +hw_cfg4->power_optimized = 1 +hw_cfg4->ahb_freq_min = 1 +hw_cfg4->hibernation = 0 +hw_cfg4->service_interval_mode = 0 +hw_cfg4->ipg_isoc_en = 0 +hw_cfg4->acg_enable = 0 +hw_cfg4->utmi_phy_data_width = 2 +hw_cfg4->dev_ctrl_ep_num = 0 +hw_cfg4->iddg_filter_enabled = 1 +hw_cfg4->vbus_valid_filter_enabled = 1 +hw_cfg4->a_valid_filter_enabled = 1 +hw_cfg4->b_valid_filter_enabled = 1 +hw_cfg4->dedicated_fifos = 1 +hw_cfg4->num_dev_in_eps = 13 +hw_cfg4->dma_desc_enable = 0 +hw_cfg4->dma_dynamic = 1 diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 12b9144bf..977369300 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -94,6 +94,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return false; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; +} + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 027ed26c9..3b91f2798 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -242,7 +242,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) } xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = desc_edpt->wMaxPacketSize.size; + xfer->max_size = tu_edpt_packet_size(desc_edpt); // Buffer allocation scheme: // For simplicity, only single buffer for now, since tinyusb currently waits @@ -275,7 +275,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // Also, DBUF got set on OUT EP 2 while debugging. Only OUT EPs seem to be // affected at this time. USB RAM directly precedes main RAM; perhaps I'm // overwriting registers via buffer overflow w/ my debugging code? - ep_regs[SIZXY] = desc_edpt->wMaxPacketSize.size; + ep_regs[SIZXY] = tu_edpt_packet_size(desc_edpt); ep_regs[BCTX] |= NAK; ep_regs[BBAX] = buf_base; ep_regs[CNF] &= ~(TOGGLE | STALL | DBUF); // ISO xfers not supported on @@ -298,6 +298,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; @@ -541,6 +547,7 @@ static void transmit_packet(uint8_t ep_num) } // Then actually commit to transmit a packet. + uint8_t * base = (xfer->buffer + xfer->queued_len); uint16_t remaining = xfer->total_len - xfer->queued_len; uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; @@ -554,7 +561,6 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { volatile uint8_t * ep0in_buf = &USBIEP0BUF; - uint8_t * base = (xfer->buffer + xfer->queued_len); for(uint16_t i = 0; i < xfer_size; i++) { ep0in_buf[i] = base[i]; @@ -576,7 +582,6 @@ static void transmit_packet(uint8_t ep_num) else #endif { - uint8_t * base = (xfer->buffer + xfer->queued_len); for(int i = 0; i < xfer_size; i++) { ep_buf[i] = base[i]; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index b68f04faa..837d0c0ce 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -314,13 +314,13 @@ static void dcd_reset(void) usb_in_ctrl_write(1 << CSR_USB_IN_CTRL_RESET_OFFSET); usb_out_ctrl_write(1 << CSR_USB_OUT_CTRL_RESET_OFFSET); - memset((void *)rx_buffer, 0, sizeof(rx_buffer)); - memset((void *)rx_buffer_max, 0, sizeof(rx_buffer_max)); - memset((void *)rx_buffer_offset, 0, sizeof(rx_buffer_offset)); + memset((void *)(uintptr_t) rx_buffer, 0, sizeof(rx_buffer)); + memset((void *)(uintptr_t) rx_buffer_max, 0, sizeof(rx_buffer_max)); + memset((void *)(uintptr_t) rx_buffer_offset, 0, sizeof(rx_buffer_offset)); - memset((void *)tx_buffer, 0, sizeof(tx_buffer)); - memset((void *)tx_buffer_max, 0, sizeof(tx_buffer_max)); - memset((void *)tx_buffer_offset, 0, sizeof(tx_buffer_offset)); + memset((void *)(uintptr_t) tx_buffer, 0, sizeof(tx_buffer)); + memset((void *)(uintptr_t) tx_buffer_max, 0, sizeof(tx_buffer_max)); + memset((void *)(uintptr_t) tx_buffer_offset, 0, sizeof(tx_buffer_offset)); tx_ep = 0; tx_active = false; @@ -429,6 +429,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +void dcd_edpt_close_all (uint8_t rhport) +{ + (void) rhport; + // TODO implement dcd_edpt_close_all() +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/tusb.c b/src/tusb.c index 6494287d2..9583f509d 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -69,7 +69,7 @@ bool tusb_inited(void) bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) { - uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); switch (desc_ep->bmAttributes.xfer) @@ -109,9 +109,9 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) { uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; + uint8_t const* desc_end = p_desc + desc_len; - while( len < desc_len ) + while( p_desc < desc_end ) { if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { @@ -121,7 +121,6 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_ ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - len = (uint16_t)(len + tu_desc_len(p_desc)); p_desc = tu_desc_next(p_desc); } } diff --git a/src/tusb.h b/src/tusb.h index b52f8839a..0d29e106c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -76,9 +76,13 @@ #include "class/msc/msc_device.h" #endif -#if CFG_TUD_AUDIO - #include "class/audio/audio_device.h" -#endif + #if CFG_TUD_AUDIO + #include "class/audio/audio_device.h" + #endif + + #if CFG_TUD_VIDEO + #include "class/video/video_device.h" + #endif #if CFG_TUD_MIDI #include "class/midi/midi_device.h" @@ -100,7 +104,7 @@ #include "class/dfu/dfu_device.h" #endif - #if CFG_TUD_NET + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index d04cb54f0..54e46996d 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -27,8 +27,10 @@ #ifndef _TUSB_OPTION_H_ #define _TUSB_OPTION_H_ +#include "common/tusb_compiler.h" + #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 11 +#define TUSB_VERSION_MINOR 12 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) @@ -36,7 +38,6 @@ // Supported MCUs // CFG_TUSB_MCU must be defined to one of following value //--------------------------------------------------------------------+ -#define TU_CHECK_MCU(_m) (CFG_TUSB_MCU == OPT_MCU_##_m) #define OPT_MCU_NONE 0 @@ -67,22 +68,27 @@ #define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family // STM32 -#define OPT_MCU_STM32F0 300 ///< ST STM32F0 -#define OPT_MCU_STM32F1 301 ///< ST STM32F1 -#define OPT_MCU_STM32F2 302 ///< ST STM32F2 -#define OPT_MCU_STM32F3 303 ///< ST STM32F3 -#define OPT_MCU_STM32F4 304 ///< ST STM32F4 -#define OPT_MCU_STM32F7 305 ///< ST STM32F7 -#define OPT_MCU_STM32H7 306 ///< ST STM32H7 -#define OPT_MCU_STM32L0 307 ///< ST STM32L0 -#define OPT_MCU_STM32L1 308 ///< ST STM32L1 -#define OPT_MCU_STM32L4 309 ///< ST STM32L4 +#define OPT_MCU_STM32F0 300 ///< ST F0 +#define OPT_MCU_STM32F1 301 ///< ST F1 +#define OPT_MCU_STM32F2 302 ///< ST F2 +#define OPT_MCU_STM32F3 303 ///< ST F3 +#define OPT_MCU_STM32F4 304 ///< ST F4 +#define OPT_MCU_STM32F7 305 ///< ST F7 +#define OPT_MCU_STM32H7 306 ///< ST H7 +#define OPT_MCU_STM32L1 308 ///< ST L1 +#define OPT_MCU_STM32L0 307 ///< ST L0 +#define OPT_MCU_STM32L4 309 ///< ST L4 +#define OPT_MCU_STM32G0 310 ///< ST G0 +#define OPT_MCU_STM32G4 311 ///< ST G4 // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 -// TI MSP430 +// TI #define OPT_MCU_MSP430x5xx 500 ///< TI MSP430x5xx +#define OPT_MCU_MSP432E4 510 ///< TI MSP432E4xx +#define OPT_MCU_TM4C123 511 ///< TI Tiva-C 123x +#define OPT_MCU_TM4C129 512 ///< TI Tiva-C 129x // ValentyUSB eptri #define OPT_MCU_VALENTYUSB_EPTRI 600 ///< Fomu eptri config @@ -112,8 +118,6 @@ // Silabs #define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG -#define OPT_MCU_EFM32GG11 1301 ///< Silabs EFM32GG11 -#define OPT_MCU_EFM32GG12 1302 ///< Silabs EFM32GG12 // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 @@ -126,9 +130,20 @@ // GigaDevice #define OPT_MCU_GD32VF103 1600 ///< GigaDevice GD32VF103 +// Broadcom +#define OPT_MCU_BCM2711 1700 ///< Broadcom BCM2711 + +// Infineon +#define OPT_MCU_XMC4000 1800 ///< Infineon XMC4000 + // BridgeTek -#define OPT_MCU_FT90X 1700 ///< BridgeTek FT90x -#define OPT_MCU_FT93X 1701 ///< BridgeTek FT93x +#define OPT_MCU_FT90X 1900 ///< BridgeTek FT90x +#define OPT_MCU_FT93X 1901 ///< BridgeTek FT93x + +// Helper to check if configured MCU is one of listed +// Apply _TU_CHECK_MCU with || as separator to list of input +#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) +#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) //--------------------------------------------------------------------+ // Supported OS @@ -207,14 +222,20 @@ #define CFG_TUSB_MEM_SECTION #endif +// alignment requirement of buffer used for endpoint transferring #ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif +// OS selection #ifndef CFG_TUSB_OS #define CFG_TUSB_OS OPT_OS_NONE #endif +#ifndef CFG_TUSB_OS_INC_PATH + #define CFG_TUSB_OS_INC_PATH +#endif + //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- @@ -239,6 +260,10 @@ #define CFG_TUD_AUDIO 0 #endif +#ifndef CFG_TUD_VIDEO + #define CFG_TUD_VIDEO 0 +#endif + #ifndef CFG_TUD_MIDI #define CFG_TUD_MIDI 0 #endif @@ -259,14 +284,23 @@ #define CFG_TUD_DFU 0 #endif -#ifndef CFG_TUD_NET - #define CFG_TUD_NET 0 -#endif - #ifndef CFG_TUD_BTH #define CFG_TUD_BTH 0 #endif +#ifndef CFG_TUD_ECM_RNDIS + #ifdef CFG_TUD_NET + #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" + #define CFG_TUD_ECM_RNDIS CFG_TUD_NET + #else + #define CFG_TUD_ECM_RNDIS 0 + #endif +#endif + +#ifndef CFG_TUD_NCM + #define CFG_TUD_NCM 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS //-------------------------------------------------------------------- @@ -278,10 +312,34 @@ #ifndef CFG_TUH_ENUMERATION_BUFSIZE #define CFG_TUH_ENUMERATION_BUFSIZE 256 #endif - - //------------- CLASS -------------// #endif // TUSB_OPT_HOST_ENABLED +//------------- CLASS -------------// + +#ifndef CFG_TUH_HUB +#define CFG_TUH_HUB 0 +#endif + +#ifndef CFG_TUH_CDC +#define CFG_TUH_CDC 0 +#endif + +#ifndef CFG_TUH_HID +#define CFG_TUH_HID 0 +#endif + +#ifndef CFG_TUH_MIDI +#define CFG_TUH_MIDI 0 +#endif + +#ifndef CFG_TUH_MSC +#define CFG_TUH_MSC 0 +#endif + +#ifndef CFG_TUH_VENDOR +#define CFG_TUH_VENDOR 0 +#endif + //--------------------------------------------------------------------+ // Port Specific // TUP stand for TinyUSB Port (can be renamed) diff --git a/tools/iar_gen.py b/tools/iar_gen.py new file mode 100644 index 000000000..73c8b29fc --- /dev/null +++ b/tools/iar_gen.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 + +import os +import xml.dom.minidom as XML + +# Read base configuration +base = "" +with open("iar_template.ipcf") as f: + base = f.read() + +# Enumerate all device/host examples +dir_1 = os.listdir("../examples") +for dir_2 in dir_1: + if os.path.isdir("../examples/{}".format(dir_2)): + print(dir_2) + examples = os.listdir("../examples/{}".format(dir_2)) + for example in examples: + if os.path.isdir("../examples/{}/{}".format(dir_2, example)): + print("../examples/{}/{}".format(dir_2, example)) + conf = XML.parseString(base) + files = conf.getElementsByTagName("files")[0] + inc = conf.getElementsByTagName("includePath")[0] + # Add bsp inc + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw") + path.appendChild(path_txt) + inc.appendChild(path) + # Add board.c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "bsp") + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + # Add example's .c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "example") + for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): + if file.endswith(".c") or file.endswith(".h"): + path = conf.createElement('path') + path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) + path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + cfg_str = conf.toprettyxml() + cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) + #print(cfg_str) + with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: + f.write(cfg_str) diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf new file mode 100644 index 000000000..ba54fe057 --- /dev/null +++ b/tools/iar_template.ipcf @@ -0,0 +1,145 @@ + + + + + $TUSB_DIR$/src + $TUSB_DIR$/lib/SEGGER_RTT/RTT + $PROJ_DIR$ + + + + $TUSB_DIR$/src/device/usbd.c + $TUSB_DIR$/src/device/usbd_control.c + + + $TUSB_DIR$/src/common/tusb_fifo.c + + + $TUSB_DIR$/src/class/audio/audio_device.c + + + $TUSB_DIR$/src/class/bth/bth_device.c + + + $TUSB_DIR$/src/class/cdc/cdc_device.c + $TUSB_DIR$/src/class/cdc/cdc_host.c + $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c + + + $TUSB_DIR$/src/class/dfu/dfu_device.c + $TUSB_DIR$/src/class/dfu/dfu_rt_device.c + + + $TUSB_DIR$/src/class/hid/hid_device.c + $TUSB_DIR$/src/class/hid/hid_host.c + + + $TUSB_DIR$/src/class/midi/midi_device.c + + + $TUSB_DIR$/src/class/msc/msc_device.c + $TUSB_DIR$/src/class/msc/msc_host.c + + + $TUSB_DIR$/src/class/net/ecm_rndis_device.c + $TUSB_DIR$/src/class/net/ncm_device.c + + + $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c + + + $TUSB_DIR$/src/class/vendor/vendor_device.c + $TUSB_DIR$/src/class/vendor/vendor_host.c + + + $TUSB_DIR$/src/tusb.c + + + $TUSB_DIR$/src/host/hub.c + $TUSB_DIR$/src/host/usbh.c + $TUSB_DIR$/src/host/usbh_control.c + + + $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c + + + $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c + + + $TUSB_DIR$/src/portable/ehci/ehci.c + + + $TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c + + + $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c + + + $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c + + + $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c + + + $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c + + + $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c + + + $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c + + + $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c + + + $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c + $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c + + + $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + + + $TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c + $TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c + + + $TUSB_DIR$/src/portable/ohci/ohci.c + + + $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c + + + $TUSB_DIR$/src/portable/renesas/usba/dcd_usba.c + + + $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c + + + $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + + + $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c + + + $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c + + + $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c + $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c + $TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c + + + +