ATSAMD51 custom board, PWM not properly configured

hello everyone
I built a custom board around ATSAMD51J20, and flashed it with a customized Adafruit bootloader (so that it works with J20 variant, since Adafruit only uses J19 as far as I know). I also customized the files "variant.cpp" and "variant.h" to my needs.
Everything that I need is working (SPI, digital inputs/outputs, analog inputs) except for PWM on pins PB16 and PB17. I'm pretty sure it is because I customized the wrong way the variant files.
Those pins are working fine if used as digital outputs, but with analogWrite, the code seems to freeze and nothing else works anymore (also no voltage on those pins).
I've read the datasheet to understand to what timers those pins are set, and tried different combinations, but no luck.

this is the simple sketch that I'm using and the variant files:

#define PWM_1 5
#define PWM_2 7

void setup() {
  pinMode(PWM_1, OUTPUT);
}

void loop() {
  analogWrite(PWM_1, 0);
  delay(1000);
  analogWrite(PWM_1, 127);
  delay(1000);
  analogWrite(PWM_1, 255);
  delay(1000);
}
#include "variant.h"

const PinDescription g_APinDescription[]=
{
  { PORTB, 13, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH1   , TCC3_CH1    , EXTERNAL_INT_13   }, //0    DAC_BIT_07
  { PORTB, 12, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH0   , TCC3_CH0    , EXTERNAL_INT_12   }, //1    DAC-BIT_O8
  { PORTB, 22, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, //2    ON_EXTMOD
  { PORTA,  4, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4  , TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, //3    POT_BALANCE    [ADC]
  { PORTA,  5, PIO_SERCOM_ALT, PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, //4
  { PORTB, 16, PIO_TIMER     , PIN_ATTR_PWM_F                  , No_ADC_Channel, TC6_CH0   , TCC0_CH4    , EXTERNAL_INT_0    }, //5    PWM_DEPTH      [PWM]
  { PORTB, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_15   }, //6    DAC_BIT_05
  { PORTB, 17, PIO_TIMER     , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH1   , TCC0_CH5    , EXTERNAL_INT_1    }, //7    PWM_FREQ       [PWM]
  { PORTB, 14, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_14   }, //8    DAC_BIT_06
  { PORTB,  4, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4    }, //9    SHIFT_LIN
  { PORTB,  5, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5    }, //10   SHIFT_LOUT
  { PORTB,  6, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, //11   ACTIVE_1
  { PORTB,  7, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, //12   TAP
  { PORTB, 23, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, //13
  { PORTA,  2, PIO_DIGITAL   , PIN_ATTR_ANALOG                 , DAC_Channel0  , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, //14
  { PORTA,  4, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, //15
  { PORTA,  7, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC1_CH1   , TC1_CH1     , EXTERNAL_INT_7    }, //16   DLY_EOC
  { PORTA,  5, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, //17
  { PORTB,  0, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0    }, //18   SHIFT_DIN
  { PORTB,  1, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, //19   SHIFT_DOUT
  { PORTA,  6, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6  , TC1_CH0   , TC1_CH0     , EXTERNAL_INT_6    }, //20   POT_FDBK       [ADC]
  { PORTB,  8, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2  , TC4_CH0   , TC4_CH0     , EXTERNAL_INT_8    }, //21   POT_FREQ       [ADC]
  { PORTB,  2, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel14 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, //22   LED_METER      [ADC]
  { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, //23   SHIFT_CLK
  { PORTA,  0, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, //24
  { PORTB, 31, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC4_CH1  , TCC4_CH1    , EXTERNAL_INT_15   }, //25   ON_SQUARE
  { PORTB,  9, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3  , TC4_CH1   , TC4_CH1     , EXTERNAL_INT_9    }, //26   POT_DEPTH      [ADC]
  { PORTB,  2, PIO_SERCOM_ALT, PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, //27
  { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, //28
  { PORTA, 12, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_12   }, //29
  { PORTA, 13, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_13   }, //30   ADC_SCLK       [SPI-CLK]
  { PORTA, 14, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH0   , TC3_CH0     , EXTERNAL_INT_14   }, //31   ADC_SO         [SPI-SO]
  { PORTB, 30, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH0   , TC0_CH0     , EXTERNAL_INT_14   }, //32   ON_TRI
  { PORTA,  1, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_1    }, //33
  { PORTA, 16, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, //34   DAC_BIT_01
  { PORTA, 17, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH1  , TC2_CH1     , EXTERNAL_INT_1    }, //35   DAC_BIT_03
  { PORTA, 18, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH2  , TC3_CH0     , EXTERNAL_INT_2    }, //36   DAC_BIT_04
  { PORTA, 19, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH3  , TC3_CH1     , EXTERNAL_INT_3    }, //37   ADC_CS         [SPI-CS]
  { PORTA, 20, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH0     , EXTERNAL_INT_4    }, //38   ADC_BIT_13
  { PORTA, 21, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH1     , EXTERNAL_INT_5    }, //39   DLY_DA_SH
  { PORTA, 22, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH2  , TC4_CH0     , EXTERNAL_INT_6    }, //40
  { PORTA, 23, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH3  , TC4_CH1     , EXTERNAL_INT_7    }, //41   MIDI_RX        [RX]
  { PORTB, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_10   }, //42   DAC_BIT_10
  { PORTB, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_11   }, //43   DAC_BIT_09
  { PORTA,  8, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI  }, //44   DLY_START
  { PORTA,  9, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9    }, //45   DAC_BIT_13
  { PORTA, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10   }, //46   DAC_BIT_11
  { PORTA, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, //47   DAC_BIT_12
  { PORTA, 24, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, //48   [USB D-]
  { PORTA, 25, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, //49   [USB D+]
  { PORTA, 27, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, //50
  { PORTA, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH1   , TC3_CH1     , EXTERNAL_INT_15   }, //51   DAC_BIT_02
} ;

const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;

SERCOM sercom0( SERCOM0 ) ;
SERCOM sercom1( SERCOM1 ) ;
SERCOM sercom2( SERCOM2 ) ;
SERCOM sercom3( SERCOM3 ) ;
SERCOM sercom4( SERCOM4 ) ;
SERCOM sercom5( SERCOM5 ) ;

Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;

void SERCOM4_0_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial1.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial1.IrqHandler();
}

#ifndef _VARIANT_PYPORTAL_M4_
#define _VARIANT_PYPORTAL_M4_

// The definitions here needs a SAMD core >=1.6.10
#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610

/** Frequency of the board main oscillator */
#define VARIANT_MAINOSC     (32768ul)

/** Master clock frequency */
#define VARIANT_MCK        (F_CPU)

#define VARIANT_GCLK0_FREQ (F_CPU)
#define VARIANT_GCLK1_FREQ (48000000UL)
#define VARIANT_GCLK2_FREQ (100000000UL)

#include "WVariant.h"

#ifdef __cplusplus
#include "SERCOM.h"
#include "Uart.h"
#endif

#ifdef __cplusplus
extern "C"
{
#endif

#define PINS_COUNT           (52u)
#define NUM_DIGITAL_PINS     (46u)
#define NUM_ANALOG_INPUTS    (5u)
#define NUM_ANALOG_OUTPUTS   (1u)

#define analogInputToDigitalPin(p)  ((p == 3u || p == 20u || p == 21u || p == 22u || p == 26u) ? (p) : -1)
#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
#define portOutputRegister(port)   ( &(port->OUT.reg) )
#define portInputRegister(port)    ( &(port->IN.reg) )
#define portModeRegister(port)     ( &(port->DIR.reg) )
#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )

//TODO da ridefinire!!
 #define PIN_A0               (14ul)
 #define PIN_A1               (PIN_A0 + 1)
 #define PIN_A2               (PIN_A0 + 2)
 #define PIN_A3               (PIN_A0 + 3)
 #define PIN_A4               (PIN_A0 + 4)
 #define PIN_A5               (PIN_A0 + 5)
 #define PIN_A6               (PIN_A0 + 6)
 #define PIN_A7               (PIN_A0 + 7)
 #define PIN_A8               (PIN_A0 + 8)
 #define PIN_A9               (PIN_A0 + 9)
 #define PIN_DAC0             PIN_A0
 #define PIN_DAC1             PIN_A1

static const uint8_t A0  = PIN_A0;
static const uint8_t A1  = PIN_A1;
static const uint8_t A2  = PIN_A2;
static const uint8_t A3  = PIN_A3;
static const uint8_t A4  = PIN_A4;
static const uint8_t A5  = PIN_A5;
static const uint8_t A6  = PIN_A6;
static const uint8_t A7  = PIN_A7;
static const uint8_t A8  = PIN_A8;
static const uint8_t A9  = PIN_A9;

 static const uint8_t DAC0 = PIN_DAC0;

#define ADC_RESOLUTION      12

// Serial1
#define PIN_SERIAL1_RX       (0ul)
#define PIN_SERIAL1_TX       (1ul)
#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
#define PAD_SERIAL1_TX       (UART_TX_PAD_0)

//SPI
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO         (31u)
#define PIN_SPI_MOSI         (29u)
#define PIN_SPI_SCK          (30u)
#define PERIPH_SPI           sercom2
#define PAD_SPI_TX           SPI_PAD_0_SCK_1
#define PAD_SPI_RX           SERCOM_RX_PAD_2
//static const uint8_t SS   = PIN_A2;       // ???
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK  = PIN_SPI_SCK;

//USB
#define PIN_USB_HOST_ENABLE (29ul) // ???
#define PIN_USB_DM          (48ul)
#define PIN_USB_DP          (49ul)

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

extern SERCOM sercom0;
extern SERCOM sercom1;
extern SERCOM sercom2;
extern SERCOM sercom3;
extern SERCOM sercom4;
extern SERCOM sercom5;

extern Uart Serial1;

#endif

#define SERIAL_PORT_USBVIRTUAL      Serial
#define SERIAL_PORT_MONITOR         Serial
#define SERIAL_PORT_HARDWARE        Serial1
#define SERIAL_PORT_HARDWARE_OPEN   Serial1

#endif

anyone please? :frowning:

J19 and J20 only differ in the amount of flash, right? So the pin definitions (mapping of port/bit to actual functions available) shouldn't change. You have:

  { PORTB, 16, PIO_TIMER     , PIN_ATTR_PWM_F                  , No_ADC_Channel, TC6_CH0   , TCC0_CH4    , EXTERNAL_INT_0    }, //5    PWM_DEPTH      [PWM]
    :
  { PORTB, 17, PIO_TIMER     , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH1   , TCC0_CH5    , EXTERNAL_INT_1    }, //7    PWM_FREQ       [PWM] 

While the Adafruit source has:

  { PORTB,  17, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 }, // d2
  { PORTB,  16, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 }, // d3

I'm not sure what PIO_TIMER means in that field, but given that it's NEVER used in the Adafruit SAMD51 boards, I think it's probably not the right thing to use. The other parameters for those pins are also different. I don't think yours look WRONG, but I'm not sure how having multiple timer types (TC and TCC) interacts with the PWM code.
I'd stick with the Adafruit definitions, and see if that works.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.