Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions src/arduino/Adafruit_USBH_Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,14 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
SPIClass *spi = host->_spi;

if (active) {
// MAX3421e max clock is 26MHz
// Depending on mcu ports, it may need to be clipped down
// MAX3421e max clock is 26MHz. SAMD SERCOM clocks are quantized by the
// baud generator, so request values that stay within each port's limit.
#ifdef ARDUINO_ARCH_SAMD
// SAMD 21/51 can only work reliably at 12MHz
#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X)
uint32_t const max_clock = 25000000ul;
#else
uint32_t const max_clock = 12000000ul;
#endif
#else
uint32_t const max_clock = 26000000ul;
#endif
Expand Down Expand Up @@ -273,11 +276,20 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void)host;

#ifdef ARDUINO_ARCH_SAMD
//--- SAMD51 ---//
#ifdef __SAMD51__
//--- SAMD51/SAME51 ---//
#if TU_CHECK_MCU(OPT_MCU_SAMD51)
const IRQn_Type irq =
(IRQn_Type)(EIC_0_IRQn + g_APinDescription[host->_intr].ulExtInt);

if (enabled) {
NVIC_EnableIRQ(irq);
} else {
NVIC_DisableIRQ(irq);
}
#elif TU_CHECK_MCU(OPT_MCU_SAME5X)
const IRQn_Type irq =
(IRQn_Type)(EIC_EXTINT_0_IRQn + g_APinDescription[host->_intr].ulExtInt);

if (enabled) {
NVIC_EnableIRQ(irq);
} else {
Expand Down
39 changes: 35 additions & 4 deletions src/arduino/ports/samd/Adafruit_TinyUSB_samd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,23 @@
//--------------------------------------------------------------------+
extern "C" {

#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X
#if TU_CHECK_MCU(OPT_MCU_SAMD51)

// SAMD51
void USB_0_Handler(void) { tud_int_handler(0); }
void USB_1_Handler(void) { tud_int_handler(0); }
void USB_2_Handler(void) { tud_int_handler(0); }
void USB_3_Handler(void) { tud_int_handler(0); }

#elif CFG_TUSB_MCU == OPT_MCU_SAMD21
#elif TU_CHECK_MCU(OPT_MCU_SAME5X)

// SAME53/54
void USB_OTHER_Handler(void) { tud_int_handler(0); }
void USB_SOF_HSOF_Handler(void) { tud_int_handler(0); }
void USB_TRCPT0_Handler(void) { tud_int_handler(0); }
void USB_TRCPT1_Handler(void) { tud_int_handler(0); }

#elif TU_CHECK_MCU(OPT_MCU_SAMD21)

// SAMD21
void USB_Handler(void) { tud_int_handler(0); }
Expand All @@ -61,7 +69,7 @@ void TinyUSB_Port_InitDevice(uint8_t rhport) {
(void)rhport;

/* Enable USB clock */
#if defined(__SAMD51__)
#if TU_CHECK_MCU(OPT_MCU_SAMD51)
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;

Expand All @@ -84,6 +92,29 @@ void TinyUSB_Port_InitDevice(uint8_t rhport) {
NVIC_SetPriority(USB_1_IRQn, 0UL);
NVIC_SetPriority(USB_2_IRQn, 0UL);
NVIC_SetPriority(USB_3_IRQn, 0UL);
#elif TU_CHECK_MCU(OPT_MCU_SAME5X)
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;

// Set up the USB DP/DN pins
PORT->Group[0].PINCFG[PIN_PA24H_USB_DM].bit.PMUXEN = 1;
PORT->Group[0].PMUX[PIN_PA24H_USB_DM / 2].reg &=
~(0xF << (4 * (PIN_PA24H_USB_DM & 0x01u)));
PORT->Group[0].PMUX[PIN_PA24H_USB_DM / 2].reg |=
MUX_PA24H_USB_DM << (4 * (PIN_PA24H_USB_DM & 0x01u));
PORT->Group[0].PINCFG[PIN_PA25H_USB_DP].bit.PMUXEN = 1;
PORT->Group[0].PMUX[PIN_PA25H_USB_DP / 2].reg &=
~(0xF << (4 * (PIN_PA25H_USB_DP & 0x01u)));
PORT->Group[0].PMUX[PIN_PA25H_USB_DP / 2].reg |=
MUX_PA25H_USB_DP << (4 * (PIN_PA25H_USB_DP & 0x01u));

GCLK->PCHCTRL[USB_GCLK_ID].reg =
GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);

NVIC_SetPriority(USB_OTHER_IRQn, 0UL);
NVIC_SetPriority(USB_SOF_HSOF_IRQn, 0UL);
NVIC_SetPriority(USB_TRCPT0_IRQn, 0UL);
NVIC_SetPriority(USB_TRCPT1_IRQn, 0UL);
#else
PM->APBBMASK.reg |= PM_APBBMASK_USB;

Expand Down Expand Up @@ -126,7 +157,7 @@ void TinyUSB_Port_EnterDFU(void) {
}

uint8_t TinyUSB_Port_GetSerialNumber(uint8_t serial_id[16]) {
#ifdef __SAMD51__
#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X)
uint32_t *id_addresses[4] = {(uint32_t *)0x008061FC, (uint32_t *)0x00806010,
(uint32_t *)0x00806014, (uint32_t *)0x00806018};
#else // samd21
Expand Down
4 changes: 3 additions & 1 deletion src/arduino/ports/samd/tusb_config_samd.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ extern "C" {
//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------
#ifdef __SAMD51__
#if defined(__SAMD51__) || defined(__SAME51__)
#define CFG_TUSB_MCU OPT_MCU_SAMD51
#elif defined(__SAME53__) || defined(__SAME54__)
#define CFG_TUSB_MCU OPT_MCU_SAME5X
#else
#define CFG_TUSB_MCU OPT_MCU_SAMD21
#endif
Expand Down
20 changes: 19 additions & 1 deletion src/portable/microchip/samd/dcd_samd.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#if CFG_TUD_ENABLED && TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X, OPT_MCU_SAMD51, OPT_MCU_SAME5X)

#include "sam.h"
#include "same5x_usb.h"
#include "device/dcd.h"

/*------------------------------------------------------------------*/
Expand Down Expand Up @@ -103,7 +104,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
return true;
}

#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X)
#if TU_CHECK_MCU(OPT_MCU_SAMD51)
void dcd_int_enable(uint8_t rhport) {
(void) rhport;
NVIC_EnableIRQ(USB_0_IRQn);
Expand All @@ -120,6 +121,23 @@ void dcd_int_disable(uint8_t rhport) {
NVIC_DisableIRQ(USB_0_IRQn);
}

#elif TU_CHECK_MCU(OPT_MCU_SAME5X)
void dcd_int_enable(uint8_t rhport) {
(void) rhport;
NVIC_EnableIRQ(USB_OTHER_IRQn);
NVIC_EnableIRQ(USB_SOF_HSOF_IRQn);
NVIC_EnableIRQ(USB_TRCPT0_IRQn);
NVIC_EnableIRQ(USB_TRCPT1_IRQn);
}

void dcd_int_disable(uint8_t rhport) {
(void) rhport;
NVIC_DisableIRQ(USB_TRCPT1_IRQn);
NVIC_DisableIRQ(USB_TRCPT0_IRQn);
NVIC_DisableIRQ(USB_SOF_HSOF_IRQn);
NVIC_DisableIRQ(USB_OTHER_IRQn);
}

#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X)
void dcd_int_enable(uint8_t rhport) {
(void) rhport;
Expand Down
25 changes: 24 additions & 1 deletion src/portable/microchip/samd/hcd_samd.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "host/hcd.h"
#include "sam.h"
#include "same5x_usb.h"

/*------------------------------------------------------------------*/
/* MACRO TYPEDEF CONSTANT ENUM
Expand Down Expand Up @@ -425,7 +426,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
return true;
}

#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X)
#if TU_CHECK_MCU(OPT_MCU_SAMD51)

// Enable USB interrupt
void hcd_int_enable(uint8_t rhport)
Expand All @@ -447,6 +448,28 @@ void hcd_int_disable(uint8_t rhport)
NVIC_DisableIRQ(USB_0_IRQn);
}

#elif TU_CHECK_MCU(OPT_MCU_SAME5X)

// Enable USB interrupt
void hcd_int_enable(uint8_t rhport)
{
(void) rhport;
NVIC_EnableIRQ(USB_OTHER_IRQn);
NVIC_EnableIRQ(USB_SOF_HSOF_IRQn);
NVIC_EnableIRQ(USB_TRCPT0_IRQn);
NVIC_EnableIRQ(USB_TRCPT1_IRQn);
}

// Disable USB interrupt
void hcd_int_disable(uint8_t rhport)
{
(void) rhport;
NVIC_DisableIRQ(USB_TRCPT1_IRQn);
NVIC_DisableIRQ(USB_TRCPT0_IRQn);
NVIC_DisableIRQ(USB_SOF_HSOF_IRQn);
NVIC_DisableIRQ(USB_OTHER_IRQn);
}

#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X)

// Enable USB interrupt
Expand Down
85 changes: 85 additions & 0 deletions src/portable/microchip/samd/same5x_usb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2026 Chris Rabel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef _SAME5X_USB_H_
#define _SAME5X_USB_H_

#if defined(__GNUC__)
#pragma GCC system_header
#endif

#include "tusb_option.h"

#if TU_CHECK_MCU(OPT_MCU_SAME5X)

#ifndef _Ul
#define _Ul(x) x##U
#endif

#ifndef TUSB_SAME5X_COMPAT_ROREG8
#define TUSB_SAME5X_COMPAT_ROREG8 1
typedef volatile const uint8_t RoReg8;
#endif

#if defined(__has_include)
#if __has_include("samd51/include/component/usb.h")
#include "samd51/include/component/usb.h"
#else
#error "SAME5x USB support requires SAMD51 USB component headers on the include path."
#endif
#else
#include "samd51/include/component/usb.h"
#endif

#if !defined(NVMCTRL_SW0) && defined(SW0_ADDR)
#define NVMCTRL_SW0 SW0_ADDR
#elif !defined(NVMCTRL_SW0) && defined(SW0_FUSES_BASE_ADDRESS)
#define NVMCTRL_SW0 SW0_FUSES_BASE_ADDRESS
#endif

#ifndef USB_FUSES_TRANSN_ADDR
#define USB_FUSES_TRANSN_ADDR (NVMCTRL_SW0 + 4)
#define USB_FUSES_TRANSN_Pos 0
#define USB_FUSES_TRANSN_Msk (_Ul(0x1F) << USB_FUSES_TRANSN_Pos)
#endif

#ifndef USB_FUSES_TRANSP_ADDR
#define USB_FUSES_TRANSP_ADDR (NVMCTRL_SW0 + 4)
#define USB_FUSES_TRANSP_Pos 5
#define USB_FUSES_TRANSP_Msk (_Ul(0x1F) << USB_FUSES_TRANSP_Pos)
#endif

#ifndef USB_FUSES_TRIM_ADDR
#define USB_FUSES_TRIM_ADDR (NVMCTRL_SW0 + 4)
#define USB_FUSES_TRIM_Pos 10
#define USB_FUSES_TRIM_Msk (_Ul(0x7) << USB_FUSES_TRIM_Pos)
#endif

#if !defined(USB) && defined(USB_REGS)
#define USB ((Usb *)USB_REGS)
#endif

#endif

#endif
Loading