♻️ Refactor HAL as singleton (#23357, #23871, #23897)

This commit is contained in:
Scott Lahteine
2022-02-17 18:50:31 -06:00
committed by Scott Lahteine
parent 428b67db31
commit 56cec9690a
81 changed files with 1976 additions and 1418 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)
@ -61,17 +57,21 @@
#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_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_PROBE_ADC() == n \
|| GET_COOLER_ADC() == n \
|| GET_BOARD_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)
@ -91,6 +91,118 @@
#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
};
// ------------------------
// Types
// ------------------------
@ -108,12 +220,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,
@ -160,6 +270,15 @@ uint16_t HAL_adc_result;
#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,
@ -206,15 +325,23 @@ uint16_t HAL_adc_result;
#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
@ -260,16 +387,24 @@ uint16_t HAL_adc_result;
#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
@ -315,6 +450,15 @@ uint16_t HAL_adc_result;
#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)
@ -326,9 +470,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
@ -357,7 +502,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
@ -394,7 +539,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
@ -407,16 +552,16 @@ 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)
@ -426,17 +571,9 @@ void HAL_init() {
#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;
@ -450,7 +587,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);
@ -468,9 +605,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);
@ -505,17 +644,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

@ -89,51 +89,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);
//
// PWM
//
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
//
// Pin Map
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
@ -142,35 +121,93 @@ inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255,
//
// 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 ignored "-Wunused-function"
#endif
int freeMemory();
#pragma GCC diagnostic pop
#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() {}
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 channel
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();
};