DM: added samd51 support

This commit is contained in:
dean 2017-06-30 17:24:28 -04:00
parent 99001c0099
commit 37b9881cbe
15 changed files with 1153 additions and 166 deletions

View file

@ -151,3 +151,42 @@ adafruit_circuitplayground_m0.build.vid=0x239A
adafruit_circuitplayground_m0.build.pid=0x8018
adafruit_circuitplayground_m0.bootloader.tool=openocd
adafruit_circuitplayground_m0.bootloader.file=circuitplay/circuitplay_m0_samd21g18_sam_ba.bin
# Arduino X1
# ------------------------------
arduino_x1.name=Adafruit X1
arduino_x1.vid.0=0x2341
arduino_x1.pid.0=0x804d
arduino_x1.vid.1=0x2341
arduino_x1.pid.1=0x004d
arduino_x1.vid.2=0x2341
arduino_x1.pid.2=0x824d
# If the board is a 2341:824d use 2341:824d for build and set other parameters as well
arduino_x1.vid.2.build.vid=0x2341
arduino_x1.vid.2.build.pid=0x824d
arduino_x1.vid.2.build.usb_product="Adafruit X1"
arduino_x1.vid.2.bootloader.file=x1/samdx1_sam_ba.bin
arduino_x1.upload.tool=bossac
arduino_x1.upload.protocol=sam-ba
#TODO: fix
arduino_x1.upload.maximum_size=262144
arduino_x1.upload.use_1200bps_touch=true
arduino_x1.upload.wait_for_upload_port=true
arduino_x1.upload.native_usb=true
arduino_x1.build.mcu=cortex-m4
arduino_x1.build.f_cpu=48000000L
arduino_x1.build.usb_product="Adafruit X1"
arduino_x1.build.usb_manufacturer="Adafruit LLC"
arduino_x1.build.board=SAMD_X1
arduino_x1.build.core=arduino
arduino_x1.build.extra_flags=-D__SAMD51G19A__ {build.usb_flags}
arduino_x1.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
arduino_x1.build.openocdscript=openocd_scripts/arduino_zero.cfg
arduino_x1.build.variant=arduino_x1
arduino_x1.build.variant_system_lib=
arduino_x1.build.vid=0x2341
arduino_x1.build.pid=0x804d
arduino_x1.bootloader.tool=openocd
arduino_x1.bootloader.file=x1/samdx1_sam_ba.bin

View file

@ -130,4 +130,8 @@ void loop( void ) ;
#include "USB/USBAPI.h"
#include "USB/USB_host.h"
#define _U(x) x ## U /**< C code: Unsigned integer literal constant value */
#define _L(x) x ## L /**< C code: Long integer literal constant value */
#define _UL(x) x ## UL /**< C code: Unsigned Long integer literal constant value */
#endif // Arduino_h

View file

@ -35,35 +35,61 @@ extern const uint32_t __text_start__;
#endif
static inline bool nvmReady(void) {
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
return NVMCTRL->STATUS.reg & NVMCTRL_STATUS_READY;
#else
return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY;
#endif
}
__attribute__ ((long_call, section (".ramfunc")))
static void banzai() {
// Disable all interrupts
__disable_irq();
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//THESE MUST MATCH THE BOOTLOADER
#define DOUBLE_TAP_MAGIC 0x07738135
#define BOOT_DOUBLE_TAP_ADDRESS 0x20007FFC
unsigned long *a = (unsigned long *)BOOT_DOUBLE_TAP_ADDRESS;
*a = DOUBLE_TAP_MAGIC;
//NVMCTRL->ADDR.reg = APP_START;
//NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY;
// Reset the device
NVIC_SystemReset() ;
while (true);
#else
// Avoid erasing the application if APP_START is < than the minimum bootloader size
// This could happen if without_bootloader linker script was chosen
// Minimum bootloader size in SAMD21 family is 512bytes (RM section 22.6.5)
if (APP_START < (0x200 + 4)) {
goto reset;
}
// Erase application
while (!nvmReady())
;
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK;
NVMCTRL->ADDR.reg = (uintptr_t)&NVM_MEMORY[APP_START / 4];
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER | NVMCTRL_CTRLA_CMDEX_KEY;
while (!nvmReady())
;
;
reset:
// Reset the device
NVIC_SystemReset() ;
while (true);
#endif
}
static int ticks = -1;

View file

@ -18,6 +18,7 @@
#include "SERCOM.h"
#include "variant.h"
#include "Arduino.h"
SERCOM::SERCOM(Sercom* s)
{
@ -182,17 +183,25 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch
resetSPI();
initClockNVIC();
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(0x3) | //master mode
SERCOM_SPI_CTRLA_DOPO(mosi) |
SERCOM_SPI_CTRLA_DIPO(miso) |
dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
#else
//Setting the CTRLA register
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
SERCOM_SPI_CTRLA_DOPO(mosi) |
SERCOM_SPI_CTRLA_DIPO(miso) |
dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
#endif
//Setting the CTRLB register
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
SERCOM_SPI_CTRLB_RXEN; //Active the SPI receiver.
while( sercom->SPI.SYNCBUSY.bit.CTRLB == 1 );
}
void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
@ -475,7 +484,7 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
address = (address << 0x1ul) | flag;
// Wait idle or owner bus mode
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
// Send start and address
sercom->I2CM.ADDR.bit.ADDR = address;
@ -629,9 +638,57 @@ uint8_t SERCOM::readDataWIRE( void )
void SERCOM::initClockNVIC( void )
{
uint8_t clockId = 0;
IRQn_Type IdNvic=PendSV_IRQn ; // Dummy init to intercept potential error later
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
uint32_t clk_core;
uint32_t clk_slow;
if(sercom == SERCOM0)
{
clk_core = SERCOM0_GCLK_ID_CORE;
clk_slow = SERCOM0_GCLK_ID_SLOW;
IdNvic = SERCOM0_0_IRQn;
}
else if(sercom == SERCOM1)
{
clk_core = SERCOM1_GCLK_ID_CORE;
clk_slow = SERCOM1_GCLK_ID_SLOW;
IdNvic = SERCOM1_0_IRQn;
}
else if(sercom == SERCOM2)
{
clk_core = SERCOM2_GCLK_ID_CORE;
clk_slow = SERCOM2_GCLK_ID_SLOW;
IdNvic = SERCOM2_2_IRQn;
}
else if(sercom == SERCOM3)
{
clk_core = SERCOM3_GCLK_ID_CORE;
clk_slow = SERCOM3_GCLK_ID_SLOW;
IdNvic = SERCOM3_0_IRQn;
}
else if(sercom == SERCOM4)
{
clk_core = SERCOM4_GCLK_ID_CORE;
clk_slow = SERCOM4_GCLK_ID_SLOW;
IdNvic = SERCOM4_0_IRQn;
}
else if(sercom == SERCOM5)
{
clk_core = SERCOM5_GCLK_ID_CORE;
clk_slow = SERCOM5_GCLK_ID_SLOW;
IdNvic = SERCOM5_0_IRQn;
}
if ( IdNvic == PendSV_IRQn )
{
// We got a problem here
return ;
}
#else
uint8_t clockId = 0;
if(sercom == SERCOM0)
{
clockId = GCM_SERCOM0_CORE;
@ -668,11 +725,18 @@ void SERCOM::initClockNVIC( void )
// We got a problem here
return ;
}
#endif
// Setting NVIC
NVIC_EnableIRQ(IdNvic);
NVIC_ClearPendingIRQ(IdNvic);
NVIC_SetPriority (IdNvic, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority */
NVIC_EnableIRQ(IdNvic);
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
GCLK->PCHCTRL[clk_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[clk_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
#else
//Setting clock
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
@ -682,4 +746,5 @@ void SERCOM::initClockNVIC( void )
{
/* Wait for synchronization */
}
#endif
}

View file

@ -19,7 +19,11 @@
#include "Tone.h"
#include "variant.h"
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.SYNCBUSY.bit.ENABLE);
#else
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
#endif
uint32_t toneMaxFrequency = F_CPU / 2;
uint32_t lastOutputPin = 0xFFFFFFFF;
@ -31,8 +35,13 @@ volatile int64_t toggleCount;
volatile bool toneIsActive = false;
volatile bool firstTimeRunning = false;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
#define TONE_TC TC3
#define TONE_TC_IRQn TC3_IRQn
#else
#define TONE_TC TC5
#define TONE_TC_IRQn TC5_IRQn
#endif
#define TONE_TC_TOP 0xFFFF
#define TONE_TC_CHANNEL 0
@ -66,10 +75,15 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
firstTimeRunning = true;
NVIC_SetPriority(TONE_TC_IRQn, 0);
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
MCLK->APBCMASK.bit.TC4_ = 1;
#else
// Enable GCLK for TC4 and TC5 (timer counter input clock)
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5));
while (GCLK->STATUS.bit.SYNCBUSY);
#endif
}
if (toneIsActive && (outputPin != lastOutputPin))
@ -120,7 +134,12 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
uint16_t tmpReg = 0;
tmpReg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
TONE_TC->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; // Set TONE_TC mode as match frequency
#else
tmpReg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TONE_TC mode as match frequency
#endif
tmpReg |= prescalerConfigBits;
TONE_TC->COUNT16.CTRLA.reg |= tmpReg;
WAIT_TC16_REGS_SYNC(TONE_TC)

View file

@ -39,8 +39,18 @@ public:
void reset();
// Enable
inline void enable() { usb.CTRLA.bit.ENABLE = 1; }
inline void disable() { usb.CTRLA.bit.ENABLE = 0; }
inline void enable() {
usb.CTRLA.bit.ENABLE = 1;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
while( usb.SYNCBUSY.reg & USB_SYNCBUSY_ENABLE ); //wait for sync
#endif
}
inline void disable() {
usb.CTRLA.bit.ENABLE = 0;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
while( usb.SYNCBUSY.reg & USB_SYNCBUSY_ENABLE ); //wait for sync
#endif
}
// USB mode (device/host)
inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; }

View file

@ -24,6 +24,7 @@
#else
#include "SAMD21_USBDevice.h"
#endif
#include "PluggableUSB.h"
#include <stdlib.h>
@ -37,6 +38,7 @@ USBDevice_SAMR21G18x usbd;
USBDevice_SAMD21G18x usbd;
#endif
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
#define TX_RX_LED_PULSE_MS 100
#ifdef PIN_LED_TXL
@ -300,9 +302,26 @@ void USBDeviceClass::init()
digitalWrite(PIN_LED_RXL, HIGH);
#endif
// Enable USB clock
/* Enable USB clock */
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
// 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_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
while(GCLK->SYNCBUSY.bit.GENCTRL0)
{
/* Wait for synchronization */
}
#else
PM->APBBMASK.reg |= PM_APBBMASK_USB;
// Set up the USB DP/DN pins
PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
@ -313,10 +332,11 @@ void USBDeviceClass::init()
// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
GCLK_CLKCTRL_CLKEN;
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY)
;
;
#endif
USB_SetHandler(&UDD_Handler);
@ -329,8 +349,14 @@ void USBDeviceClass::init()
usbd.setFullSpeed();
// Configure interrupts
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the correct interrupts
/* Attach to the USB host */
NVIC_SetPriority((IRQn_Type) USB_0_IRQn, 0UL);
NVIC_EnableIRQ((IRQn_Type) USB_0_IRQn);
#else
NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
#endif
usbd.enable();

View file

@ -67,7 +67,11 @@ void UHD_Init(void)
USB_SetHandler(&UHD_Handler);
/* Enable USB clock */
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
#else
PM->APBBMASK.reg |= PM_APBBMASK_USB;
#endif
/* Set up the USB DP/DM pins */
pinPeripheral( PIN_USB_DM, PIO_COM );
@ -79,9 +83,14 @@ void UHD_Init(void)
// PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
// PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
/* ----------------------------------------------------------------------------------------------
* Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
*/
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
#else
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
GCLK_CLKCTRL_CLKEN;
@ -90,6 +99,7 @@ void UHD_Init(void)
{
/* Wait for synchronization */
}
#endif
/* Reset */
USB->HOST.CTRLA.bit.SWRST = 1;
@ -103,8 +113,13 @@ void UHD_Init(void)
uhd_force_host_mode();
while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
/* Load Pad Calibration */
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the right address
pad_transn = (*((uint32_t *)(NVMCTRL_CBW4) // Non-Volatile Memory Controller
#else
pad_transn = (*((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller
#endif
+ (NVM_USB_PAD_TRANSN_POS / 32))
>> (NVM_USB_PAD_TRANSN_POS % 32))
& ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
@ -116,7 +131,11 @@ void UHD_Init(void)
USB->HOST.PADCAL.bit.TRANSN = pad_transn;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the right address
pad_transp = (*((uint32_t *)(NVMCTRL_CBW4)
#else
pad_transp = (*((uint32_t *)(NVMCTRL_OTP4)
#endif
+ (NVM_USB_PAD_TRANSP_POS / 32))
>> (NVM_USB_PAD_TRANSP_POS % 32))
& ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
@ -128,7 +147,11 @@ void UHD_Init(void)
USB->HOST.PADCAL.bit.TRANSP = pad_transp;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the right address
pad_trim = (*((uint32_t *)(NVMCTRL_CBW4)
#else
pad_trim = (*((uint32_t *)(NVMCTRL_OTP4)
#endif
+ (NVM_USB_PAD_TRIM_POS / 32))
>> (NVM_USB_PAD_TRIM_POS % 32))
& ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
@ -167,8 +190,13 @@ void UHD_Init(void)
USB->HOST.CTRLB.bit.VBUSOK = 1;
// Configure interrupts
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the right interrupts
NVIC_SetPriority((IRQn_Type)USB_0_IRQn, 0UL);
NVIC_EnableIRQ((IRQn_Type)USB_0_IRQn);
#else
NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
#endif
}

View file

@ -28,6 +28,17 @@ static void __initialize()
{
memset(callbacksInt, 0, sizeof(callbacksInt));
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__) //TODO: verify the correct interrupts
///EIC MCLK is enabled by default
NVIC_DisableIRQ(EIC_0_IRQn);
NVIC_ClearPendingIRQ(EIC_0_IRQn);
NVIC_SetPriority(EIC_0_IRQn, 0);
NVIC_EnableIRQ(EIC_0_IRQn);
GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
#else
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_SetPriority(EIC_IRQn, 0);
@ -35,6 +46,7 @@ static void __initialize()
// Enable GCLK for IEC (External Interrupt Controller)
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));
#endif
/* Shall we do that?
// Do a software reset on EIC
@ -43,8 +55,13 @@ static void __initialize()
*/
// Enable EIC
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
EIC->CTRLA.bit.ENABLE = 1;
while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
#else
EIC->CTRL.bit.ENABLE = 1;
while (EIC->STATUS.bit.SYNCBUSY == 1) { }
#endif
}
/*
@ -71,7 +88,11 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
}
// Enable wakeup capability on pin in case being used during sleep
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//TODO: find how to do
#else
EIC->WAKEUP.reg |= (1 << in);
#endif
// Assign pin to EIC
pinPeripheral(pin, PIO_EXTINT);
@ -111,8 +132,12 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break;
}
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//TODO: find how to do
#else
// Enable the interrupt
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
#endif
}
/*
@ -131,7 +156,11 @@ void detachInterrupt(uint32_t pin)
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in);
// Disable wakeup capability on pin during sleep
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//TODO: find how to do
#else
EIC->WAKEUP.reg &= ~(1 << in);
#endif
}
/*

View file

@ -34,6 +34,328 @@ void Dummy_Handler(void)
for (;;) { }
}
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
/* Cortex-M4 processor handlers */
void Reset_Handler ( void );
void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MemManage_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void BusFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UsageFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DebugMon_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SysTick_Handler ( void );
/* Peripherals handlers */
void PM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCLK_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSC32KCTRL_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SUPC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SUPC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void WDT_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_8_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_9_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_10_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_11_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_12_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_13_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_14_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_15_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void FREQM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void NVMCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void NVMCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DMAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DMAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DMAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DMAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DMAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EVSYS_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EVSYS_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EVSYS_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EVSYS_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EVSYS_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TAL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TAL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RAMECC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM3_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM4_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM5_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM5_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM5_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM5_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM6_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM6_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM6_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM6_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USB_0_Handler ( void ) __attribute__ ((weak));
void USB_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USB_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USB_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC1_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC3_Handler ( void ) __attribute__ ((weak)); //used in Tone.cpp
void TC4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PDEC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PDEC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PDEC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ADC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ADC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ADC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ADC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void I2S_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AES_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TRNG_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ICM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PUKCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void QSPI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SDHC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SDHC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
/* Initialize segments */
extern uint32_t __etext;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
extern uint32_t __StackTop;
/* Exception Table */
__attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
{
/* Configure Initial Stack Pointer, using linker-generated symbols */
(void*) (&__StackTop),
/* Cortex-M handlers */
(void*) Reset_Handler,
(void*) NMI_Handler,
(void*) HardFault_Handler,
(void*) MemManage_Handler,
(void*) BusFault_Handler,
(void*) UsageFault_Handler,
(void*) (0UL), /* Reserved */
(void*) (0UL), /* Reserved */
(void*) (0UL), /* Reserved */
(void*) (0UL), /* Reserved */
(void*) SVC_Handler,
(void*) DebugMon_Handler,
(void*) (0UL), /* Reserved */
(void*) PendSV_Handler,
(void*) SysTick_Handler,
/* Peripheral handlers */
(void*) PM_Handler, /* 0 Power Manager */
(void*) MCLK_Handler, /* 1 Main Clock */
(void*) OSCCTRL_0_Handler, /* 2 Oscillators Control IRQ 0 */
(void*) OSCCTRL_1_Handler, /* 3 Oscillators Control IRQ 1 */
(void*) OSCCTRL_2_Handler, /* 4 Oscillators Control IRQ 2 */
(void*) OSCCTRL_3_Handler, /* 5 Oscillators Control IRQ 3 */
(void*) OSCCTRL_4_Handler, /* 6 Oscillators Control IRQ 4 */
(void*) OSC32KCTRL_Handler, /* 7 32kHz Oscillators Control */
(void*) SUPC_0_Handler, /* 8 Supply Controller IRQ 0 */
(void*) SUPC_1_Handler, /* 9 Supply Controller IRQ 1 */
(void*) WDT_Handler, /* 10 Watchdog Timer */
(void*) RTC_Handler, /* 11 Real-Time Counter */
(void*) EIC_0_Handler, /* 12 External Interrupt Controller IRQ 0 */
(void*) EIC_1_Handler, /* 13 External Interrupt Controller IRQ 1 */
(void*) EIC_2_Handler, /* 14 External Interrupt Controller IRQ 2 */
(void*) EIC_3_Handler, /* 15 External Interrupt Controller IRQ 3 */
(void*) EIC_4_Handler, /* 16 External Interrupt Controller IRQ 4 */
(void*) EIC_5_Handler, /* 17 External Interrupt Controller IRQ 5 */
(void*) EIC_6_Handler, /* 18 External Interrupt Controller IRQ 6 */
(void*) EIC_7_Handler, /* 19 External Interrupt Controller IRQ 7 */
(void*) EIC_8_Handler, /* 20 External Interrupt Controller IRQ 8 */
(void*) EIC_9_Handler, /* 21 External Interrupt Controller IRQ 9 */
(void*) EIC_10_Handler, /* 22 External Interrupt Controller IRQ 10 */
(void*) EIC_11_Handler, /* 23 External Interrupt Controller IRQ 11 */
(void*) EIC_12_Handler, /* 24 External Interrupt Controller IRQ 12 */
(void*) EIC_13_Handler, /* 25 External Interrupt Controller IRQ 13 */
(void*) EIC_14_Handler, /* 26 External Interrupt Controller IRQ 14 */
(void*) EIC_15_Handler, /* 27 External Interrupt Controller IRQ 15 */
(void*) FREQM_Handler, /* 28 Frequency Meter */
(void*) NVMCTRL_0_Handler, /* 29 Non-Volatile Memory Controller IRQ 0 */
(void*) NVMCTRL_1_Handler, /* 30 Non-Volatile Memory Controller IRQ 1 */
(void*) DMAC_0_Handler, /* 31 Direct Memory Access Controller IRQ 0 */
(void*) DMAC_1_Handler, /* 32 Direct Memory Access Controller IRQ 1 */
(void*) DMAC_2_Handler, /* 33 Direct Memory Access Controller IRQ 2 */
(void*) DMAC_3_Handler, /* 34 Direct Memory Access Controller IRQ 3 */
(void*) DMAC_4_Handler, /* 35 Direct Memory Access Controller IRQ 4 */
(void*) EVSYS_0_Handler, /* 36 Event System Interface IRQ 0 */
(void*) EVSYS_1_Handler, /* 37 Event System Interface IRQ 1 */
(void*) EVSYS_2_Handler, /* 38 Event System Interface IRQ 2 */
(void*) EVSYS_3_Handler, /* 39 Event System Interface IRQ 3 */
(void*) EVSYS_4_Handler, /* 40 Event System Interface IRQ 4 */
(void*) PAC_Handler, /* 41 Peripheral Access Controller */
(void*) TAL_0_Handler, /* 42 Trigger Allocator IRQ 0 */
(void*) TAL_1_Handler, /* 43 Trigger Allocator IRQ 1 */
(void*) (0UL),
(void*) RAMECC_Handler, /* 45 RAM ECC */
(void*) SERCOM0_0_Handler, /* 46 Serial Communication Interface 0 IRQ 0 */
(void*) SERCOM0_1_Handler, /* 47 Serial Communication Interface 0 IRQ 1 */
(void*) SERCOM0_2_Handler, /* 48 Serial Communication Interface 0 IRQ 2 */
(void*) SERCOM0_3_Handler, /* 49 Serial Communication Interface 0 IRQ 3 */
(void*) SERCOM1_0_Handler, /* 50 Serial Communication Interface 1 IRQ 0 */
(void*) SERCOM1_1_Handler, /* 51 Serial Communication Interface 1 IRQ 1 */
(void*) SERCOM1_2_Handler, /* 52 Serial Communication Interface 1 IRQ 2 */
(void*) SERCOM1_3_Handler, /* 53 Serial Communication Interface 1 IRQ 3 */
(void*) SERCOM2_0_Handler, /* 54 Serial Communication Interface 2 IRQ 0 */
(void*) SERCOM2_1_Handler, /* 55 Serial Communication Interface 2 IRQ 1 */
(void*) SERCOM2_2_Handler, /* 56 Serial Communication Interface 2 IRQ 2 */
(void*) SERCOM2_3_Handler, /* 57 Serial Communication Interface 2 IRQ 3 */
(void*) SERCOM3_0_Handler, /* 58 Serial Communication Interface 3 IRQ 0 */
(void*) SERCOM3_1_Handler, /* 59 Serial Communication Interface 3 IRQ 1 */
(void*) SERCOM3_2_Handler, /* 60 Serial Communication Interface 3 IRQ 2 */
(void*) SERCOM3_3_Handler, /* 61 Serial Communication Interface 3 IRQ 3 */
(void*) SERCOM4_0_Handler, /* 62 Serial Communication Interface 4 IRQ 0 */
(void*) SERCOM4_1_Handler, /* 63 Serial Communication Interface 4 IRQ 1 */
(void*) SERCOM4_2_Handler, /* 64 Serial Communication Interface 4 IRQ 2 */
(void*) SERCOM4_3_Handler, /* 65 Serial Communication Interface 4 IRQ 3 */
(void*) SERCOM5_0_Handler, /* 66 Serial Communication Interface 5 IRQ 0 */
(void*) SERCOM5_1_Handler, /* 67 Serial Communication Interface 5 IRQ 1 */
(void*) SERCOM5_2_Handler, /* 68 Serial Communication Interface 5 IRQ 2 */
(void*) SERCOM5_3_Handler, /* 69 Serial Communication Interface 5 IRQ 3 */
(void*) SERCOM6_0_Handler, /* 70 Serial Communication Interface 6 IRQ 0 */
(void*) SERCOM6_1_Handler, /* 71 Serial Communication Interface 6 IRQ 1 */
(void*) SERCOM6_2_Handler, /* 72 Serial Communication Interface 6 IRQ 2 */
(void*) SERCOM6_3_Handler, /* 73 Serial Communication Interface 6 IRQ 3 */
(void*) SERCOM7_0_Handler, /* 74 Serial Communication Interface 7 IRQ 0 */
(void*) SERCOM7_1_Handler, /* 75 Serial Communication Interface 7 IRQ 1 */
(void*) SERCOM7_2_Handler, /* 76 Serial Communication Interface 7 IRQ 2 */
(void*) SERCOM7_3_Handler, /* 77 Serial Communication Interface 7 IRQ 3 */
(void*) (0UL),
(void*) (0UL),
(void*) USB_0_Handler, /* 80 Universal Serial Bus IRQ 0 */
(void*) USB_1_Handler, /* 81 Universal Serial Bus IRQ 1 */
(void*) USB_2_Handler, /* 82 Universal Serial Bus IRQ 2 */
(void*) USB_3_Handler, /* 83 Universal Serial Bus IRQ 3 */
(void*) (0UL),
(void*) TCC0_0_Handler, /* 85 Timer Counter Control 0 IRQ 0 */
(void*) TCC0_1_Handler, /* 86 Timer Counter Control 0 IRQ 1 */
(void*) TCC0_2_Handler, /* 87 Timer Counter Control 0 IRQ 2 */
(void*) TCC0_3_Handler, /* 88 Timer Counter Control 0 IRQ 3 */
(void*) TCC0_4_Handler, /* 89 Timer Counter Control 0 IRQ 4 */
(void*) TCC0_5_Handler, /* 90 Timer Counter Control 0 IRQ 5 */
(void*) TCC0_6_Handler, /* 91 Timer Counter Control 0 IRQ 6 */
(void*) TCC1_0_Handler, /* 92 Timer Counter Control 1 IRQ 0 */
(void*) TCC1_1_Handler, /* 93 Timer Counter Control 1 IRQ 1 */
(void*) TCC1_2_Handler, /* 94 Timer Counter Control 1 IRQ 2 */
(void*) TCC1_3_Handler, /* 95 Timer Counter Control 1 IRQ 3 */
(void*) TCC1_4_Handler, /* 96 Timer Counter Control 1 IRQ 4 */
(void*) TCC2_0_Handler, /* 97 Timer Counter Control 2 IRQ 0 */
(void*) TCC2_1_Handler, /* 98 Timer Counter Control 2 IRQ 1 */
(void*) TCC2_2_Handler, /* 99 Timer Counter Control 2 IRQ 2 */
(void*) TCC2_3_Handler, /* 100 Timer Counter Control 2 IRQ 3 */
(void*) TCC3_0_Handler, /* 101 Timer Counter Control 3 IRQ 0 */
(void*) TCC3_1_Handler, /* 102 Timer Counter Control 3 IRQ 1 */
(void*) TCC3_2_Handler, /* 103 Timer Counter Control 3 IRQ 2 */
(void*) TCC4_0_Handler, /* 104 Timer Counter Control 4 IRQ 0 */
(void*) TCC4_1_Handler, /* 105 Timer Counter Control 4 IRQ 1 */
(void*) TCC4_2_Handler, /* 106 Timer Counter Control 4 IRQ 2 */
(void*) TC0_Handler, /* 107 Basic Timer Counter 0 */
(void*) TC1_Handler, /* 108 Basic Timer Counter 1 */
(void*) TC2_Handler, /* 109 Basic Timer Counter 2 */
(void*) TC3_Handler, /* 110 Basic Timer Counter 3 */
(void*) TC4_Handler, /* 111 Basic Timer Counter 4 */
(void*) TC5_Handler, /* 112 Basic Timer Counter 5 */
(void*) TC6_Handler, /* 113 Basic Timer Counter 6 */
(void*) TC7_Handler, /* 114 Basic Timer Counter 7 */
(void*) PDEC_0_Handler, /* 115 Quadrature Decodeur IRQ 0 */
(void*) PDEC_1_Handler, /* 116 Quadrature Decodeur IRQ 1 */
(void*) PDEC_2_Handler, /* 117 Quadrature Decodeur IRQ 2 */
(void*) ADC0_0_Handler, /* 118 Analog Digital Converter 0 IRQ 0 */
(void*) ADC0_1_Handler, /* 119 Analog Digital Converter 0 IRQ 1 */
(void*) ADC1_0_Handler, /* 120 Analog Digital Converter 1 IRQ 0 */
(void*) ADC1_1_Handler, /* 121 Analog Digital Converter 1 IRQ 1 */
(void*) AC_Handler, /* 122 Analog Comparators */
(void*) DAC_0_Handler, /* 123 Digital-to-Analog Converter IRQ 0 */
(void*) DAC_1_Handler, /* 124 Digital-to-Analog Converter IRQ 1 */
(void*) DAC_2_Handler, /* 125 Digital-to-Analog Converter IRQ 2 */
(void*) DAC_3_Handler, /* 126 Digital-to-Analog Converter IRQ 3 */
(void*) DAC_4_Handler, /* 127 Digital-to-Analog Converter IRQ 4 */
(void*) I2S_Handler, /* 128 Inter-IC Sound Interface */
(void*) PCC_Handler, /* 129 Parallel Capture Controller */
(void*) AES_Handler, /* 130 Advanced Encryption Standard */
(void*) TRNG_Handler, /* 131 True Random Generator */
(void*) ICM_Handler, /* 132 Integrity Check Monitor */
(void*) PUKCC_Handler, /* 133 PUblic-Key Cryptography Controller */
(void*) QSPI_Handler, /* 134 Quad SPI interface */
(void*) SDHC0_Handler, /* 135 SD/MMC Host Controller 0 */
(void*) SDHC1_Handler, /* 136 SD/MMC Host Controller 1 */
};
#else
/* Cortex-M0+ core handlers */
void HardFault_Handler(void) __attribute__ ((weak, alias("Dummy_Handler")));
void Reset_Handler (void);
@ -134,6 +456,8 @@ __attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
(void*) (0UL), /* Reserved */
};
#endif
extern int main(void);
/* This is called on processor reset to initialize the device and call main() */
@ -176,11 +500,19 @@ void SysTick_Handler(void)
static void (*usb_isr)(void) = NULL;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
void USB_0_Handler(void)
{
if (usb_isr)
usb_isr();
}
#else
void USB_Handler(void)
{
if (usb_isr)
usb_isr();
}
#endif
void USB_SetHandler(void (*new_usb_isr)(void))
{

View file

@ -37,24 +37,37 @@
*/
// Constants for Clock generators
#define GENERIC_CLOCK_GENERATOR_MAIN (0u)
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
#define GENERIC_CLOCK_GENERATOR_XOSC32K (3u)
#else
#define GENERIC_CLOCK_GENERATOR_XOSC32K (1u)
#endif
#define GENERIC_CLOCK_GENERATOR_OSC32K (1u)
#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */
#define GENERIC_CLOCK_GENERATOR_OSC8M (3u)
// Constants for Clock multiplexers
#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u)
//#define USE_PLL
void SystemInit( void )
{
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_RWS(0);
#else
/* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;
/* Turn on the digital interface clock */
PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
#if defined(CRYSTALLESS)
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//TODO:
#else
/* ----------------------------------------------------------------------------------------------
* 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
*/
@ -67,24 +80,110 @@ void SystemInit( void )
SYSCTRL_OSC32K_ENABLE;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY) == 0 ); // Wait for oscillator stabilization
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
#else // has crystal
/* ----------------------------------------------------------------------------------------------
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
*/
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
/* ----------------------------------------------------------------------------------------------
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
*/
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
{
/* Wait for oscillator stabilization */
}
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
#endif
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_CGM_XT | OSC32KCTRL_XOSC32K_XTALEN;
while( (OSC32KCTRL->STATUS.reg & OSC32KCTRL_STATUS_XOSC32KRDY) == 0 ){
/* Wait for oscillator to be ready */
}
#else
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
{
/* Wait for oscillator stabilization */
}
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
#endif //CRYSTALLESS
/* Software reset the module to ensure it is re-initialized correctly */
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
GCLK->CTRLA.bit.SWRST = 1;
while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_SWRST ){
/* wait for reset to complete */
}
#ifdef USE_PLL
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(1499); //120 Mhz
while(OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.DPLLRATIO);
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_XOSC32;
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
while( OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 0 || OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK == 0 );
#else
/* ----------------------------------------------------------------------------------------------
* 2) Put XOSC32K as source of Generic Clock Generator 3
*/
GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_XOSC32K].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_XOSC32K) | //generic clock gen 3
GCLK_GENCTRL_GENEN;
while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL3 ){
/* Wait for synchronization */
}
/* ----------------------------------------------------------------------------------------------
* 3) Put Generic Clock Generator 3 as source for Generic Clock Gen 0 (DFLL48M reference)
*/
GCLK->GENCTRL[GENERIC_CLOCK_MULTIPLEXER_DFLL48M].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) | GCLK_GENCTRL_GENEN;
while ( GCLK->SYNCBUSY.bit.GENCTRL0 ){
/* Wait for synchronization */
}
/* ----------------------------------------------------------------------------------------------
* 4) Enable DFLL48M clock
*/
/* DFLL Configuration in Closed Loop mode - Closed-Loop Operation */
OSCCTRL->DFLLCTRLA.reg = 0;
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK3_Val);
OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
OSCCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
OSCCTRL_DFLLMUL_MUL( (VARIANT_MCK/VARIANT_MAINOSC) ); // External 32KHz is the reference
while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLMUL )
{
/* Wait for synchronization */
}
OSCCTRL->DFLLCTRLB.reg = 0;
while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLCTRLB )
{
/* Wait for synchronization */
}
OSCCTRL->DFLLCTRLA.reg |= OSCCTRL_DFLLCTRLA_ENABLE;
while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_ENABLE )
{
/* Wait for synchronization */
}
#endif //USE_PLL
#else
/* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
* CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
*/
@ -107,13 +206,13 @@ void SystemInit( void )
/* Write Generic Clock Generator 1 configuration */
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
#if defined(CRYSTALLESS)
GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
#else
GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
#endif
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
GCLK_GENCTRL_GENEN ;
#if defined(CRYSTALLESS)
GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
#else
GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
#endif
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
GCLK_GENCTRL_GENEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
@ -131,7 +230,6 @@ void SystemInit( void )
{
/* Wait for synchronization */
}
/* ----------------------------------------------------------------------------------------------
* 4) Enable DFLL48M clock
*/
@ -139,7 +237,7 @@ void SystemInit( void )
/* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */
/* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0 ;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
@ -154,10 +252,17 @@ void SystemInit( void )
{
/* Wait for synchronization */
}
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
#if defined(CRYSTALLESS)
#define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
#define NVM_SW_CALIB_DFLL48M_FINE_VAL 64
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
//TODO:
#else
// Turn on DFLL
uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32) )
@ -165,41 +270,17 @@ void SystemInit( void )
if (coarse == 0x3f) {
coarse = 0x1f;
}
// TODO(tannewt): Load this value from memory we've written previously. There
// isn't a value from the Atmel factory.
uint32_t fine = 0x1ff;
uint32_t fine =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32) )
& ((1 << 10) - 1);
if (fine == 0x3ff) {
fine = 0x1ff;
}
SYSCTRL->DFLLVAL.bit.COARSE = coarse;
SYSCTRL->DFLLVAL.bit.FINE = fine;
/* Write full configuration to DFLL control register */
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 0x1f / 4 ) | // Coarse step is 31, half of the max value
SYSCTRL_DFLLMUL_FSTEP( 10 ) |
SYSCTRL_DFLLMUL_MUL( (48000) ) ;
SYSCTRL->DFLLCTRL.reg = 0;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
/* Wait for synchronization */
}
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_MODE |
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
SYSCTRL_DFLLCTRL_CCDIS |
SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
SYSCTRL_DFLLCTRL_BPLCKC;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
/* Wait for synchronization */
}
/* Enable the DFLL */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
#else // has crystal
/* Write full configuration to DFLL control register */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
SYSCTRL_DFLLCTRL_WAITLOCK |
SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
@ -210,15 +291,80 @@ void SystemInit( void )
/* Enable the DFLL */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
#else // has crystal
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
OSCCTRL->DFLLCTRLB.reg |= OSCCTRL_DFLLCTRLB_MODE |
OSCCTRL_DFLLCTRLB_WAITLOCK |
OSCCTRL_DFLLCTRLB_QLDIS;
#else
/* Write full configuration to DFLL control register */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
SYSCTRL_DFLLCTRL_WAITLOCK |
SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
/* Wait for synchronization */
}
/* Enable the DFLL */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
{
/* Wait for locks flags */
}
#endif //(__SAMD51P20A__ || __SAMD51G19A__)
#endif //crystalless
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
#ifdef USE_PLL
/* ----------------------------------------------------------------------------------------------
* 5) Switch Generic Clock Generator 0 to DPLL0. CPU will run at 120MHz.
*/
GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_MAIN].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DPLL0) |
GCLK_GENCTRL_IDC |
//GCLK_GENCTRL_OE |
GCLK_GENCTRL_GENEN;
#else
while ( (OSCCTRL->STATUS.reg & (OSCCTRL_STATUS_DFLLRDY | OSCCTRL_STATUS_DFLLLCKC)) != (OSCCTRL_STATUS_DFLLRDY | OSCCTRL_STATUS_DFLLLCKC) )
{
/* Wait for locks flags */
/* Wait for synchronization */
}
#endif
/* ----------------------------------------------------------------------------------------------
* 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
*/
GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_MAIN].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) |
GCLK_GENCTRL_IDC |
//GCLK_GENCTRL_OE |
GCLK_GENCTRL_GENEN;
#endif
while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0 )
{
/* Wait for synchronization */
}
//TODO: steps 6, 7, 8
MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
#else
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
/* Wait for synchronization */
@ -245,7 +391,7 @@ void SystemInit( void )
{
/* Wait for synchronization */
}
/* ----------------------------------------------------------------------------------------------
* 6) Modify PRESCaler value of OSC8M to have 8MHz
*/
@ -298,4 +444,6 @@ void SystemInit( void )
* 9) Disable automatic NVM write operations
*/
NVMCTRL->CTRLB.bit.MANW = 1;
#endif
}

View file

@ -22,11 +22,16 @@
extern "C" {
#endif
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
uint32_t SystemCoreClock=48000000ul ;
#else
/*
* System Core Clock is at 1MHz (8MHz/8) at Reset.
* It is switched to 48MHz in the Reset Handler (startup.c)
*/
uint32_t SystemCoreClock=1000000ul ;
#endif
/*
void calibrateADC()
@ -71,6 +76,15 @@ void init( void )
// // Clock EIC for I/O interrupts
// PM->APBAMASK.reg |= PM_APBAMASK_EIC ;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0 | MCLK_APBAMASK_SERCOM1;
MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2 | MCLK_APBBMASK_SERCOM3 | MCLK_APBBMASK_TCC0 | MCLK_APBBMASK_TCC1;
MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC2 | MCLK_APBCMASK_TC4 | MCLK_APBCMASK_TC5;
MCLK->APBDMASK.reg |= MCLK_APBDMASK_DAC | MCLK_APBDMASK_SERCOM4 | MCLK_APBDMASK_SERCOM5 | MCLK_APBDMASK_ADC0 | MCLK_APBDMASK_ADC1;
#else
// Clock SERCOM for Serial
PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ;
@ -78,9 +92,10 @@ void init( void )
PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ;
// ATSAMR, for example, doesn't have a DAC
#ifdef PM_APBCMASK_DAC
// Clock ADC/DAC for Analog
PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ;
#ifdef PM_APBCMASK_DAC
// Clock ADC/DAC for Analog
PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ;
#endif
#endif
// Setup all pins (digital and analog) in INPUT mode (default is nothing)
@ -91,6 +106,39 @@ void init( void )
// Initialize Analog Controller
// Setting clock
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
GCLK->PCHCTRL[ADC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 0
ADC0->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV256_Val;
ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB ); //wait for sync
ADC0->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_SAMPCTRL ); //wait for sync
ADC0->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground)
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL ); //wait for sync
// Averaging (see datasheet table in AVGCTRL register description)
ADC0->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // 1 sample only (no oversampling nor averaging)
ADC_AVGCTRL_ADJRES(0x0ul); // Adjusting result by 0
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_AVGCTRL ); //wait for sync
analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v)
GCLK->PCHCTRL[DAC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 0
while (GCLK->PCHCTRL[DAC_GCLK_ID].bit.CHEN == 0);
while ( DAC->SYNCBUSY.bit.SWRST == 1 ); // Wait for synchronization of registers between the clock domains
DAC->CTRLB.reg = DAC_CTRLB_REFSEL_VDDANA; //Use Analog supply
//TODO: enable external output?
#else
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
@ -122,12 +170,12 @@ void init( void )
GCLK_CLKCTRL_CLKEN ;
// ATSAMR, for example, doesn't have a DAC
#ifdef DAC
#ifdef DAC
while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
DAC_CTRLB_EOEN ; // External Output Enable (Vout)
#endif
#endif
}
#ifdef __cplusplus

View file

@ -27,6 +27,7 @@ static int _readResolution = 10;
static int _ADCResolution = 10;
static int _writeResolution = 8;
#if !defined(__SAMD51P20A__) && !defined(__SAMD51G19A__)
// Wait for synchronization of registers between the clock domains
static __inline__ void syncADC() __attribute__((always_inline, unused));
static void syncADC() {
@ -56,20 +57,41 @@ static void syncTCC(Tcc* TCCx) {
while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK);
}
#endif
void analogReadResolution(int res)
{
_readResolution = res;
if (res > 10) {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
_ADCResolution = 12;
} else if (res > 8) {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
_ADCResolution = 10;
} else {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
_ADCResolution = 8;
}
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
if (res > 10) {
ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
_ADCResolution = 12;
} else if (res > 8) {
ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
_ADCResolution = 10;
} else {
ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
_ADCResolution = 8;
}
while(ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB); //wait for sync
#else
if (res > 10) {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
_ADCResolution = 12;
} else if (res > 8) {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
_ADCResolution = 10;
} else {
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
_ADCResolution = 8;
}
syncADC();
#endif
}
void analogWriteResolution(int res)
@ -96,6 +118,43 @@ static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
*/
void analogReference(eAnalogReference mode)
{
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
while(ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_REFCTRL); //wait for sync
//TODO: fix gains
switch (mode)
{
case AR_INTERNAL:
case AR_INTERNAL2V23:
//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR(); // Gain Factor Selection
ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/1.48 VDDANA = 1/1.48* 3V3 = 2.2297
break;
case AR_EXTERNAL:
//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
break;
/* Don't think this works on SAMD51
case AR_INTERNAL1V0:
//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; // 1.0V voltage reference
break;
*/
case AR_INTERNAL1V65:
//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection
ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
break;
case AR_DEFAULT:
default:
//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
break;
}
#else
syncADC();
switch (mode)
{
@ -126,6 +185,7 @@ void analogReference(eAnalogReference mode)
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
break;
}
#endif
}
uint32_t analogRead(uint32_t pin)
@ -135,26 +195,78 @@ uint32_t analogRead(uint32_t pin)
if (pin == 6) {
pin = PIN_A6;
} else if (pin == 7) {
pin = PIN_A7;
pin = PIN_A7;
} else if (pin <= 5) {
pin += A0;
pin += A0;
}
//TODO: disable only the necessary DAC
pinPeripheral(pin, PIO_ANALOG);
// ATSAMR, for example, doesn't have a DAC
//ATSAMR, for example, doesn't have a DAC
#ifdef DAC
if (pin == A0) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
syncDAC();
DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
//DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
syncDAC();
}
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
if (pin == A0 || pin == A4) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
while (DAC->SYNCBUSY.bit.ENABLE);
#else
if (pin == A0) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
syncDAC();
#endif
DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
//DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
while (DAC->SYNCBUSY.bit.ENABLE);
#else
syncDAC();
#endif
}
#endif
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL ); //wait for sync
ADC0->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input
// Control A
/*
* Bit 1 ENABLE: Enable
* 0: The ADC is disabled.
* 1: The ADC is enabled.
* Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The
* value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register
* (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete.
*
* Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be
* configured. The first conversion after the reference is changed must not be used.
*/
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
ADC0->CTRLA.bit.ENABLE = 0x01; // Enable ADC
// Start conversion
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
ADC0->SWTRIG.bit.START = 1;
// Clear the Data Ready flag
ADC0->INTFLAG.reg = ADC_INTFLAG_RESRDY;
// Start conversion again, since The first conversion after the reference is changed must not be used.
ADC0->SWTRIG.bit.START = 1;
// Store the value
while (ADC0->INTFLAG.bit.RESRDY == 0); // Waiting for conversion to complete
valueRead = ADC0->RESULT.reg;
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
ADC0->CTRLA.bit.ENABLE = 0x00; // Disable ADC
while( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
#else
syncADC();
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input
// Control A
/*
* Bit 1 ENABLE: Enable
@ -188,6 +300,7 @@ uint32_t analogRead(uint32_t pin)
syncADC();
ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC
syncADC();
#endif
return mapResolution(valueRead, _ADCResolution, _readResolution);
}
@ -197,7 +310,6 @@ uint32_t analogRead(uint32_t pin)
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(uint32_t pin, uint32_t value)
{
PinDescription pinDesc = g_APinDescription[pin];
@ -205,24 +317,52 @@ void analogWrite(uint32_t pin, uint32_t value)
// ATSAMR, for example, doesn't have a DAC
#ifdef DAC
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
{
// DAC handling code
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
{
// DAC handling code
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
if (pin != PIN_A0 && pin != PIN_A4) { // 2 DACs on A0 (PA02) and A4 (PA05)
#else
if (pin != PIN_A0) { // Only 1 DAC on A0 (PA02)
#endif
return;
}
if (pin != PIN_A0) { // Only 1 DAC on A0 (PA02)
return;
}
value = mapResolution(value, _writeResolution, 10);
value = mapResolution(value, _writeResolution, 10);
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
syncDAC();
DAC->DATA.reg = value & 0x3FF; // DAC on 10 bits.
syncDAC();
DAC->CTRLA.bit.ENABLE = 0x01; // Enable DAC
syncDAC();
return;
}
while (DAC->SYNCBUSY.bit.ENABLE);
DAC->CTRLA.bit.ENABLE = 1; // Enable DAC
while (DAC->SYNCBUSY.bit.ENABLE);
if(pin == PIN_A0){
DAC->DACCTRL[0].bit.ENABLE = 1;
while (!(DAC->STATUS.reg & DAC_STATUS_READY0));
DAC->DATA[0].reg = value & 0x3FF; // DAC on 10 bits.
while (DAC->SYNCBUSY.bit.DATA0);
}
else if(pin == PIN_A4){
DAC->DACCTRL[1].bit.ENABLE = 1;
while (!(DAC->STATUS.reg & DAC_STATUS_READY1));
DAC->DATA[1].reg = value & 0x3FF; // DAC on 10 bits.
while (DAC->SYNCBUSY.bit.DATA1);
}
#else
syncDAC();
DAC->DATA.reg = value & 0x3FF; // DAC on 10 bits.
syncDAC();
DAC->CTRLA.bit.ENABLE = 0x01; // Enable DAC
syncDAC();
#endif
return;
}
#endif
if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM)
{
value = mapResolution(value, _writeResolution, 8);
@ -249,6 +389,76 @@ void analogWrite(uint32_t pin, uint32_t value)
if (!tcEnabled[tcNum]) {
tcEnabled[tcNum] = true;
#if defined(__SAMD51P20A__) || defined(__SAMD51G19A__)
uint32_t GCLK_CLKCTRL_IDs[] = {
TCC0_GCLK_ID,
TCC1_GCLK_ID,
TCC2_GCLK_ID,
TC3_GCLK_ID
};
GCLK->PCHCTRL[GCLK_CLKCTRL_IDs[tcNum]].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 0
// Set PORT
if (tcNum >= TCC_INST_NUM) {
// -- Configure TC
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 0;
while (TCx->COUNT8.SYNCBUSY.bit.ENABLE);
// Set Timer counter Mode to 8 bits, normal PWM, prescaler 1/256
TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV256;
TCx->COUNT8.WAVE.reg = TC_WAVE_WAVEGEN_NPWM;
while (TCx->COUNT8.SYNCBUSY.bit.CC0 || TCx->COUNT8.SYNCBUSY.bit.CC1);
// Set the initial value
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
while (TCx->COUNT8.SYNCBUSY.bit.CC0 || TCx->COUNT8.SYNCBUSY.bit.CC1);
// Set PER to maximum counter value (resolution : 0xFF)
TCx->COUNT8.PER.reg = 0xFF;
while (TCx->COUNT8.SYNCBUSY.bit.PER);
// Enable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 1;
while (TCx->COUNT8.SYNCBUSY.bit.ENABLE);
} else {
// -- Configure TCC
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCCx
TCCx->CTRLA.bit.ENABLE = 0;
while (TCCx->SYNCBUSY.bit.ENABLE);
// Set prescaler to 1/256
TCCx->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV256;
// Set TCx as normal PWM
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
// Set the initial value
TCCx->CC[tcChannel].reg = (uint32_t) value;
while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
// Set PER to maximum counter value (resolution : 0xFF)
TCCx->PER.reg = 0xFF;
while (TCCx->SYNCBUSY.bit.PER);
// Enable TCCx
TCCx->CTRLA.bit.ENABLE = 1;
while (TCCx->SYNCBUSY.bit.ENABLE);
}
} else {
if (tcNum >= TCC_INST_NUM) {
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
while (TCx->COUNT8.SYNCBUSY.bit.CC0 || TCx->COUNT8.SYNCBUSY.bit.CC1);
} else {
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
while (TCCx->SYNCBUSY.bit.CTRLB);
while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
TCCx->CCBUF[tcChannel].reg = (uint32_t) value;
while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
TCCx->CTRLBCLR.bit.LUPD = 1;
while (TCCx->SYNCBUSY.bit.CTRLB);
}
}
#else
uint16_t GCLK_CLKCTRL_IDs[] = {
GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0
GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1
@ -261,63 +471,66 @@ void analogWrite(uint32_t pin, uint32_t value)
};
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]);
while (GCLK->STATUS.bit.SYNCBUSY == 1);
// Set PORT
if (tcNum >= TCC_INST_NUM) {
// -- Configure TC
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 0;
syncTC_8(TCx);
// Set Timer counter Mode to 8 bits, normal PWM, prescaler 1/256
TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM | TC_CTRLA_PRESCALER_DIV256;
syncTC_8(TCx);
// Set the initial value
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
syncTC_8(TCx);
// Set PER to maximum counter value (resolution : 0xFF)
TCx->COUNT8.PER.reg = 0xFF;
syncTC_8(TCx);
// Enable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 1;
syncTC_8(TCx);
} else {
// -- Configure TCC
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCCx
TCCx->CTRLA.bit.ENABLE = 0;
syncTCC(TCCx);
// Set prescaler to 1/256
TCCx->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV256;
syncTCC(TCCx);
// Set TCx as normal PWM
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
syncTCC(TCCx);
// Set the initial value
TCCx->CC[tcChannel].reg = (uint32_t) value;
syncTCC(TCCx);
// Set PER to maximum counter value (resolution : 0xFF)
TCCx->PER.reg = 0xFF;
syncTCC(TCCx);
// Enable TCCx
TCCx->CTRLA.bit.ENABLE = 1;
syncTCC(TCCx);
}
} else {
if (tcNum >= TCC_INST_NUM) {
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
syncTC_8(TCx);
} else {
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
TCCx->CTRLBSET.bit.LUPD = 1;
syncTCC(TCCx);
TCCx->CCB[tcChannel].reg = (uint32_t) value;
syncTCC(TCCx);
TCCx->CTRLBCLR.bit.LUPD = 1;
syncTCC(TCCx);
}
}
#endif
// Set PORT
if (tcNum >= TCC_INST_NUM) {
// -- Configure TC
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 0;
syncTC_8(TCx);
// Set Timer counter Mode to 8 bits, normal PWM, prescaler 1/256
TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM | TC_CTRLA_PRESCALER_DIV256;
syncTC_8(TCx);
// Set the initial value
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
syncTC_8(TCx);
// Set PER to maximum counter value (resolution : 0xFF)
TCx->COUNT8.PER.reg = 0xFF;
syncTC_8(TCx);
// Enable TCx
TCx->COUNT8.CTRLA.bit.ENABLE = 1;
syncTC_8(TCx);
} else {
// -- Configure TCC
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
// Disable TCCx
TCCx->CTRLA.bit.ENABLE = 0;
syncTCC(TCCx);
// Set prescaler to 1/256
TCCx->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV256;
syncTCC(TCCx);
// Set TCx as normal PWM
TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
syncTCC(TCCx);
// Set the initial value
TCCx->CC[tcChannel].reg = (uint32_t) value;
syncTCC(TCCx);
// Set PER to maximum counter value (resolution : 0xFF)
TCCx->PER.reg = 0xFF;
syncTCC(TCCx);
// Enable TCCx
TCCx->CTRLA.bit.ENABLE = 1;
syncTCC(TCCx);
}
} else {
if (tcNum >= TCC_INST_NUM) {
Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
syncTC_8(TCx);
} else {
Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
TCCx->CTRLBSET.bit.LUPD = 1;
syncTCC(TCCx);
TCCx->CCB[tcChannel].reg = (uint32_t) value;
syncTCC(TCCx);
TCCx->CTRLBCLR.bit.LUPD = 1;
syncTCC(TCCx);
}
}
return;
}

View file

@ -19,7 +19,7 @@
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=Adafruit SAMD (32-bits ARM Cortex-M0+) Boards
name=Adafruit SAMD (32-bits ARM Cortex-M0+ and Cortex-M4) Boards
version=1.0.18
# Compile variables

Binary file not shown.