diff options
| author | Ha Thach <[email protected]> | 2023-09-11 22:22:13 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-11 22:22:13 +0700 |
| commit | 6d922de0cb11e2aa8e1b64b0c2019a2a8649b96c (patch) | |
| tree | 1ef048dfc752e73faddc452d15d685872f064a7b | |
| parent | 702740a3e283165fdb63c53d0b51bf78c9bddb36 (diff) | |
| parent | f55052b61f548f0f28ec8c1b9b706f34424c58d1 (diff) | |
Merge pull request #2251 from hathach/add-max3421e-hcd
Add max3421e host driver
73 files changed, 2060 insertions, 303 deletions
diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 70385bc1b..975f351a0 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -38,7 +38,6 @@ jobs: - 'lpc11 lpc13 lpc15 lpc17' - 'lpc51 lpc54' - 'mm32 msp432e4' - - 'nrf' - 'samd11 same5x saml2x' - 'stm32f2 stm32f3' - 'stm32l0 stm32u5 stm32wb' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index e3a00f9c5..4b788a213 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -38,6 +38,7 @@ jobs: - 'lpc18 lpc40 lpc43' - 'lpc55' - 'mcx' + - 'nrf' - 'ra' - 'rp2040' - 'samd21' diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 2a7babf3f..89ec1066c 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -33,6 +33,7 @@ <configuration PROFILE_NAME="lpc54628" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=lpcxpresso54628 -DLOG=4 -DLOGGER=RTT" /> <configuration PROFILE_NAME="lpc55s69" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=lpcxpresso55s69 -DLOG=4 -DLOGGER=RTT" /> <configuration PROFILE_NAME="mcxn947" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=mcxn947brk -DLOG=3 -DLOGGER=RTT" /> + <configuration PROFILE_NAME="feather_nrf52840_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_nrf52840_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" /> <configuration PROFILE_NAME="pca10056" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" /> <configuration PROFILE_NAME="pca10095" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10095 -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" /> <configuration PROFILE_NAME="stm32g0b1nucleo" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32g0b1nucleo" /> @@ -52,8 +53,8 @@ <configuration PROFILE_NAME="ra6m5 PORT0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1 -DPORT=0" /> <configuration PROFILE_NAME="uno_r4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=uno_r4 -DLOG=4 -DLOGGER=RTT" /> <configuration PROFILE_NAME="portenta_c33" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=portenta_c33 -DLOG=3" /> - <configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT" /> - <configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT" /> + <configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" /> + <configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" /> </configurations> </component> </project>
\ No newline at end of file diff --git a/.idea/runConfigurations/kl25.xml b/.idea/runConfigurations/kl25.xml index a08c20d44..66f8ea684 100644 --- a/.idea/runConfigurations/kl25.xml +++ b/.idea/runConfigurations/kl25.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="kl25" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MKL25Z128xxx4" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="kl25" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MKL25Z128xxx4" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/lpc1857.xml b/.idea/runConfigurations/lpc1857.xml index 7525f51f7..f7d4ba402 100644 --- a/.idea/runConfigurations/lpc1857.xml +++ b/.idea/runConfigurations/lpc1857.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="lpc1857" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "lpc1857" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="lpc1857" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "lpc1857" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/lpc4088.xml b/.idea/runConfigurations/lpc4088.xml index 7b32b2b85..911876903 100644 --- a/.idea/runConfigurations/lpc4088.xml +++ b/.idea/runConfigurations/lpc4088.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="lpc4088" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "lpc4088" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="lpc4088" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "lpc4088" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/lpc54628.xml b/.idea/runConfigurations/lpc54628.xml new file mode 100644 index 000000000..e0047f187 --- /dev/null +++ b/.idea/runConfigurations/lpc54628.xml @@ -0,0 +1,10 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="lpc54628" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "LPC54628J512" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> + <debugger kind="GDB" isBundled="true" /> + </custom-gdb-server> + <method v="2"> + <option name="CLION.COMPOUND.BUILD" enabled="true" /> + </method> + </configuration> +</component>
\ No newline at end of file diff --git a/.idea/runConfigurations/lpc55s69.xml b/.idea/runConfigurations/lpc55s69.xml new file mode 100644 index 000000000..d5e9b117a --- /dev/null +++ b/.idea/runConfigurations/lpc55s69.xml @@ -0,0 +1,10 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="lpc55s69" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "lpc55s69" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> + <debugger kind="GDB" isBundled="true" /> + </custom-gdb-server> + <method v="2"> + <option name="CLION.COMPOUND.BUILD" enabled="true" /> + </method> + </configuration> +</component>
\ No newline at end of file diff --git a/.idea/runConfigurations/mcx947.xml b/.idea/runConfigurations/mcx947.xml index 77dec59f8..31e5c27dd 100644 --- a/.idea/runConfigurations/mcx947.xml +++ b/.idea/runConfigurations/mcx947.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="mcx947" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MCXN947_M33_0" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $ProjectFileDir$/hw/bsp/mcx/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="mcx947" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MCXN947_M33_0" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $ProjectFileDir$/hw/bsp/mcx/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/nrf52840.xml b/.idea/runConfigurations/nrf52840.xml index 084669c39..3ffa16385 100644 --- a/.idea/runConfigurations/nrf52840.xml +++ b/.idea/runConfigurations/nrf52840.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="nrf52840" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "nrf52840_xxaa" -if swd -speed 8000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="nrf52840" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-select usb=752001685 -device "nrf52840_xxaa" -if swd -speed 8000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/nrf5340.xml b/.idea/runConfigurations/nrf5340.xml index 98fe39d80..2f8009444 100644 --- a/.idea/runConfigurations/nrf5340.xml +++ b/.idea/runConfigurations/nrf5340.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="nrf5340" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "nrf5340_xxaa_app" -if swd -speed 16000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="nrf5340" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-select usb=752001685 -device "nrf5340_xxaa_app" -if swd -speed 16000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/ra4m1.xml b/.idea/runConfigurations/ra4m1.xml index 561b509a2..6135e5cf3 100644 --- a/.idea/runConfigurations/ra4m1.xml +++ b/.idea/runConfigurations/ra4m1.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="ra4m1" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA4M1AB" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="ra4m1" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA4M1AB" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/ra6m1.xml b/.idea/runConfigurations/ra6m1.xml index 099510c60..0833d43b3 100644 --- a/.idea/runConfigurations/ra6m1.xml +++ b/.idea/runConfigurations/ra6m1.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="ra6m1" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA6M1AD" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="ra6m1" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA6M1AD" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/ra6m5.xml b/.idea/runConfigurations/ra6m5.xml index 0cffac135..606e04e52 100644 --- a/.idea/runConfigurations/ra6m5.xml +++ b/.idea/runConfigurations/ra6m5.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="ra6m5" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA6M5BH" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="ra6m5" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA6M5BH" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/rt1010.xml b/.idea/runConfigurations/rt1010.xml index 63df076b1..f4f48181c 100644 --- a/.idea/runConfigurations/rt1010.xml +++ b/.idea/runConfigurations/rt1010.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="rt1010" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MIMXRT1011xxx5A" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $ProjectFileDir$/hw/bsp/imxrt/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="rt1010" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MIMXRT1011xxx5A" -if swd -speed 50000 -port 25321 -nogui -singlerun -jlinkscriptfile $ProjectFileDir$/hw/bsp/imxrt/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/rt1060.xml b/.idea/runConfigurations/rt1060.xml index 147f197a2..3d740edeb 100644 --- a/.idea/runConfigurations/rt1060.xml +++ b/.idea/runConfigurations/rt1060.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="rt1060" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MIMXRT1062xxx5A" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="rt1060" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "MIMXRT1062xxx5A" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/samd21g18.xml b/.idea/runConfigurations/samd21g18.xml new file mode 100644 index 000000000..9a1e65563 --- /dev/null +++ b/.idea/runConfigurations/samd21g18.xml @@ -0,0 +1,10 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="samd21g18" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "ATSAMD21G18" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> + <debugger kind="GDB" isBundled="true" /> + </custom-gdb-server> + <method v="2"> + <option name="CLION.COMPOUND.BUILD" enabled="true" /> + </method> + </configuration> +</component>
\ No newline at end of file diff --git a/.idea/runConfigurations/samd51j19.xml b/.idea/runConfigurations/samd51j19.xml new file mode 100644 index 000000000..74d0e3649 --- /dev/null +++ b/.idea/runConfigurations/samd51j19.xml @@ -0,0 +1,10 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="samd51j19" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "ATSAMD51J19A" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> + <debugger kind="GDB" isBundled="true" /> + </custom-gdb-server> + <method v="2"> + <option name="CLION.COMPOUND.BUILD" enabled="true" /> + </method> + </configuration> +</component>
\ No newline at end of file diff --git a/.idea/runConfigurations/stlink.xml b/.idea/runConfigurations/stlink.xml index 7e9166d90..b29b63f1a 100644 --- a/.idea/runConfigurations/stlink.xml +++ b/.idea/runConfigurations/stlink.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="stlink" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-p 62847 -cp "/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.0.600.202301161003/tools/bin" --frequency 24000 --swd" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="stlink" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-p 62847 -cp "/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.0.600.202301161003/tools/bin" --frequency 24000 --swd" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::62847" executable="/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.linux64_2.0.500.202301161003/tools/bin/ST-LINK_gdbserver" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/stm32g474.xml b/.idea/runConfigurations/stm32g474.xml index 2e4c4b82a..a7267fe90 100644 --- a/.idea/runConfigurations/stm32g474.xml +++ b/.idea/runConfigurations/stm32g474.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="stm32g474" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "stm32g474re" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="stm32g474" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "stm32g474re" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/stm32h743.xml b/.idea/runConfigurations/stm32h743.xml index f0ab6e9e7..9cd142de0 100644 --- a/.idea/runConfigurations/stm32h743.xml +++ b/.idea/runConfigurations/stm32h743.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="stm32h743" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "stm32h743xi" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="stm32h743" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "stm32h743xi" -if swd -speed 50000 -port 25321 -nogui -singlerun" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/.idea/runConfigurations/uno_r4.xml b/.idea/runConfigurations/uno_r4.xml index e9e1ebb8d..75eb3df4d 100644 --- a/.idea/runConfigurations/uno_r4.xml +++ b/.idea/runConfigurations/uno_r4.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="uno_r4" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA4M1AB" -if swd -speed 20000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="rp2040" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> + <configuration default="false" name="uno_r4" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" PROGRAM_PARAMS="-device "R7FA4M1AB" -if swd -speed 20000 -port 25321 -nogui -singlerun -jlinkscriptfile $PROJECT_DIR$/hw/bsp/ra/debug.jlinkscript" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="feather_nrf52840_express" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc"> <custom-gdb-server version="1" gdb-connect="tcp::25321" executable="/usr/bin/JLinkGDBServer" warmup-ms="0" download-type="UPDATED_ONLY" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD"> <debugger kind="GDB" isBundled="true" /> </custom-gdb-server> diff --git a/README.rst b/README.rst index d72cdb149..aef310b98 100644 --- a/README.rst +++ b/README.rst @@ -33,6 +33,7 @@ Supported MCUs The stack supports the following MCUs: - **Allwinner:** F1C100s/F1C200s +- **Analog:** MAX3421e (aka Arduino usb host shield) - **Broadcom:** BCM2837, BCM2711 - **Dialog:** DA1469x - **Espressif:** ESP32-S2, ESP32-S3 @@ -46,12 +47,13 @@ The stack supports the following MCUs: - iMX RT Series: RT10xx, RT11xx - Kinetis: KL25, K32L2 - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 + - MCX: N9x - **Raspberry Pi:** RP2040 - **Renesas:** - - RX Series: 63N, 65N, 72N - - RA Series: RA4M1, RA4M3 + - RX Series: 63n, 65n, 72n + - RA Series: 4m1, 4m3, 6m1, 6m5 - **Silabs:** EFM32GG - **Sony:** CXD56 @@ -87,6 +89,8 @@ Host Stack - Human Interface Device (HID): Keyboard, Mouse, Generic - Mass Storage Class (MSC) +- Communication Device Class: CDC-ACM +- Vendor serial over USB: FTDI, CP210x - Hub with multiple-level support Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. diff --git a/examples/dual/host_hid_to_device_cdc/only.txt b/examples/dual/host_hid_to_device_cdc/only.txt index a3b567f9a..cfc87eb4e 100644 --- a/examples/dual/host_hid_to_device_cdc/only.txt +++ b/examples/dual/host_hid_to_device_cdc/only.txt @@ -3,3 +3,4 @@ board:mimxrt1064_evk board:mcb1800 mcu:RP2040 mcu:ra6m5 +mcu:MAX3421 diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index abb75f068..c8e9138e3 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -35,9 +35,9 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB #endif // RHPort number used for host can be defined by board.mk, default to port 0 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index 1e0d067bf..b4ccd8223 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -35,11 +35,12 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB #endif + // RHPort number used for host can be defined by board.mk, default to port 0 #ifndef BOARD_TUH_RHPORT #define BOARD_TUH_RHPORT 0 diff --git a/examples/make.mk b/examples/make.mk index a590e34f7..8fe4a3486 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -73,7 +73,6 @@ ifeq ($(FAMILY),) else # Include Family and Board specific defs include $(TOP)/$(FAMILY_PATH)/family.mk - SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) endif @@ -84,9 +83,6 @@ CROSS_COMPILE ?= arm-none-eabi- ifeq ($(TOOLCHAIN),iar) CC := iccarm -endif - -ifeq ($(CC),iccarm) USE_IAR = 1 endif @@ -105,13 +101,12 @@ endif #-------------- Source files and compiler flags -------------- # tinyusb makefile include $(TOP)/src/tinyusb.mk +SRC_C += $(TINYUSB_SRC_C) # Include all source C in family & board folder SRC_C += hw/bsp/board.c SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(BOARD_PATH)/*.c)) -SRC_C += $(TINYUSB_SRC_C) - INC += \ $(TOP)/$(FAMILY_PATH) \ $(TOP)/src \ @@ -119,6 +114,12 @@ INC += \ BOARD_UPPER = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(BOARD)))))))))))))))))))))))))))) CFLAGS += -DBOARD_$(BOARD_UPPER) +# use max3421 as host controller +ifeq (${MAX3421_HOST},1) + SRC_C += src/portable/analog/max3421/hcd_max3421.c + CFLAGS += -DCFG_TUH_MAX3421=1 +endif + # Log level is mapped to TUSB DEBUG option ifneq ($(LOG),) CMAKE_DEFSYM += -DLOG=$(LOG) diff --git a/examples/rules.mk b/examples/rules.mk index 44d6b84c8..227849a18 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -72,7 +72,7 @@ endif # get depenecies .PHONY: get-deps get-deps: - $(PYTHON) $(TOP)/tools/get_deps.py $(DEPS_SUBMODULES) + $(PYTHON) $(TOP)/tools/get_deps.py ${FAMILY} .PHONY: size size: $(BUILD)/$(PROJECT).elf diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 417630a03..562792625 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -44,17 +44,16 @@ // If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead #if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) + #include "SEGGER_RTT.h" -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ +TU_ATTR_USED int sys_write(int fhdl, const void *buf, size_t count) { (void) fhdl; - SEGGER_RTT_Write(0, (const char*) buf, (int) count); + SEGGER_RTT_Write(0, (const char *) buf, (int) count); return count; } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read(int fhdl, char *buf, size_t count) { (void) fhdl; int rd = (int) SEGGER_RTT_Read(0, buf, count); return (rd > 0) ? rd : -1; @@ -67,8 +66,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #include "board_mcu.h" -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) { (void) fhdl; uint8_t const* buf8 = (uint8_t const*) buf; @@ -79,8 +77,7 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) return (int) count; } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; (void) buf; (void) count; @@ -90,14 +87,12 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #else // Default logging with on-board UART -TU_ATTR_USED int sys_write (int fhdl, const void *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, (int) count); } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; int rd = board_uart_read((uint8_t*) buf, (int) count); return (rd > 0) ? rd : -1; @@ -105,8 +100,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #endif -int board_getchar(void) -{ +int board_getchar(void) { char c; - return ( sys_read(0, &c, 1) > 0 ) ? (int) c : (-1); + return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); } diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 7c89427c0..642282b0e 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -216,6 +216,7 @@ function(family_configure_common TARGET RTOS) if (NOT TARGET segger_rtt) add_library(segger_rtt STATIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c) target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) + target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) endif() target_link_libraries(${TARGET} PUBLIC segger_rtt) endif () @@ -252,6 +253,15 @@ function(family_add_tinyusb TARGET OPT_MCU RTOS) # link tinyusb with freeRTOS kernel target_link_libraries(${TARGET}-tinyusb PUBLIC freertos_kernel) endif () + + # use max3421 as host controller + if (MAX3421_HOST STREQUAL "1") + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUH_MAX3421=1) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/analog/max3421/hcd_max3421.c + ) + endif () + endfunction() @@ -437,5 +447,10 @@ if (NOT FAMILY_MCUS) set(FAMILY_MCUS ${FAMILY}) endif() +# if use max3421 as host controller, expand FAMILY_MCUS to include max3421 +if (MAX3421_HOST STREQUAL "1") + set(FAMILY_MCUS ${FAMILY_MCUS} MAX3421) +endif () + # save it in case of re-inclusion set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "") diff --git a/hw/bsp/nrf/boards/adafruit_clue/board.cmake b/hw/bsp/nrf/boards/adafruit_clue/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/adafruit_clue/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake b/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake new file mode 100644 index 000000000..93647063a --- /dev/null +++ b/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/arduino_nano33_ble.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake new file mode 100644 index 000000000..ce6da8b43 --- /dev/null +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake @@ -0,0 +1,9 @@ +set(MCU_VARIANT nrf52840) +#set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) + +# enable max3421 host driver for this board +set(MAX3421_HOST 1) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index 8e6ce3230..76100a14a 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -45,6 +45,13 @@ #define UART_RX_PIN 24 #define UART_TX_PIN 25 +// SPI for USB host shield +#define MAX3421_SCK_PIN 14 +#define MAX3421_MOSI_PIN 13 +#define MAX3421_MISO_PIN 15 +#define MAX3421_CS_PIN 27 +#define MAX3421_INTR_PIN 26 + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk index b80807963..488f07b82 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk @@ -1,6 +1,9 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA +# enable max3421 host driver for this board +MAX3421_HOST = 1 + # All source paths should be relative to the top level. LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld diff --git a/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake b/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake new file mode 100644 index 000000000..ffa5932c1 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nrf52840_mdk_dongle.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/pca10056/board.cmake b/hw/bsp/nrf/boards/pca10056/board.cmake index b4fe39fc0..693d7beed 100644 --- a/hw/bsp/nrf/boards/pca10056/board.cmake +++ b/hw/bsp/nrf/boards/pca10056/board.cmake @@ -2,7 +2,4 @@ set(MCU_VARIANT nrf52840) set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - NRF52840_XXAA - ) endfunction() diff --git a/hw/bsp/nrf/boards/pca10056/board.h b/hw/bsp/nrf/boards/pca10056/board.h index f4368f830..9459e7911 100644 --- a/hw/bsp/nrf/boards/pca10056/board.h +++ b/hw/bsp/nrf/boards/pca10056/board.h @@ -31,6 +31,8 @@ extern "C" { #endif +#define _PINNUM(port, pin) ((port)*32 + (pin)) + // LED #define LED_PIN 13 #define LED_STATE_ON 0 @@ -43,6 +45,13 @@ #define UART_RX_PIN 8 #define UART_TX_PIN 6 +// SPI for USB host shield +#define MAX3421_SCK_PIN _PINNUM(1, 15) +#define MAX3421_MOSI_PIN _PINNUM(1, 13) +#define MAX3421_MISO_PIN _PINNUM(1, 14) +#define MAX3421_CS_PIN _PINNUM(1, 12) +#define MAX3421_INTR_PIN _PINNUM(1, 11) + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/boards/pca10059/board.cmake b/hw/bsp/nrf/boards/pca10059/board.cmake new file mode 100644 index 000000000..c79eb5964 --- /dev/null +++ b/hw/bsp/nrf/boards/pca10059/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/pca10059.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index 1e72243c9..ca5399a3a 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -2,10 +2,6 @@ set(MCU_VARIANT nrf5340_application) set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - NRF5340_XXAA - NRF5340_XXAA_APPLICATION - ) target_sources(${TARGET} PRIVATE ${NRFX_DIR}/drivers/src/nrfx_usbreg.c ) diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/pca10095/board.h index fd3c63d6a..ad3379bf6 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/pca10095/board.h @@ -31,6 +31,8 @@ extern "C" { #endif +#define _PINNUM(port, pin) ((port)*32 + (pin)) + // LED #define LED_PIN 28 #define LED_STATE_ON 0 @@ -43,6 +45,13 @@ #define UART_RX_PIN 32 #define UART_TX_PIN 33 +// SPI for USB host shield +#define MAX3421_SCK_PIN _PINNUM(1, 15) +#define MAX3421_MOSI_PIN _PINNUM(1, 13) +#define MAX3421_MISO_PIN _PINNUM(1, 14) +#define MAX3421_CS_PIN _PINNUM(1, 12) +#define MAX3421_INTR_PIN _PINNUM(1, 11) + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/boards/pca10100/board.cmake b/hw/bsp/nrf/boards/pca10100/board.cmake new file mode 100644 index 000000000..c30026815 --- /dev/null +++ b/hw/bsp/nrf/boards/pca10100/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52833) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52833_xxaa.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake new file mode 100644 index 000000000..693d7beed --- /dev/null +++ b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 9ca666e36..6fcfd9476 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -34,12 +34,15 @@ #pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wredundant-decls" #endif #include "nrfx.h" #include "hal/nrf_gpio.h" +#include "drivers/include/nrfx_gpiote.h" #include "drivers/include/nrfx_power.h" #include "drivers/include/nrfx_uarte.h" +#include "drivers/include/nrfx_spim.h" #ifdef SOFTDEVICE_PRESENT #include "nrf_sdm.h" @@ -54,8 +57,7 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ +void USBD_IRQHandler(void) { tud_int_handler(0); } @@ -86,15 +88,28 @@ static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); - // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) -TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) -{ +TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } -void board_init(void) -{ +//------------- Host using MAX2341E -------------// +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); + +void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { + if (!(pin == MAX3421_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; + + tuh_int_handler(1); +} +#endif + + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +void board_init(void) { // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -110,22 +125,21 @@ void board_init(void) nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // 1ms tick timer - SysTick_Config(SystemCoreClock/1000); + SysTick_Config(SystemCoreClock / 1000); // UART - nrfx_uarte_config_t uart_cfg = - { - .pseltxd = UART_TX_PIN, - .pselrxd = UART_RX_PIN, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE - .interrupt_priority = 7, - .hal_cfg = { - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED, - } + nrfx_uarte_config_t uart_cfg = { + .pseltxd = UART_TX_PIN, + .pselrxd = UART_RX_PIN, + .pselcts = NRF_UARTE_PSEL_DISCONNECTED, + .pselrts = NRF_UARTE_PSEL_DISCONNECTED, + .p_context = NULL, + .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE + .interrupt_priority = 7, + .hal_cfg = { + .hwfc = NRF_UARTE_HWFC_DISABLED, + .parity = NRF_UARTE_PARITY_EXCLUDED, + } }; nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler); @@ -165,61 +179,105 @@ void board_init(void) // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially - #ifdef NRF5340_XXAA +#ifdef NRF5340_XXAA usb_reg = NRF_USBREGULATOR->USBREGSTATUS; - #else +#else usb_reg = NRF_POWER->USBREGSTATUS; - #endif +#endif } if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED); if ( usb_reg & OUTPUTRDY_Msk ) tusb_hal_nrf_power_event(USB_EVT_READY); #endif + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + // MAX3421 need 3.3v signal (may not be needed) + #if defined(UICR_REGOUT0_VOUT_Msk) && 0 + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) { + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3; + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + NVIC_SystemReset(); + } + #endif + + // manually manage CS + nrf_gpio_cfg_output(MAX3421_CS_PIN); + nrf_gpio_pin_write(MAX3421_CS_PIN, 1); + + // USB host using max3421e usb controller via SPI + nrfx_spim_config_t cfg = { + .sck_pin = MAX3421_SCK_PIN, + .mosi_pin = MAX3421_MOSI_PIN, + .miso_pin = MAX3421_MISO_PIN, + .ss_pin = NRFX_SPIM_PIN_NOT_USED, + .ss_active_high = false, + .irq_priority = 3, + .orc = 0xFF, + // default setting 4 Mhz, Mode 0, MSB first + .frequency = NRF_SPIM_FREQ_4M, + .mode = NRF_SPIM_MODE_0, + .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, + }; + + // no handler --> blocking + nrfx_spim_init(&_spi, &cfg, NULL, NULL); + + // max3421e interrupt pin + nrfx_gpiote_init(1); + nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); + in_config.pull = NRF_GPIO_PIN_PULLUP; + + nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); + nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); +#endif + } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - nrf_gpio_pin_write(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +void board_led_write(bool state) { + nrf_gpio_pin_write(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN); } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; return 0; // return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0; } -int board_uart_write(void const * buf, int len) -{ - return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len)) ? len : 0; +int board_uart_write(void const *buf, int len) { + return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const *) buf, (size_t) len)) ? len : 0; } #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + #endif #ifdef SOFTDEVICE_PRESENT // process SOC event from SD -uint32_t proc_soc(void) -{ +uint32_t proc_soc(void) { uint32_t soc_evt; uint32_t err = sd_evt_get(&soc_evt); @@ -236,25 +294,57 @@ uint32_t proc_soc(void) return err; } -uint32_t proc_ble(void) -{ +uint32_t proc_ble(void) { // do nothing with ble return NRF_ERROR_NOT_FOUND; } -void SD_EVT_IRQHandler(void) -{ +void SD_EVT_IRQHandler(void) { // process BLE and SOC until there is no more events - while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) - { - + while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) { } } -void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) -{ +void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { (void) id; (void) pc; (void) info; } #endif + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + // use NVIC_Enable/Disable instead since nrfx_gpiote_trigger_enable/disable clear pending and can miss interrupt + // when disabled and re-enabled. + if (enabled) { + NVIC_EnableIRQ(GPIOTE_IRQn); + } else { + NVIC_DisableIRQ(GPIOTE_IRQn); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + nrfx_spim_xfer_desc_t xfer = { + .p_tx_buffer = tx_buf, + .tx_length = tx_len, + .p_rx_buffer = rx_buf, + .rx_length = rx_len, + }; + + return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); +} + +#endif diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 2b13249f4..99d9ac6dd 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -32,14 +32,23 @@ function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) add_library(${BOARD_TARGET} STATIC # driver + ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c + ${NRFX_DIR}/drivers/src/nrfx_gpiote.c ${NRFX_DIR}/drivers/src/nrfx_power.c + ${NRFX_DIR}/drivers/src/nrfx_spim.c ${NRFX_DIR}/drivers/src/nrfx_uarte.c # mcu ${NRFX_DIR}/mdk/system_${MCU_VARIANT}.c ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONFIG_GPIO_AS_PINRESET - ) + target_compile_definitions(${BOARD_TARGET} PUBLIC CONFIG_GPIO_AS_PINRESET) + + if (MCU_VARIANT STREQUAL "nrf52840") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52840_XXAA) + elseif (MCU_VARIANT STREQUAL "nrf52833") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52833_XXAA) + elseif (MCU_VARIANT STREQUAL "nrf5340_application") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF5340_XXAA NRF5340_XXAA_APPLICATION) + endif () if (TRACE_ETM STREQUAL "1") # ENABLE_TRACE will cause system_nrf5x.c to set up ETM trace diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index cdcfe39bd..4b53b9a4f 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -1,5 +1,6 @@ UF2_FAMILY_ID = 0xADA52840 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/nordic/nrfx + +NRFX_DIR = hw/mcu/nordic/nrfx include $(TOP)/$(BOARD_PATH)/board.mk @@ -14,24 +15,27 @@ CFLAGS += \ # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual -Wno-error=redundant-decls -LDFLAGS += -L$(TOP)/hw/mcu/nordic/nrfx/mdk +LDFLAGS += -L$(TOP)/${NRFX_DIR}/mdk SRC_C += \ src/portable/nordic/nrf5x/dcd_nrf5x.c \ - hw/mcu/nordic/nrfx/drivers/src/nrfx_power.c \ - hw/mcu/nordic/nrfx/drivers/src/nrfx_uarte.c \ - hw/mcu/nordic/nrfx/mdk/system_$(MCU_VARIANT).c + ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c \ + ${NRFX_DIR}/drivers/src/nrfx_gpiote.c \ + ${NRFX_DIR}/drivers/src/nrfx_power.c \ + ${NRFX_DIR}/drivers/src/nrfx_spim.c \ + ${NRFX_DIR}/drivers/src/nrfx_uarte.c \ + ${NRFX_DIR}/mdk/system_$(MCU_VARIANT).c INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - $(TOP)/hw/mcu/nordic/nrfx \ - $(TOP)/hw/mcu/nordic/nrfx/mdk \ - $(TOP)/hw/mcu/nordic/nrfx/hal \ - $(TOP)/hw/mcu/nordic/nrfx/drivers/include \ - $(TOP)/hw/mcu/nordic/nrfx/drivers/src \ + $(TOP)/${NRFX_DIR} \ + $(TOP)/${NRFX_DIR}/mdk \ + $(TOP)/${NRFX_DIR}/hal \ + $(TOP)/${NRFX_DIR}/drivers/include \ + $(TOP)/${NRFX_DIR}/drivers/src \ -SRC_S += hw/mcu/nordic/nrfx/mdk/gcc_startup_$(MCU_VARIANT).S +SRC_S += ${NRFX_DIR}/mdk/gcc_startup_$(MCU_VARIANT).S ASFLAGS += -D__HEAP_SIZE=0 diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h index 696a3fb04..95ef33ce4 100644 --- a/hw/bsp/nrf/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config.h @@ -5,13 +5,13 @@ #define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_CLOCK_ENABLED 0 +#define NRFX_GPIOTE_ENABLED 1 #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 -#define NRFX_UARTE1_ENABLED 0 -#define NRFX_UARTE2_ENABLED 0 -#define NRFX_UARTE3_ENABLED 0 +#define NRFX_SPIM_ENABLED 1 +#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi #define NRFX_PRS_ENABLED 0 #define NRFX_USBREG_ENABLED 1 @@ -42,5 +42,4 @@ #error "Unknown device." #endif - #endif // NRFX_CONFIG_H__ diff --git a/hw/bsp/nrf/nrfx_glue.h b/hw/bsp/nrf/nrfx_glue.h index cdf49b4ab..ef756c670 100644 --- a/hw/bsp/nrf/nrfx_glue.h +++ b/hw/bsp/nrf/nrfx_glue.h @@ -220,6 +220,75 @@ static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number) /** @} */ +//------------------------------------------------------------------------------ + +#include <soc/nrfx_atomic.h> + +/** + * @brief Atomic 32 bit unsigned type. + */ +#define nrfx_atomic_t nrfx_atomic_u32_t + +/** + * @brief Stores value to an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value to store. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_STORE(p_data, value) nrfx_atomic_u32_fetch_store(p_data, value) + +/** + * @brief Performs logical OR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of OR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_OR(p_data, value) nrfx_atomic_u32_fetch_or(p_data, value) + +/** + * @brief Performs logical AND operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of AND operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_AND(p_data, value) nrfx_atomic_u32_fetch_and(p_data, value) + +/** + * @brief Performs logical XOR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of XOR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_XOR(p_data, value) nrfx_atomic_u32_fetch_xor(p_data, value) + +/** + * @brief Performs logical ADD operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of ADD operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_ADD(p_data, value) nrfx_atomic_u32_fetch_add(p_data, value) + +/** + * @brief Performs logical SUB operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of SUB operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_SUB(p_data, value) nrfx_atomic_u32_fetch_sub(p_data, value) + #ifdef __cplusplus } #endif diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.h b/hw/bsp/samd21/boards/metro_m0_express/board.h index d26aae53c..6dd53e901 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.h +++ b/hw/bsp/samd21/boards/metro_m0_express/board.h @@ -43,6 +43,22 @@ #define UART_RX_PIN 4 #define UART_TX_PIN 5 +// SPI for USB host shield +#define MAX3421_SERCOM_ID 4 // SERCOM4 +#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) + +#define MAX3421_SCK_PIN (32+11) +#define MAX3421_MOSI_PIN (32+10) +#define MAX3421_MISO_PIN 12 +#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 +#define MAX3421_RX_PAD 0 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 7 // D9 +#define MAX3421_INTR_EIC_ID 7 // EIC7 + + #ifdef __cplusplus } #endif diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index 2121e028a..cfe66b8dc 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -47,30 +47,34 @@ #endif //--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +/* Referenced GCLKs, should be initialized firstly */ +#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) + +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) + +//--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USB_Handler(void) -{ +void USB_Handler(void) { tud_int_handler(0); } //--------------------------------------------------------------------+ -// UART support +// Implementation //--------------------------------------------------------------------+ static void uart_init(void); -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -/* Referenced GCLKs, should be initialized firstly */ -#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) -/* Not referenced GCLKs, initialized last */ -#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) +static void max3421_init(void); +#endif -void board_init(void) -{ +void board_init(void) { // Clock init ( follow hpl_init.c ) hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); @@ -85,7 +89,7 @@ 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 +#if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(CONF_CPU_FREQUENCY / 1000); #endif @@ -103,7 +107,7 @@ void board_init(void) uart_init(); -#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); #endif @@ -134,22 +138,24 @@ void board_init(void) gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + max3421_init(); +#endif } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - (void)state; +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)); + gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); #endif } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { #ifdef BUTTON_PIN return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); #else @@ -227,33 +233,185 @@ int board_uart_write(void const * buf, int len) } #else // ! defined(UART_SERCOM) -static void uart_init(void) -{ +static void uart_init(void) { } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +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; +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; return 0; } + #endif -#if CFG_TUSB_OS == OPT_OS_NONE +#if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +static void max3421_init(void) { + //------------- SPI Init -------------// + uint32_t const baudrate = 4000000u; + + // Enable the APB clock for SERCOM + PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); + + // Configure GCLK for SERCOM +// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val+MAX3421_SERCOM_ID) | + GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); + + Sercom* sercom = MAX3421_SERCOM; + + // Disable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + sercom->SPI.CTRLA.bit.SWRST = 1; + while (sercom->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | + SERCOM_SPI_CTRLA_MODE(3); + + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); + + // Set the baud rate + sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); + + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) + gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); + + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + + // Enable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 1; + while (sercom->SPI.SYNCBUSY.bit.ENABLE); + + //------------- External Interrupt -------------// + + // Enable the APB clock for EIC (External Interrupt Controller) + PM->APBAMASK.reg |= PM_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); + + // Configure PA20 as an input with function A (external interrupt) + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + gpio_set_pin_function(MAX3421_INTR_PIN, 0); + + // Disable EIC + EIC->CTRL.bit.ENABLE = 0; + while (EIC->STATUS.bit.SYNCBUSY); + + // Configure EIC to trigger on falling edge + uint8_t const sense_shift = MAX3421_INTR_EIC_ID * 4; + EIC->CONFIG[0].reg &= ~(7 << sense_shift); + EIC->CONFIG[0].reg |= 2 << sense_shift; + + // Enable External Interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Enable EIC + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY); +} + +void EIC_Handler(void) { + // Clear the interrupt flag + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Call the TinyUSB interrupt handler + tuh_int_handler(1); +} + +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + if (enabled) { + NVIC_EnableIRQ(EIC_IRQn); + } else { + NVIC_DisableIRQ(EIC_IRQn); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + Sercom* sercom = MAX3421_SERCOM; + + size_t count = 0; + while (count < tx_len || count < rx_len) { + // Wait for the transmit buffer to be empty + while (!sercom->SPI.INTFLAG.bit.DRE); + + // Write data to be transmitted + uint8_t data = 0x00; + if (count < tx_len) { + data = tx_buf[count]; + } + + sercom->SPI.DATA.reg = (uint32_t) data; + + // Wait for the receive buffer to be filled + while (!sercom->SPI.INTFLAG.bit.RXC); + + // Read received data + data = (uint8_t) sercom->SPI.DATA.reg; + if (count < rx_len) { + rx_buf[count] = data; + } + + count++; + } + + // wait for bus idle and clear flags + while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + + return true; +} + +#endif + + #endif diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index 49a1a781a..79c63812d 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -1,5 +1,5 @@ UF2_FAMILY_ID = 0x68ed2b88 -DEPS_SUBMODULES += hw/mcu/microchip +SDK_DIR = hw/mcu/microchip/samd21 include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m0plus @@ -18,24 +18,24 @@ CFLAGS_SKIP += -Wcast-qual SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ - hw/mcu/microchip/samd21/gcc/gcc/startup_samd21.c \ - hw/mcu/microchip/samd21/gcc/system_samd21.c \ - hw/mcu/microchip/samd21/hpl/gclk/hpl_gclk.c \ - hw/mcu/microchip/samd21/hpl/pm/hpl_pm.c \ - hw/mcu/microchip/samd21/hpl/sysctrl/hpl_sysctrl.c \ - hw/mcu/microchip/samd21/hal/src/hal_atomic.c + ${SDK_DIR}/gcc/gcc/startup_samd21.c \ + ${SDK_DIR}/gcc/system_samd21.c \ + ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ + ${SDK_DIR}/hal/src/hal_atomic.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/hw/mcu/microchip/samd21/ \ - $(TOP)/hw/mcu/microchip/samd21/config \ - $(TOP)/hw/mcu/microchip/samd21/include \ - $(TOP)/hw/mcu/microchip/samd21/hal/include \ - $(TOP)/hw/mcu/microchip/samd21/hal/utils/include \ - $(TOP)/hw/mcu/microchip/samd21/hpl/pm/ \ - $(TOP)/hw/mcu/microchip/samd21/hpl/port \ - $(TOP)/hw/mcu/microchip/samd21/hri \ - $(TOP)/hw/mcu/microchip/samd21/CMSIS/Include + $(TOP)/${SDK_DIR}/ \ + $(TOP)/${SDK_DIR}/config \ + $(TOP)/${SDK_DIR}/include \ + $(TOP)/${SDK_DIR}/hal/include \ + $(TOP)/${SDK_DIR}/hal/utils/include \ + $(TOP)/${SDK_DIR}/hpl/pm/ \ + $(TOP)/${SDK_DIR}/hpl/port \ + $(TOP)/${SDK_DIR}/hri \ + $(TOP)/${SDK_DIR}/CMSIS/Include # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index 5d7734576..b3b80db89 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -43,6 +43,22 @@ #define UART_TX_PIN 23 #define UART_RX_PIN 22 +// SPI for USB host shield +#define MAX3421_SERCOM_ID 2 // SERCOM2 +#define MAX3421_SERCOM_FUNCTION 2 // function C + +#define MAX3421_SCK_PIN 13 +#define MAX3421_MOSI_PIN 12 +#define MAX3421_MISO_PIN 14 +#define MAX3421_TX_PAD 0 // MOSI = PAD_0, SCK = PAD_1 +#define MAX3421_RX_PAD 2 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 20 // D9 +#define MAX3421_INTR_EIC_ID 4 // EIC4 + + #ifdef __cplusplus } #endif diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 2df9cbafb..2cf00c7af 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -43,42 +43,47 @@ #pragma GCC diagnostic pop #endif +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +/* Referenced GCLKs, should be initialized firstly */ +#define _GCLK_INIT_1ST 0xFFFFFFFF + +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USB_0_Handler (void) -{ +void USB_0_Handler(void) { tud_int_handler(0); } -void USB_1_Handler (void) -{ +void USB_1_Handler(void) { tud_int_handler(0); } -void USB_2_Handler (void) -{ +void USB_2_Handler(void) { tud_int_handler(0); } -void USB_3_Handler (void) -{ +void USB_3_Handler(void) { tud_int_handler(0); } //--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION +// Implementation //--------------------------------------------------------------------+ -/* Referenced GCLKs, should be initialized firstly */ -#define _GCLK_INIT_1ST 0xFFFFFFFF +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) +#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler) -/* Not referenced GCLKs, initialized last */ -#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) +static void max3421_init(void); +#endif -void board_init(void) -{ +void board_init(void) { // Clock init ( follow hpl_init.c ) hri_nvmctrl_set_CTRLA_RWS_bf(NVMCTRL, 0); @@ -104,7 +109,7 @@ void board_init(void) gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); -#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); @@ -129,45 +134,224 @@ void board_init(void) gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + max3421_init(); +#endif } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ +void board_led_write(bool state) { gpio_set_pin_level(LED_PIN, state); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { // button is active low return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +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; +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; return 0; } -#if CFG_TUSB_OS == OPT_OS_NONE +#if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +static void max3421_init(void) { + //------------- SPI Init -------------// + uint32_t const baudrate = 4000000u; + + struct { + volatile uint32_t *mck_apb; + uint32_t mask; + uint8_t gclk_id_core; + uint8_t gclk_id_slow; + } const sercom_clock[] = { + { &MCLK->APBAMASK.reg, MCLK_APBAMASK_SERCOM0, SERCOM0_GCLK_ID_CORE, SERCOM0_GCLK_ID_SLOW }, + { &MCLK->APBAMASK.reg, MCLK_APBAMASK_SERCOM1, SERCOM1_GCLK_ID_CORE, SERCOM1_GCLK_ID_SLOW }, + { &MCLK->APBBMASK.reg, MCLK_APBBMASK_SERCOM2, SERCOM2_GCLK_ID_CORE, SERCOM2_GCLK_ID_SLOW }, + { &MCLK->APBBMASK.reg, MCLK_APBBMASK_SERCOM3, SERCOM3_GCLK_ID_CORE, SERCOM3_GCLK_ID_SLOW }, + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM4, SERCOM4_GCLK_ID_CORE, SERCOM4_GCLK_ID_SLOW }, + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM5, SERCOM5_GCLK_ID_CORE, SERCOM5_GCLK_ID_SLOW }, + #ifdef SERCOM6_GCLK_ID_CORE + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM6, SERCOM6_GCLK_ID_CORE, SERCOM6_GCLK_ID_SLOW }, + #endif + #ifdef SERCOM7_GCLK_ID_CORE + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM7, SERCOM7_GCLK_ID_CORE, SERCOM7_GCLK_ID_SLOW }, + #endif + }; + + Sercom* sercom = MAX3421_SERCOM; + + // Enable the APB clock for SERCOM + *sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask; + + // Configure GCLK for SERCOM + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Disable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + sercom->SPI.CTRLA.bit.SWRST = 1; + while (sercom->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | + SERCOM_SPI_CTRLA_MODE(3); + + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); + + // Set the baud rate + sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); + + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) + gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); + + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + + // Enable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 1; + while (sercom->SPI.SYNCBUSY.bit.ENABLE); + + //------------- External Interrupt -------------// + + // Enable the APB clock for EIC (External Interrupt Controller) + MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Configure PA20 as an input with function A (external interrupt) + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + gpio_set_pin_function(MAX3421_INTR_PIN, 0); + + // Disable EIC + EIC->CTRLA.bit.ENABLE = 0; + while (EIC->SYNCBUSY.bit.ENABLE); + + // Configure EIC to trigger on falling edge + volatile uint32_t * eic_config; + uint8_t sense_shift; + if ( MAX3421_INTR_EIC_ID < 8 ) { + eic_config = &EIC->CONFIG[0].reg; + sense_shift = MAX3421_INTR_EIC_ID * 4; + } else { + eic_config = &EIC->CONFIG[1].reg; + sense_shift = (MAX3421_INTR_EIC_ID - 8) * 4; + } + + *eic_config &= ~(7 << sense_shift); + *eic_config |= 2 << sense_shift; + + // Enable External Interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Enable EIC + EIC->CTRLA.bit.ENABLE = 1; + while (EIC->SYNCBUSY.bit.ENABLE); +} + +void MAX3421_EIC_Handler(void) { + // Clear the interrupt flag + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Call the TinyUSB interrupt handler + tuh_int_handler(1); +} + +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + const IRQn_Type irq = EIC_0_IRQn + MAX3421_INTR_EIC_ID; + if (enabled) { + NVIC_EnableIRQ(irq); + } else { + NVIC_DisableIRQ(irq); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + Sercom* sercom = MAX3421_SERCOM; + + size_t count = 0; + while (count < tx_len || count < rx_len) { + // Wait for the transmit buffer to be empty + while (!sercom->SPI.INTFLAG.bit.DRE); + + // Write data to be transmitted + uint8_t data = 0x00; + if (count < tx_len) { + data = tx_buf[count]; + } + + sercom->SPI.DATA.reg = (uint32_t) data; + + // Wait for the receive buffer to be filled + while (!sercom->SPI.INTFLAG.bit.RXC); + + // Read received data + data = (uint8_t) sercom->SPI.DATA.reg; + if (count < rx_len) { + rx_buf[count] = data; + } + + count++; + } + + // wait for bus idle and clear flags + while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + + return true; +} + +#endif + #endif diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c303c6eaf..6fffed11c 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -122,13 +122,11 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) { return (uint16_t) ((((uint16_t) high) << 8) | low); } diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 36507041f..99176c02a 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -58,16 +58,14 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #define tu_printf printf #endif -static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) -{ +static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]); } // Log with Level #define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__) #define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__) -#define TU_LOG_ARR(n, ...) TU_XSTRCAT3(TU_LOG, n, _ARR)(__VA_ARGS__) -#define TU_LOG_PTR(n, ...) TU_XSTRCAT3(TU_LOG, n, _PTR)(__VA_ARGS__) +#define TU_LOG_BUF(n, ...) TU_XSTRCAT3(TU_LOG, n, _BUF)(__VA_ARGS__) #define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__) #define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__) #define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) @@ -76,8 +74,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) // Log Level 1: Error #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem -#define TU_LOG1_ARR(_x, _n) tu_print_arr((uint8_t const*)(_x), _n) -#define TU_LOG1_PTR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x))) +#define TU_LOG1_BUF(_x, _n) tu_print_buf((uint8_t const*)(_x), _n) #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) ) @@ -85,8 +82,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #if CFG_TUSB_DEBUG >= 2 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_ARR TU_LOG1_ARR - #define TU_LOG2_PTR TU_LOG1_PTR + #define TU_LOG2_BUF TU_LOG1_BUF #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX #endif @@ -95,30 +91,25 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #if CFG_TUSB_DEBUG >= 3 #define TU_LOG3 TU_LOG1 #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_ARR TU_LOG1_ARR - #define TU_LOG3_PTR TU_LOG1_PTR + #define TU_LOG3_BUF TU_LOG1_BUF #define TU_LOG3_INT TU_LOG1_INT #define TU_LOG3_HEX TU_LOG1_HEX #endif -typedef struct -{ +typedef struct { uint32_t key; const char* data; } tu_lookup_entry_t; -typedef struct -{ +typedef struct { uint16_t count; tu_lookup_entry_t const* items; } tu_lookup_table_t; -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { tu_static char not_found[11]; - for(uint16_t i=0; i<p_table->count; i++) - { + for(uint16_t i=0; i<p_table->count; i++) { if (p_table->items[i].key == key) return p_table->items[i].data; } @@ -133,7 +124,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG #define TU_LOG(n, ...) #define TU_LOG_MEM(n, ...) - #define TU_LOG_PTR(n, ...) + #define TU_LOG_BUF(n, ...) #define TU_LOG_INT(n, ...) #define TU_LOG_HEX(n, ...) #define TU_LOG_LOCATION() @@ -144,14 +135,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG0(...) #define TU_LOG0_MEM(...) -#define TU_LOG0_PTR(...) +#define TU_LOG0_BUF(...) #define TU_LOG0_INT(...) #define TU_LOG0_HEX(...) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) - #define TU_LOG1_PTR(...) + #define TU_LOG1_BUF(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) #endif @@ -159,7 +150,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) - #define TU_LOG2_PTR(...) + #define TU_LOG2_BUF(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) #endif @@ -167,7 +158,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG3 #define TU_LOG3(...) #define TU_LOG3_MEM(...) - #define TU_LOG3_PTR(...) + #define TU_LOG3_BUF(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) #endif diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 35f94efbc..8807ff8aa 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -385,6 +385,18 @@ #define TUP_RHPORT_HIGHSPEED 1 #endif + +//--------------------------------------------------------------------+ +// External USB controller +//--------------------------------------------------------------------+ + +#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #endif +#endif + + //--------------------------------------------------------------------+ // Default Values //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index f0d9fba52..50941c46f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -506,7 +506,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG_PTR(CFG_TUD_LOG_LEVEL, &event.setup_received); + TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); TU_LOG_USBD("\r\n"); // Mark as connected after receiving 1st setup packet. diff --git a/src/device/usbd.h b/src/device/usbd.h index b11c1a09d..782f538fd 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -50,8 +50,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop TU_ATTR_ALWAYS_INLINE static inline -void tud_task (void) -{ +void tud_task (void) { tud_task_ext(UINT32_MAX, false); } @@ -80,8 +79,7 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 16585167f..153be7cee 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -23,8 +23,8 @@ * * This file is part of the TinyUSB stack. */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ +#ifndef _TUSB_USBD_PVT_H_ +#define _TUSB_USBD_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -44,8 +44,7 @@ // Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* name; #endif @@ -111,8 +110,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // 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) -{ +bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); } @@ -124,11 +122,10 @@ void usbd_sof_enable(uint8_t rhport, bool en); *------------------------------------------------------------------*/ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - +void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); #ifdef __cplusplus } #endif -#endif /* USBD_PVT_H_ */ +#endif diff --git a/src/host/hcd.h b/src/host/hcd.h index 9bcc1c6df..e25b20ea3 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -39,7 +39,7 @@ // Configuration //--------------------------------------------------------------------+ -// Max number of endpoints per device +// Max number of endpoints pair per device // TODO optimize memory usage #ifndef CFG_TUH_ENDPOINT_MAX #define CFG_TUH_ENDPOINT_MAX 16 @@ -167,17 +167,17 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Open an endpoint -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc); // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); +bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); // Abort a queued transfer. Note: it can only abort transfer that has not been started // Return true if a queued transfer is aborted, false if there is no transfer to abort bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); +bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]); // clear stall, data toggle is also reset to DATA0 bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); @@ -198,8 +198,7 @@ extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); // Helper to send device attach event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_device_attach(uint8_t rhport, bool in_isr) -{ +void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event; event.rhport = rhport; event.event_id = HCD_EVENT_DEVICE_ATTACH; @@ -211,8 +210,7 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr) // Helper to send device removal event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_device_remove(uint8_t rhport, bool in_isr) -{ +void hcd_event_device_remove(uint8_t rhport, bool in_isr) { hcd_event_t event; event.rhport = rhport; event.event_id = HCD_EVENT_DEVICE_REMOVE; @@ -224,10 +222,8 @@ void hcd_event_device_remove(uint8_t rhport, bool in_isr) // Helper to send USB transfer event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) -{ - hcd_event_t event = - { +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { + hcd_event_t event = { .rhport = 0, // TODO correct rhport .event_id = HCD_EVENT_XFER_COMPLETE, .dev_addr = dev_addr, diff --git a/src/host/usbh.c b/src/host/usbh.c index 5423df669..e332f35cc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -552,8 +552,7 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) } // TODO timeout_ms is not supported yet -bool tuh_control_xfer (tuh_xfer_t* xfer) -{ +bool tuh_control_xfer (tuh_xfer_t* xfer) { // EP0 with setup packet TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); @@ -565,8 +564,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); - if (is_idle) - { + if (is_idle) { _ctrl_xfer.stage = CONTROL_STAGE_SETUP; _ctrl_xfer.daddr = daddr; _ctrl_xfer.actual_len = 0; @@ -585,14 +583,12 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? tu_str_std_request[xfer->setup->bRequest] : "Class Request"); - TU_LOG_PTR(CFG_TUH_LOG_LEVEL, xfer->setup); + TU_LOG_BUF(CFG_TUH_LOG_LEVEL, xfer->setup, 8); TU_LOG_USBH("\r\n"); - if (xfer->complete_cb) - { + if (xfer->complete_cb) { TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.request) ); - }else - { + }else { // blocking if complete callback is not provided // change callback to internal blocking, and result as user argument volatile xfer_result_t result = XFER_RESULT_INVALID; @@ -656,30 +652,23 @@ static void _xfer_complete(uint8_t daddr, xfer_result_t result) } } -static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) ep_addr; const uint8_t rhport = usbh_get_rhport(dev_addr); tusb_control_request_t const * request = &_ctrl_xfer.request; - if (XFER_RESULT_SUCCESS != result) - { + if (XFER_RESULT_SUCCESS != result) { TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); - #if CFG_TUSB_DEBUG == 1 - TU_LOG1_PTR(request); + TU_LOG1_BUF(request, 8); TU_LOG1("\r\n"); - #endif // terminate transfer if any stage failed _xfer_complete(dev_addr, result); - }else - { - switch(_ctrl_xfer.stage) - { + }else { + switch(_ctrl_xfer.stage) { case CONTROL_STAGE_SETUP: - if (request->wLength) - { + if (request->wLength) { // DATA stage: initial data toggle is always 1 _set_control_xfer_stage(CONTROL_STAGE_DATA); TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) ); @@ -688,8 +677,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result TU_ATTR_FALLTHROUGH; case CONTROL_STAGE_DATA: - if (request->wLength) - { + if (request->wLength) { TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr); TU_LOG_MEM(CFG_TUH_LOG_LEVEL, _ctrl_xfer.buffer, xferred_bytes, 2); } @@ -765,29 +753,33 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { // USBH API For Class Driver //--------------------------------------------------------------------+ -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - usbh_device_t* dev = get_device(dev_addr); +uint8_t usbh_get_rhport(uint8_t dev_addr) { + usbh_device_t *dev = get_device(dev_addr); return dev ? dev->rhport : _dev0.rhport; } -uint8_t* usbh_get_enum_buf(void) -{ +uint8_t *usbh_get_enum_buf(void) { return _usbh_ctrl_buf; } -void usbh_int_set(bool enabled) -{ +void usbh_int_set(bool enabled) { // TODO all host controller if multiple are used since they shared the same event queue - if (enabled) - { + if (enabled) { hcd_int_enable(_usbh_controller); - }else - { + } else { hcd_int_disable(_usbh_controller); } } +void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) { + hcd_event_t event = { 0 }; + event.event_id = USBH_EVENT_FUNC_CALL; + event.func_call.func = func; + event.func_call.param = param; + + osal_queue_send(_usbh_q, &event, in_isr); +} + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -862,7 +854,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b ep_state->busy = 0; ep_state->claimed = 0; TU_LOG1("Failed\r\n"); - TU_BREAKPOINT(); +// TU_BREAKPOINT(); return false; } } @@ -929,6 +921,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) switch (event->event_id) { // case HCD_EVENT_DEVICE_REMOVE: +// // FIXME device remove from a hub need an HCD API for hcd to free up endpoint // // mark device as removing to prevent further xfer before the event is processed in usbh task // break; @@ -1538,9 +1531,7 @@ static bool enum_new_device(hcd_event_t* event) xfer.result = XFER_RESULT_SUCCESS; xfer.user_data = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(&xfer); - } #if CFG_TUH_HUB else diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 0b58a91bc..2b61a77db 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_CLASSDRIVER_H_ -#define _TUSB_USBH_CLASSDRIVER_H_ +#ifndef _TUSB_USBH_PVT_H_ +#define _TUSB_USBH_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -76,6 +76,8 @@ uint8_t* usbh_get_enum_buf(void); void usbh_int_set(bool enabled); +void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ @@ -85,12 +87,10 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b tuh_xfer_cb_t complete_cb, uintptr_t user_data); TU_ATTR_ALWAYS_INLINE -static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ +static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0); } - // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c new file mode 100644 index 000000000..238b518a0 --- /dev/null +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -0,0 +1,922 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 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 CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +#include <stdatomic.h> +#include "host/hcd.h" + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// Command format is +// Reg [7:3] | 0 [2] | Dir [1] | Ack [0] + +enum { + CMDBYTE_WRITE = 0x02, +}; + +enum { + RCVVFIFO_ADDR = 1u << 3, // 0x08 + SNDFIFO_ADDR = 2u << 3, // 0x10 + SUDFIFO_ADDR = 4u << 3, // 0x20 + RCVBC_ADDR = 6u << 3, // 0x30 + SNDBC_ADDR = 7u << 3, // 0x38 + USBIRQ_ADDR = 13u << 3, // 0x68 + USBIEN_ADDR = 14u << 3, // 0x70 + USBCTL_ADDR = 15u << 3, // 0x78 + CPUCTL_ADDR = 16u << 3, // 0x80 + PINCTL_ADDR = 17u << 3, // 0x88 + REVISION_ADDR = 18u << 3, // 0x90 + HIRQ_ADDR = 25u << 3, // 0xC8 + HIEN_ADDR = 26u << 3, // 0xD0 + MODE_ADDR = 27u << 3, // 0xD8 + PERADDR_ADDR = 28u << 3, // 0xE0 + HCTL_ADDR = 29u << 3, // 0xE8 + HXFR_ADDR = 30u << 3, // 0xF0 + HRSL_ADDR = 31u << 3, // 0xF8 +}; + +enum { + USBIRQ_OSCOK_IRQ = 1u << 0, + USBIRQ_NOVBUS_IRQ = 1u << 5, + USBIRQ_VBUS_IRQ = 1u << 6, +}; + +enum { + USBCTL_PWRDOWN = 1u << 4, + USBCTL_CHIPRES = 1u << 5, +}; + +enum { + CPUCTL_IE = 1u << 0, + CPUCTL_PULSEWID0 = 1u << 6, + CPUCTL_PULSEWID1 = 1u << 7, +}; + +enum { + PINCTL_GPXA = 1u << 0, + PINCTL_GPXB = 1u << 1, + PINCTL_POSINT = 1u << 2, + PINCTL_INTLEVEL = 1u << 3, + PINCTL_FDUPSPI = 1u << 4, +}; + +enum { + HIRQ_BUSEVENT_IRQ = 1u << 0, + HIRQ_RWU_IRQ = 1u << 1, + HIRQ_RCVDAV_IRQ = 1u << 2, + HIRQ_SNDBAV_IRQ = 1u << 3, + HIRQ_SUSDN_IRQ = 1u << 4, + HIRQ_CONDET_IRQ = 1u << 5, + HIRQ_FRAME_IRQ = 1u << 6, + HIRQ_HXFRDN_IRQ = 1u << 7, +}; + +enum { + MODE_HOST = 1u << 0, + MODE_LOWSPEED = 1u << 1, + MODE_HUBPRE = 1u << 2, + MODE_SOFKAENAB = 1u << 3, + MODE_SEPIRQ = 1u << 4, + MODE_DELAYISO = 1u << 5, + MODE_DMPULLDN = 1u << 6, + MODE_DPPULLDN = 1u << 7, +}; + +enum { + HCTL_BUSRST = 1u << 0, + HCTL_FRMRST = 1u << 1, + HCTL_SAMPLEBUS = 1u << 2, + HCTL_SIGRSM = 1u << 3, + HCTL_RCVTOG0 = 1u << 4, + HCTL_RCVTOG1 = 1u << 5, + HCTL_SNDTOG0 = 1u << 6, + HCTL_SNDTOG1 = 1u << 7, +}; + +enum { + HXFR_EPNUM_MASK = 0x0f, + HXFR_SETUP = 1u << 4, + HXFR_OUT_NIN = 1u << 5, + HXFR_ISO = 1u << 6, + HXFR_HS = 1u << 7, +}; + +enum { + HRSL_RESULT_MASK = 0x0f, + HRSL_RCVTOGRD = 1u << 4, + HRSL_SNDTOGRD = 1u << 5, + HRSL_KSTATUS = 1u << 6, + HRSL_JSTATUS = 1u << 7, +}; + +enum { + HRSL_SUCCESS = 0, + HRSL_BUSY, + HRSL_BAD_REQ, + HRSL_UNDEF, + HRSL_NAK, + HRSL_STALL, + HRSL_TOG_ERR, + HRSL_WRONG_PID, + HRSL_BAD_BYTECOUNT, + HRSL_PID_ERR, + HRSL_PKT_ERR, + HRSL_CRC_ERR, + HRSL_K_ERR, + HRSL_J_ERR, + HRSL_TIMEOUT, + HRSL_BABBLE, +}; + +enum { + DEFAULT_HIEN = HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ | HIRQ_RCVDAV_IRQ +}; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +typedef struct { + struct TU_ATTR_PACKED { + uint8_t ep_dir : 1; + uint8_t is_iso : 1; + uint8_t is_setup : 1; + uint8_t data_toggle : 1; + uint8_t xfer_pending : 1; + uint8_t xfer_complete : 1; + }; + struct TU_ATTR_PACKED { + uint8_t daddr : 4; + uint8_t ep_num : 4; + }; + + uint16_t packet_size; + uint16_t total_len; + uint16_t xferred_len; + uint8_t* buf; +} max3421_ep_t; + +typedef struct { + // cached register + uint8_t sndbc; + uint8_t hirq; + uint8_t hien; + uint8_t mode; + uint8_t peraddr; + uint8_t hxfr; + + atomic_flag busy; // busy transferring + volatile uint16_t frame_count; + + max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; // [0] is reserved for addr0 + + OSAL_MUTEX_DEF(spi_mutexdef); +#if OSAL_MUTEX_REQUIRED + osal_mutex_t spi_mutex; +#endif +} max3421_data_t; + +static max3421_data_t _hcd_data; + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); +void tuh_max3421_int_api(uint8_t rhport, bool enabled); + +static void handle_connect_irq(uint8_t rhport, bool in_isr); +static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); + +//--------------------------------------------------------------------+ +// SPI Helper +//--------------------------------------------------------------------+ + +static void max3421_spi_lock(uint8_t rhport, bool in_isr) { + // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr + if (!in_isr) { + (void) osal_mutex_lock(_hcd_data.spi_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + tuh_max3421_int_api(rhport, false); + } + + // assert CS + tuh_max3421_spi_cs_api(rhport, true); +} + +static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { + // de-assert CS + tuh_max3421_spi_cs_api(rhport, false); + + // mutex unlock and re-enable interrupt + if (!in_isr) { + tuh_max3421_int_api(rhport, true); + (void) osal_mutex_unlock(_hcd_data.spi_mutex); + } +} + +static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) { + uint8_t hirq; + reg |= CMDBYTE_WRITE; + + max3421_spi_lock(rhport, in_isr); + + tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); + _hcd_data.hirq = hirq; + tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0); + + max3421_spi_unlock(rhport, in_isr); + +} + +static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) { + uint8_t hirq; + uint8_t const reg = RCVVFIFO_ADDR; + + max3421_spi_lock(rhport, in_isr); + + tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 0); + _hcd_data.hirq = hirq; + tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); + + max3421_spi_unlock(rhport, in_isr); +} + +static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) { + uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; + uint8_t rx_buf[2] = {0, 0}; + + max3421_spi_lock(rhport, in_isr); + + tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + + max3421_spi_unlock(rhport, in_isr); + + // HIRQ register since we are in full-duplex mode + _hcd_data.hirq = rx_buf[0]; +} + +static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) { + uint8_t tx_buf[2] = {reg, 0}; + uint8_t rx_buf[2] = {0, 0}; + + max3421_spi_lock(rhport, in_isr); + + bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + + max3421_spi_unlock(rhport, in_isr); + + _hcd_data.hirq = rx_buf[0]; + return ret ? rx_buf[1] : 0; +} + +static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) { + reg_write(rhport, HIRQ_ADDR, data, in_isr); + // HIRQ write 1 is clear + _hcd_data.hirq &= ~data; +} + +static inline void hien_write(uint8_t rhport, uint8_t data, bool in_isr) { + _hcd_data.hien = data; + reg_write(rhport, HIEN_ADDR, data, in_isr); +} + +static inline void mode_write(uint8_t rhport, uint8_t data, bool in_isr) { + _hcd_data.mode = data; + reg_write(rhport, MODE_ADDR, data, in_isr); +} + +static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) { + if ( _hcd_data.peraddr == data ) return; // no need to change address + + _hcd_data.peraddr = data; + reg_write(rhport, PERADDR_ADDR, data, in_isr); +} + +static inline void hxfr_write(uint8_t rhport, uint8_t data, bool in_isr) { + _hcd_data.hxfr = data; + reg_write(rhport, HXFR_ADDR, data, in_isr); +} + +static inline void sndbc_write(uint8_t rhport, uint8_t data, bool in_isr) { + _hcd_data.sndbc = data; + reg_write(rhport, SNDBC_ADDR, data, in_isr); +} + +//--------------------------------------------------------------------+ +// Endpoint helper +//--------------------------------------------------------------------+ + +static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { + for(size_t i=1; i<CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + // for control endpoint, skip direction check + if (daddr == ep->daddr && ep_num == ep->ep_num && (ep_dir == ep->ep_dir || ep_num == 0)) { + return ep; + } + } + + return NULL; +} + +// daddr = 0 and ep_num = 0 means find a free (allocate) endpoint +TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * allocate_ep(void) { + return find_ep_not_addr0(0, 0, 0); +} + +TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { + if (daddr == 0 && ep_num == 0) { + return &_hcd_data.ep[0]; + }else{ + return find_ep_not_addr0(daddr, ep_num, ep_dir); + } +} + +// free all endpoints belong to device address +static void free_ep(uint8_t daddr) { + for (size_t i=1; i<CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + if (ep->daddr == daddr) { + tu_memclr(ep, sizeof(max3421_ep_t)); + } + } +} + +static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { + size_t const idx = cur_ep - _hcd_data.ep; + + // starting from next endpoint + for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + if (ep->xfer_pending && ep->packet_size) { +// TU_LOG3("next pending i = %u\n", i); + return ep; + } + } + + // wrap around including current endpoint + for (size_t i = 0; i <= idx; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + if (ep->xfer_pending && ep->packet_size) { +// TU_LOG3("next pending i = %u\n", i); + return ep; + } + } + + return NULL; +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// optional hcd configuration, called by tuh_configure() +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport) { + (void) rhport; + + tuh_max3421_int_api(rhport, false); + tuh_max3421_spi_cs_api(rhport, false); + + TU_LOG2_INT(sizeof(max3421_ep_t)); + TU_LOG2_INT(sizeof(max3421_data_t)); + + tu_memclr(&_hcd_data, sizeof(_hcd_data)); + _hcd_data.peraddr = 0xff; // invalid + +#if OSAL_MUTEX_REQUIRED + _hcd_data.spi_mutex = osal_mutex_create(&_hcd_data.spi_mutexdef); +#endif + + // full duplex, interrupt negative edge + reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false); + + // V1 is 0x01, V2 is 0x12, V3 is 0x13 + // uint8_t const revision = reg_read(rhport, REVISION_ADDR, false); + // TU_LOG2_HEX(revision); + + // reset + reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false); + reg_write(rhport, USBCTL_ADDR, 0, false); + while( !(reg_read(rhport, USBIRQ_ADDR, false) & USBIRQ_OSCOK_IRQ) ) { + // wait for oscillator to stabilize + } + + // Mode: Host and DP/DM pull down + mode_write(rhport, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST, false); + + // frame reset & bus reset, this will trigger CONDET IRQ if device is already connected + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST, false); + + // clear all previously pending IRQ + hirq_write(rhport, 0xff, false); + + // Enable IRQ + hien_write(rhport, DEFAULT_HIEN, false); + + tuh_max3421_int_api(rhport, true); + + // Enable Interrupt pin + reg_write(rhport, CPUCTL_ADDR, CPUCTL_IE, false); + + return true; +} + +// Enable USB interrupt +// Not actually enable GPIO interrupt, just set variable to prevent handler to process +void hcd_int_enable (uint8_t rhport) { + tuh_max3421_int_api(rhport, true); +} + +// Disable USB interrupt +// Not actually disable GPIO interrupt, just set variable to prevent handler to process +void hcd_int_disable(uint8_t rhport) { + tuh_max3421_int_api(rhport, false); +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + return (uint32_t ) _hcd_data.frame_count; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + return (_hcd_data.mode & MODE_SOFKAENAB) ? true : false; +} + +// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. +// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. +void hcd_port_reset(uint8_t rhport) { + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false); +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) { + reg_write(rhport, HCTL_ADDR, 0, false); +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + return (_hcd_data.mode & MODE_LOWSPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + (void) dev_addr; +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc) { + (void) rhport; + (void) daddr; + + uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); + + max3421_ep_t * ep; + if (daddr == 0 && ep_num == 0) { + ep = &_hcd_data.ep[0]; + }else { + ep = allocate_ep(); + TU_ASSERT(ep); + ep->daddr = daddr; + ep->ep_num = ep_num; + ep->ep_dir = ep_dir; + } + + if ( TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer ) { + ep->is_iso = 1; + } + + ep->packet_size = tu_edpt_packet_size(ep_desc); + + return true; +} + +void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + // Page 12: Programming BULK-OUT Transfers + // TODO double buffered + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + + uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,); + if (xact_len) { + fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); + } + sndbc_write(rhport, xact_len, in_isr); + + uint8_t hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); + hxfr_write(rhport, hxfr, in_isr); +} + +void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + // Page 13: Programming BULK-IN Transfers + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + + uint8_t hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); + hxfr_write(rhport, hxfr, in_isr); +} + +TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + if (ep->ep_num == 0 ) { + // setup + if (ep->is_setup) { + peraddr_write(rhport, ep->daddr, in_isr); + fifo_write(rhport, SUDFIFO_ADDR, ep->buf, 8, in_isr); + hxfr_write(rhport, HXFR_SETUP, in_isr); + return; + } + + // status + if (ep->buf == NULL || ep->total_len == 0) { + uint8_t const hxfr = HXFR_HS | (ep->ep_dir ? 0 : HXFR_OUT_NIN); + peraddr_write(rhport, ep->daddr, in_isr); + hxfr_write(rhport, hxfr, in_isr); + return; + } + } + + if (ep->ep_dir) { + xact_in(rhport, ep, switch_ep, in_isr); + }else { + xact_out(rhport, ep, switch_ep, in_isr); + } +} + +// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked +bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); + TU_VERIFY(ep); + + // control transfer can switch direction + ep->ep_dir = ep_dir; + + ep->buf = buffer; + ep->total_len = buflen; + ep->xferred_len = 0; + ep->xfer_complete = 0; + ep->xfer_pending = 1; + + if ( ep_num == 0 ) { + ep->is_setup = 0; + ep->data_toggle = 1; + } + + // carry out transfer if not busy + if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { + xact_inout(rhport, ep, true, false); + } else { + return true; + } + + return true; +} + +// Abort a queued transfer. Note: it can only abort transfer that has not been started +// Return true if a queued transfer is aborted, false if there is no transfer to abort +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked +bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) { + (void) rhport; + + max3421_ep_t* ep = find_opened_ep(daddr, 0, 0); + TU_ASSERT(ep); + + ep->ep_dir = 0; + ep->is_setup = 1; + ep->buf = (uint8_t*)(uintptr_t) setup_packet; + ep->total_len = 8; + ep->xferred_len = 0; + ep->xfer_complete = 0; + ep->xfer_pending = 1; + + // carry out transfer if not busy + if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { + xact_inout(rhport, ep, true, false); + } + + return true; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +//--------------------------------------------------------------------+ +// Interrupt Handler +//--------------------------------------------------------------------+ + +static void handle_connect_irq(uint8_t rhport, bool in_isr) { + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr); + uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); + + uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; + TU_LOG2_HEX(jk); + + switch(jk) { + case 0x00: // SEO is disconnected + case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal + mode_write(rhport, new_mode, in_isr); + + // port reset anyway, this will help to stable bus signal for next connection + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr); + + hcd_event_device_remove(rhport, in_isr); + + reg_write(rhport, HCTL_ADDR, 0, in_isr); + break; + + default: { + // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset + if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) { + break; + } + + // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) + // However, since we are always in full speed mode, we can just check J-state + if (jk == HRSL_KSTATUS) { + new_mode |= MODE_LOWSPEED; + TU_LOG3("Low speed\n"); + }else { + TU_LOG3("Full speed\n"); + } + new_mode |= MODE_SOFKAENAB; + mode_write(rhport, new_mode, in_isr); + + // FIXME multiple MAX3421 rootdevice address is not 1 + uint8_t const daddr = 1; + free_ep(daddr); + + hcd_event_device_attach(rhport, in_isr); + + break; + } + } +} + +static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) { + uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); + + // save data toggle + if (ep->ep_dir) { + ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; + }else { + ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + } + + ep->xfer_pending = 0; + hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true); + + // Find next pending endpoint + max3421_ep_t *next_ep = find_next_pending_ep(ep); + if (next_ep) { + xact_inout(rhport, next_ep, true, true); + }else { + // no more pending + atomic_flag_clear(&_hcd_data.busy); + } +} + +static void handle_xfer_done(uint8_t rhport) { + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); + uint8_t const hresult = hrsl & HRSL_RESULT_MASK; + + uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0; + uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1; + + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir); + TU_VERIFY(ep, ); + + xfer_result_t xfer_result; + switch(hresult) { + case HRSL_SUCCESS: + xfer_result = XFER_RESULT_SUCCESS; + break; + + case HRSL_STALL: + xfer_result = XFER_RESULT_STALLED; + break; + + case HRSL_NAK: + if (ep_num == 0) { + // NAK on control, retry immediately + hxfr_write(rhport, _hcd_data.hxfr, true); + }else { + // NAK on non-control, find next pending to switch + max3421_ep_t *next_ep = find_next_pending_ep(ep); + + if (ep == next_ep) { + // this endpoint is only one pending, retry immediately + hxfr_write(rhport, _hcd_data.hxfr, true); + }else if (next_ep) { + // switch to next pending TODO could have issue with double buffered if not clear previously out data + xact_inout(rhport, next_ep, true, true); + }else { + TU_ASSERT(false,); + } + } + return; + + case HRSL_BAD_REQ: + // occurred when initialized without any pending transfer. Skip for now + return; + + default: + TU_LOG3("HRSL: %02X\r\n", hrsl); + xfer_result = XFER_RESULT_FAILED; + break; + } + + if (xfer_result != XFER_RESULT_SUCCESS) { + xfer_complete_isr(rhport, ep, xfer_result, hrsl); + return; + } + + if (ep_dir) { + // IN transfer: fifo data is already received in RCVDAV IRQ + if ( hxfr_type & HXFR_HS ) { + ep->xfer_complete = 1; + } + + // short packet or all bytes transferred + if ( ep->xfer_complete ) { + xfer_complete_isr(rhport, ep, xfer_result, hrsl); + }else { + // more to transfer + hxfr_write(rhport, _hcd_data.hxfr, true); + } + } else { + // SETUP or OUT transfer + uint8_t xact_len; + + if (hxfr_type & HXFR_SETUP) { + xact_len = 8; + } else if (hxfr_type & HXFR_HS) { + xact_len = 0; + } else { + xact_len = _hcd_data.sndbc; + } + + ep->xferred_len += xact_len; + ep->buf += xact_len; + + if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { + xfer_complete_isr(rhport, ep, xfer_result, hrsl); + } else { + // more to transfer + xact_out(rhport, ep, false, true); + } + } +} + +#if CFG_TUSB_DEBUG >= 3 +void print_hirq(uint8_t hirq) { + TU_LOG3_HEX(hirq); + + if (hirq & HIRQ_HXFRDN_IRQ) TU_LOG3(" HXFRDN"); + if (hirq & HIRQ_FRAME_IRQ) TU_LOG3(" FRAME"); + if (hirq & HIRQ_CONDET_IRQ) TU_LOG3(" CONDET"); + if (hirq & HIRQ_SUSDN_IRQ) TU_LOG3(" SUSDN"); + if (hirq & HIRQ_SNDBAV_IRQ) TU_LOG3(" SNDBAV"); + if (hirq & HIRQ_RCVDAV_IRQ) TU_LOG3(" RCVDAV"); + if (hirq & HIRQ_RWU_IRQ) TU_LOG3(" RWU"); + if (hirq & HIRQ_BUSEVENT_IRQ) TU_LOG3(" BUSEVENT"); + + TU_LOG3("\r\n"); +} +#else + #define print_hirq(hirq) +#endif + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien; + if (!hirq) return; +// print_hirq(hirq); + + if (hirq & HIRQ_FRAME_IRQ) { + _hcd_data.frame_count++; + } + + if (hirq & HIRQ_CONDET_IRQ) { + handle_connect_irq(rhport, true); + } + + // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or + // not call this handler again. So we need to loop until all IRQ are cleared + while ( hirq & (HIRQ_RCVDAV_IRQ | HIRQ_HXFRDN_IRQ) ) { + if ( hirq & HIRQ_RCVDAV_IRQ ) { + uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1); + uint8_t xact_len; + + // RCVDAV_IRQ can trigger 2 times (dual buffered) + while ( hirq & HIRQ_RCVDAV_IRQ ) { + uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, true); + xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); + if ( xact_len ) { + fifo_read(rhport, ep->buf, xact_len, true); + ep->buf += xact_len; + ep->xferred_len += xact_len; + } + + // ack RCVDVAV IRQ + hirq_write(rhport, HIRQ_RCVDAV_IRQ, true); + hirq = reg_read(rhport, HIRQ_ADDR, true); + } + + if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + ep->xfer_complete = 1; + } + } + + if ( hirq & HIRQ_HXFRDN_IRQ ) { + hirq_write(rhport, HIRQ_HXFRDN_IRQ, true); + handle_xfer_done(rhport); + } + + hirq = reg_read(rhport, HIRQ_ADDR, true); + } + + // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing + hirq &= ~HIRQ_SNDBAV_IRQ; + if ( hirq ) { + hirq_write(rhport, hirq, true); + } +} + +#endif diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 590dd9fcf..12d610bd6 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUSB_MCU == OPT_MCU_NONE +#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE #include "device/dcd.h" @@ -141,4 +141,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) (void) ep_addr; } + + #endif diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c new file mode 100644 index 000000000..3e3b91558 --- /dev/null +++ b/src/portable/template/hcd_template.c @@ -0,0 +1,162 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 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 CFG_TUH_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE + +#include "host/hcd.h" + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// optional hcd configuration, called by tuh_configure() +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport) { + (void) rhport; + + return false; +} + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + (void) rhport; +} + +// Enable USB interrupt +void hcd_int_enable (uint8_t rhport) { + (void) rhport; +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + (void) rhport; +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + + return 0; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + + return false; +} + +// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. +// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. +void hcd_port_reset(uint8_t rhport) { + (void) rhport; +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + + return TUSB_SPEED_FULL; +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + (void) dev_addr; +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { + (void) rhport; + (void) dev_addr; + (void) ep_desc; + + return false; +} + +// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + (void) buffer; + (void) buflen; + + return false; +} + +// Abort a queued transfer. Note: it can only abort transfer that has not been started +// Return true if a queued transfer is aborted, false if there is no transfer to abort +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + (void) dev_addr; + (void) setup_packet; + + return false; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +#endif diff --git a/src/tusb.h b/src/tusb.h index 37a521fa8..d6534ca28 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -64,7 +64,10 @@ #if CFG_TUH_VENDOR #include "class/vendor/vendor_host.h" #endif - +#else + #ifndef tuh_int_handler + #define tuh_int_handler(_x) + #endif #endif //------------- DEVICE -------------// @@ -118,6 +121,10 @@ #if CFG_TUD_BTH #include "class/bth/bth_device.h" #endif +#else + #ifndef tud_int_handler + #define tud_int_handler(_x) + #endif #endif |
