Merge upstream changes from Marlin 2.1.1

This commit is contained in:
Stefan Kalscheuer
2022-09-03 09:23:32 +02:00
parent 626283aadb
commit 986e416c7f
1610 changed files with 73839 additions and 40857 deletions

View File

@@ -42,10 +42,6 @@
#endif
#endif
// ------------------------
// Local defines
// ------------------------
#define GET_TEMP_0_ADC() TERN(HAS_TEMP_ADC_0, PIN_TO_ADC(TEMP_0_PIN), -1)
#define GET_TEMP_1_ADC() TERN(HAS_TEMP_ADC_1, PIN_TO_ADC(TEMP_1_PIN), -1)
#define GET_TEMP_2_ADC() TERN(HAS_TEMP_ADC_2, PIN_TO_ADC(TEMP_2_PIN), -1)
@@ -54,22 +50,28 @@
#define GET_TEMP_5_ADC() TERN(HAS_TEMP_ADC_5, PIN_TO_ADC(TEMP_5_PIN), -1)
#define GET_TEMP_6_ADC() TERN(HAS_TEMP_ADC_6, PIN_TO_ADC(TEMP_6_PIN), -1)
#define GET_TEMP_7_ADC() TERN(HAS_TEMP_ADC_7, PIN_TO_ADC(TEMP_7_PIN), -1)
#define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
#define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
#define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
#define GET_PROBE_ADC() TERN(HAS_TEMP_ADC_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
#define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
#define GET_BOARD_ADC() TERN(HAS_TEMP_ADC_BOARD, PIN_TO_ADC(TEMP_BOARD_PIN), -1)
#define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
#define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
#define GET_JOY_ADC_X() TERN(HAS_JOY_ADC_X, PIN_TO_ADC(JOY_X_PIN), -1)
#define GET_JOY_ADC_Y() TERN(HAS_JOY_ADC_Y, PIN_TO_ADC(JOY_Y_PIN), -1)
#define GET_JOY_ADC_Z() TERN(HAS_JOY_ADC_Z, PIN_TO_ADC(JOY_Z_PIN), -1)
#define IS_ADC_REQUIRED(n) ( \
GET_TEMP_0_ADC() == n || GET_TEMP_1_ADC() == n || GET_TEMP_2_ADC() == n || GET_TEMP_3_ADC() == n \
|| GET_TEMP_4_ADC() == n || GET_TEMP_5_ADC() == n || GET_TEMP_6_ADC() == n || GET_TEMP_7_ADC() == n \
|| GET_PROBE_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_COOLER_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_PROBE_ADC() == n \
|| GET_COOLER_ADC() == n \
|| GET_BOARD_ADC() == n \
|| GET_FILAMENT_WIDTH_ADC() == n \
|| GET_BUTTONS_ADC() == n \
|| GET_BUTTONS_ADC() == n \
|| GET_JOY_ADC_X() == n || GET_JOY_ADC_Y() == n || GET_JOY_ADC_Z() == n \
)
#if IS_ADC_REQUIRED(0)
@@ -89,6 +91,152 @@
#define DMA_IS_REQUIRED 1
#endif
enum ADCIndex {
#if GET_TEMP_0_ADC() == 0
TEMP_0,
#endif
#if GET_TEMP_1_ADC() == 0
TEMP_1,
#endif
#if GET_TEMP_2_ADC() == 0
TEMP_2,
#endif
#if GET_TEMP_3_ADC() == 0
TEMP_3,
#endif
#if GET_TEMP_4_ADC() == 0
TEMP_4,
#endif
#if GET_TEMP_5_ADC() == 0
TEMP_5,
#endif
#if GET_TEMP_6_ADC() == 0
TEMP_6,
#endif
#if GET_TEMP_7_ADC() == 0
TEMP_7,
#endif
#if GET_BED_ADC() == 0
TEMP_BED,
#endif
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER,
#endif
#if GET_PROBE_ADC() == 0
TEMP_PROBE,
#endif
#if GET_COOLER_ADC() == 0
TEMP_COOLER,
#endif
#if GET_BOARD_ADC() == 0
TEMP_BOARD,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH,
#endif
#if GET_BUTTONS_ADC() == 0
ADC_KEY,
#endif
#if GET_JOY_ADC_X() == 0
JOY_X,
#endif
#if GET_JOY_ADC_Y() == 0
JOY_Y,
#endif
#if GET_JOY_ADC_Z() == 0
JOY_Z,
#endif
#if GET_TEMP_0_ADC() == 1
TEMP_0,
#endif
#if GET_TEMP_1_ADC() == 1
TEMP_1,
#endif
#if GET_TEMP_2_ADC() == 1
TEMP_2,
#endif
#if GET_TEMP_3_ADC() == 1
TEMP_3,
#endif
#if GET_TEMP_4_ADC() == 1
TEMP_4,
#endif
#if GET_TEMP_5_ADC() == 1
TEMP_5,
#endif
#if GET_TEMP_6_ADC() == 1
TEMP_6,
#endif
#if GET_TEMP_7_ADC() == 1
TEMP_7,
#endif
#if GET_BED_ADC() == 1
TEMP_BED,
#endif
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER,
#endif
#if GET_PROBE_ADC() == 1
TEMP_PROBE,
#endif
#if GET_COOLER_ADC() == 1
TEMP_COOLER,
#endif
#if GET_BOARD_ADC() == 1
TEMP_BOARD,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH,
#endif
#if GET_BUTTONS_ADC() == 1
ADC_KEY,
#endif
#if GET_JOY_ADC_X() == 1
JOY_X,
#endif
#if GET_JOY_ADC_Y() == 1
JOY_Y,
#endif
#if GET_JOY_ADC_Z() == 1
JOY_Z,
#endif
ADC_COUNT
};
#if ENABLED(USE_WATCHDOG)
#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
void MarlinHAL::watchdog_init() {
// The low-power oscillator used by the WDT runs at 32,768 Hz with
// a 1:32 prescale, thus 1024 Hz, though probably not super precise.
// Setup WDT clocks
MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
MCLK->APBAMASK.bit.WDT_ = true;
OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
SYNC(WDT->SYNCBUSY.bit.ENABLE);
WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset
hal.watchdog_refresh();
WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
SYNC(WDT->SYNCBUSY.bit.ENABLE);
}
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or SAMD will go into emergency procedures.
void MarlinHAL::watchdog_refresh() {
SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
}
#endif
// ------------------------
// Types
// ------------------------
@@ -106,12 +254,10 @@
// Private Variables
// ------------------------
uint16_t HAL_adc_result;
#if ADC_IS_REQUIRED
// Pins used by ADC inputs. Order must be ADC0 inputs first then ADC1
const uint8_t adc_pins[] = {
static constexpr uint8_t adc_pins[ADC_COUNT] = {
// ADC0 pins
#if GET_TEMP_0_ADC() == 0
TEMP_0_PIN,
@@ -137,24 +283,36 @@ uint16_t HAL_adc_result;
#if GET_TEMP_7_ADC() == 0
TEMP_7_PIN,
#endif
#if GET_PROBE_ADC() == 0
TEMP_PROBE_PIN,
#endif
#if GET_BED_ADC() == 0
TEMP_BED_PIN,
#endif
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER_PIN,
#endif
#if GET_PROBE_ADC() == 0
TEMP_PROBE_PIN,
#endif
#if GET_COOLER_ADC() == 0
TEMP_COOLER_PIN,
#endif
#if GET_BOARD_ADC() == 0
TEMP_BOARD_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH_PIN,
#endif
#if GET_BUTTONS_ADC() == 0
ADC_KEYPAD_PIN,
#endif
#if GET_JOY_ADC_X() == 0
JOY_X_PIN,
#endif
#if GET_JOY_ADC_Y() == 0
JOY_Y_PIN,
#endif
#if GET_JOY_ADC_Z() == 0
JOY_Z_PIN,
#endif
// ADC1 pins
#if GET_TEMP_0_ADC() == 1
TEMP_0_PIN,
@@ -180,33 +338,44 @@ uint16_t HAL_adc_result;
#if GET_TEMP_7_ADC() == 1
TEMP_7_PIN,
#endif
#if GET_PROBE_ADC() == 1
TEMP_PROBE_PIN,
#endif
#if GET_BED_ADC() == 1
TEMP_BED_PIN,
#endif
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER_PIN,
#endif
#if GET_PROBE_ADC() == 1
TEMP_PROBE_PIN,
#endif
#if GET_COOLER_ADC() == 1
TEMP_COOLER_PIN,
#endif
#if GET_BOARD_ADC() == 1
TEMP_BOARD_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH_PIN,
#endif
#if GET_BUTTONS_ADC() == 1
ADC_KEYPAD_PIN,
#endif
#if GET_JOY_ADC_X() == 1
JOY_X_PIN,
#endif
#if GET_JOY_ADC_Y() == 1
JOY_Y_PIN,
#endif
#if GET_JOY_ADC_Z() == 1
JOY_Z_PIN,
#endif
};
uint16_t HAL_adc_results[COUNT(adc_pins)];
static uint16_t adc_results[ADC_COUNT];
#if ADC0_IS_REQUIRED
Adafruit_ZeroDMA adc0DMAProgram,
adc0DMARead;
Adafruit_ZeroDMA adc0DMAProgram, adc0DMARead;
const HAL_DMA_DAC_Registers adc0_dma_regs_list[] = {
static constexpr HAL_DMA_DAC_Registers adc0_dma_regs_list[ADC_COUNT] = {
#if GET_TEMP_0_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_0_PIN) },
#endif
@@ -231,34 +400,45 @@ uint16_t HAL_adc_result;
#if GET_TEMP_7_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_7_PIN) },
#endif
#if GET_PROBE_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
#endif
#if GET_BED_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
#endif
#if GET_CHAMBER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_PROBE_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
#endif
#if GET_COOLER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_BOARD_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_BOARD_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
#if GET_BUTTONS_ADC() == 0
{ PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
#endif
#if GET_JOY_ADC_X() == 0
{ PIN_TO_INPUTCTRL(JOY_X_PIN) },
#endif
#if GET_JOY_ADC_Y() == 0
{ PIN_TO_INPUTCTRL(JOY_Y_PIN) },
#endif
#if GET_JOY_ADC_Z() == 0
{ PIN_TO_INPUTCTRL(JOY_Z_PIN) },
#endif
};
#define ADC0_AINCOUNT COUNT(adc0_dma_regs_list)
#endif // ADC0_IS_REQUIRED
#if ADC1_IS_REQUIRED
Adafruit_ZeroDMA adc1DMAProgram,
adc1DMARead;
Adafruit_ZeroDMA adc1DMAProgram, adc1DMARead;
const HAL_DMA_DAC_Registers adc1_dma_regs_list[] = {
static constexpr HAL_DMA_DAC_Registers adc1_dma_regs_list[ADC_COUNT] = {
#if GET_TEMP_0_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_0_PIN) },
#endif
@@ -283,24 +463,36 @@ uint16_t HAL_adc_result;
#if GET_TEMP_7_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_7_PIN) },
#endif
#if GET_PROBE_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
#endif
#if GET_BED_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
#endif
#if GET_CHAMBER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_PROBE_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
#endif
#if GET_COOLER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_BOARD_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_BOARD_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
#if GET_BUTTONS_ADC() == 1
{ PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
#endif
#if GET_JOY_ADC_X() == 1
{ PIN_TO_INPUTCTRL(JOY_X_PIN) },
#endif
#if GET_JOY_ADC_Y() == 1
{ PIN_TO_INPUTCTRL(JOY_Y_PIN) },
#endif
#if GET_JOY_ADC_Z() == 1
{ PIN_TO_INPUTCTRL(JOY_Z_PIN) },
#endif
};
#define ADC1_AINCOUNT COUNT(adc1_dma_regs_list)
@@ -312,9 +504,10 @@ uint16_t HAL_adc_result;
// Private functions
// ------------------------
#if DMA_IS_REQUIRED
void MarlinHAL::dma_init() {
#if DMA_IS_REQUIRED
void dma_init() {
DmacDescriptor *descriptor;
#if ADC0_IS_REQUIRED
@@ -343,7 +536,7 @@ uint16_t HAL_adc_result;
if (adc0DMARead.allocate() == DMA_STATUS_OK) {
adc0DMARead.addDescriptor(
(void *)&ADC0->RESULT.reg, // SRC
&HAL_adc_results, // DEST
&adc_results, // DEST
ADC0_AINCOUNT, // CNT
DMA_BEAT_SIZE_HWORD,
false, // SRCINC
@@ -380,7 +573,7 @@ uint16_t HAL_adc_result;
if (adc1DMARead.allocate() == DMA_STATUS_OK) {
adc1DMARead.addDescriptor(
(void *)&ADC1->RESULT.reg, // SRC
&HAL_adc_results[ADC0_AINCOUNT], // DEST
&adc_results[ADC0_AINCOUNT], // DEST
ADC1_AINCOUNT, // CNT
DMA_BEAT_SIZE_HWORD,
false, // SRCINC
@@ -393,36 +586,28 @@ uint16_t HAL_adc_result;
#endif
DMAC->PRICTRL0.bit.RRLVLEN0 = true; // Activate round robin for DMA channels required by ADCs
}
#endif // DMA_IS_REQUIRED
#endif // DMA_IS_REQUIRED
}
// ------------------------
// Public functions
// ------------------------
// HAL initialization task
void HAL_init() {
void MarlinHAL::init() {
TERN_(DMA_IS_REQUIRED, dma_init());
#if ENABLED(SDSUPPORT)
#if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT)
#if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
SET_INPUT_PULLUP(SD_DETECT_PIN);
#endif
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
}
// HAL idle task
/*
void HAL_idletask() {
}
*/
void HAL_clear_reset_source() { }
#pragma push_macro("WDT")
#undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
uint8_t HAL_get_reset_source() {
uint8_t MarlinHAL::get_reset_source() {
RSTC_RCAUSE_Type resetCause;
resetCause.reg = REG_RSTC_RCAUSE;
@@ -436,7 +621,7 @@ uint8_t HAL_get_reset_source() {
}
#pragma pop_macro("WDT")
void HAL_reboot() { NVIC_SystemReset(); }
void MarlinHAL::reboot() { NVIC_SystemReset(); }
extern "C" {
void * _sbrk(int incr);
@@ -454,9 +639,11 @@ int freeMemory() {
// ADC
// ------------------------
void HAL_adc_init() {
uint16_t MarlinHAL::adc_result;
void MarlinHAL::adc_init() {
#if ADC_IS_REQUIRED
memset(HAL_adc_results, 0xFF, sizeof(HAL_adc_results)); // Fill result with invalid values
memset(adc_results, 0xFF, sizeof(adc_results)); // Fill result with invalid values
LOOP_L_N(pi, COUNT(adc_pins))
pinPeripheral(adc_pins[pi], PIO_ANALOG);
@@ -491,17 +678,13 @@ void HAL_adc_init() {
#endif // ADC_IS_REQUIRED
}
void HAL_adc_start_conversion(const uint8_t adc_pin) {
void MarlinHAL::adc_start(const pin_t pin) {
#if ADC_IS_REQUIRED
LOOP_L_N(pi, COUNT(adc_pins)) {
if (adc_pin == adc_pins[pi]) {
HAL_adc_result = HAL_adc_results[pi];
return;
}
}
LOOP_L_N(pi, COUNT(adc_pins))
if (pin == adc_pins[pi]) { adc_result = adc_results[pi]; return; }
#endif
HAL_adc_result = 0xFFFF;
adc_result = 0xFFFF;
}
#endif // __SAMD51__

View File

@@ -26,7 +26,6 @@
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
#include "MarlinSerial_AGCM4.h"
@@ -89,46 +88,30 @@
typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS
#define HAL_SERVO_LIB Servo
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
class Servo;
typedef Servo hal_servo_t;
//
// Interrupts
//
#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
#define cli() __disable_irq() // Disable interrupts
#define sei() __enable_irq() // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
void HAL_reboot();
#define cli() __disable_irq() // Disable interrupts
#define sei() __enable_irq() // Enable interrupts
//
// ADC
//
extern uint16_t HAL_adc_result; // Most recent ADC conversion
#define HAL_ANALOG_SELECT(pin)
void HAL_adc_init();
//#define HAL_ADC_FILTERED // Disable Marlin's oversampling. The HAL filters ADC values.
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10 // ... 12
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t adc_pin);
//
// Pin Map
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
@@ -137,37 +120,97 @@ void HAL_adc_start_conversion(const uint8_t adc_pin);
//
// Tone
//
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin);
// Enable hooks into idle and setup for HAL
void HAL_init();
/*
#define HAL_IDLETASK 1
void HAL_idletask();
*/
//
// Utility functions
//
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
// ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
extern "C" {
#endif
char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);
extern "C" int freeMemory();
#ifdef __cplusplus
}
#endif
#pragma GCC diagnostic pop
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Restart the firmware from 0x0
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init();
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {}
// Begin ADC sampling on the given pin. Called from Temperature::isr!
static void adc_start(const pin_t pin);
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* Set the PWM duty cycle for the pin to the given value.
* No option to invert the duty cycle [default = false]
* No option to change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
private:
static void dma_init();
};

View File

@@ -53,7 +53,7 @@
static volatile int8_t currentServoIndex[_Nbr_16timers]; // index for the servo being pulsed for each timer (or -1 if refresh interval)
FORCE_INLINE static uint16_t getTimerCount() {
Tc * const tc = TimerConfig[SERVO_TC].pTc;
Tc * const tc = timer_config[SERVO_TC].pTc;
tc->COUNT16.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
SYNC(tc->COUNT16.SYNCBUSY.bit.CTRLB || tc->COUNT16.SYNCBUSY.bit.COUNT);
@@ -65,7 +65,7 @@ FORCE_INLINE static uint16_t getTimerCount() {
// Interrupt handler for the TC
// ----------------------------
HAL_SERVO_TIMER_ISR() {
Tc * const tc = TimerConfig[SERVO_TC].pTc;
Tc * const tc = timer_config[SERVO_TC].pTc;
const timer16_Sequence_t timer =
#ifndef _useTimer1
_timer2
@@ -77,7 +77,8 @@ HAL_SERVO_TIMER_ISR() {
;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
if (currentServoIndex[timer] < 0) {
int8_t cho = currentServoIndex[timer]; // Handle the prior servo first
if (cho < 0) { // Servo -1 indicates the refresh interval completed...
#if defined(_useTimer1) && defined(_useTimer2)
if (currentServoIndex[timer ^ 1] >= 0) {
// Wait for both channels
@@ -86,46 +87,38 @@ HAL_SERVO_TIMER_ISR() {
return;
}
#endif
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer
SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
}
else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW); // pulse this channel low if activated
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
// Select the next servo controlled by this timer
currentServoIndex[timer]++;
currentServoIndex[timer] = ++cho; // go to the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
if (SERVO(timer, cho).Pin.isActive) // activated?
digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
if (SERVO(timer, currentServoIndex[timer]).Pin.isActive) // check if activated
digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks;
tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
}
else {
// finished all channels so wait for the refresh period to expire before starting over
currentServoIndex[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
const uint16_t tcCounterValue = getTimerCount();
if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL);
else
tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL); // at least REFRESH_INTERVAL has elapsed
currentServoIndex[timer] = -1; // reset the timer COUNT.reg on the next call
const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER), // allow 256 cycles to ensure the next CV not missed
ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
tc->COUNT16.CC[tcChannel].reg = min(cval, ival);
}
if (tcChannel == 0) {
SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
// Clear the interrupt
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
}
else {
SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
// Clear the interrupt
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
}
}
void initISR(timer16_Sequence_t timer) {
Tc * const tc = TimerConfig[SERVO_TC].pTc;
void initISR(const timer16_Sequence_t timer) {
Tc * const tc = timer_config[SERVO_TC].pTc;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
static bool initialized = false; // Servo TC has been initialized
@@ -201,9 +194,9 @@ void initISR(timer16_Sequence_t timer) {
}
}
void finISR(timer16_Sequence_t timer) {
Tc * const tc = TimerConfig[SERVO_TC].pTc;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
void finISR(const timer16_Sequence_t timer_index) {
Tc * const tc = timer_config[SERVO_TC].pTc;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
// Disable the match channel interrupt request
tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;

View File

@@ -60,6 +60,12 @@
#define MATCH_J_MIN_EILINE(P) TERN0(HAS_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN))
#define MATCH_K_MAX_EILINE(P) TERN0(HAS_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN))
#define MATCH_K_MIN_EILINE(P) TERN0(HAS_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN))
#define MATCH_U_MAX_EILINE(P) TERN0(HAS_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN))
#define MATCH_U_MIN_EILINE(P) TERN0(HAS_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN))
#define MATCH_V_MAX_EILINE(P) TERN0(HAS_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN))
#define MATCH_V_MIN_EILINE(P) TERN0(HAS_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN))
#define MATCH_W_MAX_EILINE(P) TERN0(HAS_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN))
#define MATCH_W_MIN_EILINE(P) TERN0(HAS_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN))
#define MATCH_Z2_MAX_EILINE(P) TERN0(HAS_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN))
#define MATCH_Z2_MIN_EILINE(P) TERN0(HAS_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN))
#define MATCH_Z3_MAX_EILINE(P) TERN0(HAS_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN))
@@ -75,6 +81,9 @@
&& !MATCH_I_MAX_EILINE(P) && !MATCH_I_MIN_EILINE(P) \
&& !MATCH_J_MAX_EILINE(P) && !MATCH_J_MIN_EILINE(P) \
&& !MATCH_K_MAX_EILINE(P) && !MATCH_K_MIN_EILINE(P) \
&& !MATCH_U_MAX_EILINE(P) && !MATCH_U_MIN_EILINE(P) \
&& !MATCH_V_MAX_EILINE(P) && !MATCH_V_MIN_EILINE(P) \
&& !MATCH_W_MAX_EILINE(P) && !MATCH_W_MIN_EILINE(P) \
&& !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \
&& !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \
&& !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \
@@ -199,4 +208,40 @@ void setup_endstop_interrupts() {
#endif
attachInterrupt(K_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_U_MAX
#if !AVAILABLE_EILINE(U_MAX_PIN)
#error "U_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(U_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_U_MIN
#if !AVAILABLE_EILINE(U_MIN_PIN)
#error "U_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(U_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_V_MAX
#if !AVAILABLE_EILINE(V_MAX_PIN)
#error "V_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(V_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_V_MIN
#if !AVAILABLE_EILINE(V_MIN_PIN)
#error "V_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(V_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_W_MAX
#if !AVAILABLE_EILINE(W_MAX_PIN)
#error "W_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(W_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_W_MIN
#if !AVAILABLE_EILINE(W_MIN_PIN)
#error "W_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(W_MIN_PIN, endstop_ISR, CHANGE);
#endif
}

View File

@@ -36,7 +36,7 @@
#error "OnBoard SPI BUS can't be shared with other devices."
#endif
#if SERVO_TC == RTC_TIMER_NUM
#if SERVO_TC == MF_TIMER_RTC
#error "Servos can't use RTC timer"
#endif

View File

@@ -31,13 +31,13 @@
// Local defines
// --------------------------------------------------------------------------
#define NUM_HARDWARE_TIMERS 8
#define NUM_HARDWARE_TIMERS 9
// --------------------------------------------------------------------------
// Private Variables
// --------------------------------------------------------------------------
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS+1] = {
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ {.pTc=TC0}, TC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper (assigned priority 2)
{ {.pTc=TC1}, TC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers)
{ {.pTc=TC2}, TC2_IRQn, 5 }, // 2 - tone (reserved by framework and fixed assigned priority 5)
@@ -67,19 +67,19 @@ FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
// --------------------------------------------------------------------------
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
// Disable interrupt, just in case it was already enabled
Disable_Irq(irq);
if (timer_num == RTC_TIMER_NUM) {
Rtc * const rtc = TimerConfig[timer_num].pRtc;
if (timer_num == MF_TIMER_RTC) {
Rtc * const rtc = timer_config[timer_num].pRtc;
// Disable timer interrupt
rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
// RTC clock setup
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K; // External 32.768KHz oscillator
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K; // External 32.768kHz oscillator
// Stop timer, just in case, to be able to reconfigure it
rtc->MODE0.CTRLA.bit.ENABLE = false;
@@ -101,7 +101,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE);
}
else {
Tc * const tc = TimerConfig[timer_num].pTc;
Tc * const tc = timer_config[timer_num].pTc;
// Disable timer interrupt
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
@@ -141,17 +141,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
}
// Finally, enable IRQ
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
NVIC_SetPriority(irq, timer_config[timer_num].priority);
NVIC_EnableIRQ(irq);
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq);
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
Disable_Irq(irq);
}
@@ -161,7 +161,7 @@ static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq);
}

View File

@@ -25,21 +25,22 @@
// --------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------
#define RTC_TIMER_NUM 8 // This is not a TC but a RTC
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#define MF_TIMER_RTC 8 // This is not a TC but a RTC
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
#ifndef PULSE_TIMER_NUM
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER_NUM
#define TEMP_TIMER_NUM RTC_TIMER_NUM // Timer Index for Temperature
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP MF_TIMER_RTC // Timer Index for Temperature
#endif
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
@@ -52,30 +53,29 @@ typedef uint32_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#define TC_PRIORITY(t) t == SERVO_TC ? 1 \
: (t == STEP_TIMER_NUM || t == PULSE_TIMER_NUM) ? 2 \
: (t == TEMP_TIMER_NUM) ? 6 \
: 7
#define TC_PRIORITY(t) ( t == SERVO_TC ? 1 \
: (t == MF_TIMER_STEP || t == MF_TIMER_PULSE) ? 2 \
: (t == MF_TIMER_TEMP) ? 6 : 7 )
#define _TC_HANDLER(t) void TC##t##_Handler()
#define TC_HANDLER(t) _TC_HANDLER(t)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() TC_HANDLER(STEP_TIMER_NUM)
#define HAL_STEP_TIMER_ISR() TC_HANDLER(MF_TIMER_STEP)
#endif
#if STEP_TIMER_NUM != PULSE_TIMER_NUM
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM)
#if MF_TIMER_STEP != MF_TIMER_PULSE
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(MF_TIMER_PULSE)
#endif
#if TEMP_TIMER_NUM == RTC_TIMER_NUM
#if MF_TIMER_TEMP == MF_TIMER_RTC
#define HAL_TEMP_TIMER_ISR() void RTC_Handler()
#else
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(TEMP_TIMER_NUM)
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(MF_TIMER_TEMP)
#endif
// --------------------------------------------------------------------------
@@ -95,7 +95,7 @@ typedef struct {
// Public Variables
// --------------------------------------------------------------------------
extern const tTimerConfig TimerConfig[];
extern const tTimerConfig timer_config[];
// --------------------------------------------------------------------------
// Public functions
@@ -104,20 +104,20 @@ extern const tTimerConfig TimerConfig[];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
// Should never be called with timer RTC_TIMER_NUM
Tc * const tc = TimerConfig[timer_num].pTc;
// Should never be called with timer MF_TIMER_RTC
Tc * const tc = timer_config[timer_num].pTc;
tc->COUNT32.CC[0].reg = compare;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
// Should never be called with timer RTC_TIMER_NUM
Tc * const tc = TimerConfig[timer_num].pTc;
// Should never be called with timer MF_TIMER_RTC
Tc * const tc = timer_config[timer_num].pTc;
return (hal_timer_t)tc->COUNT32.CC[0].reg;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
// Should never be called with timer RTC_TIMER_NUM
Tc * const tc = TimerConfig[timer_num].pTc;
// Should never be called with timer MF_TIMER_RTC
Tc * const tc = timer_config[timer_num].pTc;
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
return tc->COUNT32.COUNT.reg;
@@ -128,13 +128,13 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
if (timer_num == RTC_TIMER_NUM) {
Rtc * const rtc = TimerConfig[timer_num].pRtc;
if (timer_num == MF_TIMER_RTC) {
Rtc * const rtc = timer_config[timer_num].pRtc;
// Clear interrupt flag
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
}
else {
Tc * const tc = TimerConfig[timer_num].pTc;
Tc * const tc = timer_config[timer_num].pTc;
// Clear interrupt flag
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
}

View File

@@ -1,54 +0,0 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
void watchdog_init() {
// The low-power oscillator used by the WDT runs at 32,768 Hz with
// a 1:32 prescale, thus 1024 Hz, though probably not super precise.
// Setup WDT clocks
MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
MCLK->APBAMASK.bit.WDT_ = true;
OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
SYNC(WDT->SYNCBUSY.bit.ENABLE);
WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset
HAL_watchdog_refresh();
WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
SYNC(WDT->SYNCBUSY.bit.ENABLE);
}
#endif // USE_WATCHDOG
#endif // __SAMD51__

View File

@@ -1,31 +0,0 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
// Initialize watchdog with a 4 second interrupt time
void watchdog_init();
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or SAMD will go into emergency procedures.
inline void HAL_watchdog_refresh() {
SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
}