DM: added samd51 support
This commit is contained in:
parent
99001c0099
commit
37b9881cbe
15 changed files with 1153 additions and 166 deletions
39
boards.txt
39
boards.txt
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
tools/bossac.exe
BIN
tools/bossac.exe
Binary file not shown.
Loading…
Reference in a new issue