♻️ 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

@@ -79,7 +79,7 @@
#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
// ------------------------
// Public Variables
// Serial ports
// ------------------------
#if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE
@@ -112,74 +112,37 @@
#endif
#endif
uint16_t HAL_adc_result;
// ------------------------
// Private Variables
// ADC
// ------------------------
STM32ADC adc(ADC1);
const uint8_t adc_pins[] = {
OPTITEM(HAS_TEMP_ADC_0, TEMP_0_PIN)
OPTITEM(HAS_TEMP_ADC_1, TEMP_1_PIN)
OPTITEM(HAS_TEMP_ADC_2, TEMP_2_PIN)
OPTITEM(HAS_TEMP_ADC_3, TEMP_3_PIN)
OPTITEM(HAS_TEMP_ADC_4, TEMP_4_PIN)
OPTITEM(HAS_TEMP_ADC_5, TEMP_5_PIN)
OPTITEM(HAS_TEMP_ADC_6, TEMP_6_PIN)
OPTITEM(HAS_TEMP_ADC_7, TEMP_7_PIN)
OPTITEM(HAS_HEATED_BED, TEMP_BED_PIN)
OPTITEM(HAS_TEMP_CHAMBER, TEMP_CHAMBER_PIN)
OPTITEM(HAS_TEMP_ADC_PROBE, TEMP_PROBE_PIN)
OPTITEM(HAS_TEMP_COOLER, TEMP_COOLER_PIN)
OPTITEM(HAS_TEMP_BOARD, TEMP_BOARD_PIN)
OPTITEM(FILAMENT_WIDTH_SENSOR, FILWIDTH_PIN)
OPTITEM(HAS_ADC_BUTTONS, ADC_KEYPAD_PIN)
OPTITEM(HAS_JOY_ADC_X, JOY_X_PIN)
OPTITEM(HAS_JOY_ADC_Y, JOY_Y_PIN)
OPTITEM(HAS_JOY_ADC_Z, JOY_Z_PIN)
OPTITEM(POWER_MONITOR_CURRENT, POWER_MONITOR_CURRENT_PIN)
OPTITEM(POWER_MONITOR_VOLTAGE, POWER_MONITOR_VOLTAGE_PIN)
};
// Watch out for recursion here! Our pin_t is signed, so pass through to Arduino -> analogRead(uint8_t)
enum TempPinIndex : char {
OPTITEM(HAS_TEMP_ADC_0, TEMP_0)
OPTITEM(HAS_TEMP_ADC_1, TEMP_1)
OPTITEM(HAS_TEMP_ADC_2, TEMP_2)
OPTITEM(HAS_TEMP_ADC_3, TEMP_3)
OPTITEM(HAS_TEMP_ADC_4, TEMP_4)
OPTITEM(HAS_TEMP_ADC_5, TEMP_5)
OPTITEM(HAS_TEMP_ADC_6, TEMP_6)
OPTITEM(HAS_TEMP_ADC_7, TEMP_7)
OPTITEM(HAS_HEATED_BED, TEMP_BED)
OPTITEM(HAS_TEMP_CHAMBER, TEMP_CHAMBER)
OPTITEM(HAS_TEMP_ADC_PROBE, TEMP_PROBE)
OPTITEM(HAS_TEMP_COOLER, TEMP_COOLER)
OPTITEM(HAS_TEMP_BOARD, TEMP_BOARD)
OPTITEM(FILAMENT_WIDTH_SENSOR, FILWIDTH)
OPTITEM(HAS_ADC_BUTTONS, ADC_KEY)
OPTITEM(HAS_JOY_ADC_X, JOY_X)
OPTITEM(HAS_JOY_ADC_Y, JOY_Y)
OPTITEM(HAS_JOY_ADC_Z, JOY_Z)
OPTITEM(POWER_MONITOR_CURRENT, POWERMON_CURRENT)
OPTITEM(POWER_MONITOR_VOLTAGE, POWERMON_VOLTS)
ADC_PIN_COUNT
};
uint16_t analogRead(const pin_t pin) {
const bool is_analog = _GET_MODE(pin) == GPIO_INPUT_ANALOG;
return is_analog ? analogRead(uint8_t(pin)) : 0;
}
uint16_t HAL_adc_results[ADC_PIN_COUNT];
// Wrapper to maple unprotected analogWrite
void analogWrite(const pin_t pin, int pwm_val8) {
if (PWM_PIN(pin)) analogWrite(uint8_t(pin), pwm_val8);
}
uint16_t MarlinHAL::adc_result;
// ------------------------
// Private functions
// ------------------------
static void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); // only values 0..7 are used
reg_value = SCB->AIRCR; /* read old register configuration */
reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */
reg_value = SCB->AIRCR; // read old register configuration
reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); // clear bits to change
reg_value = (reg_value |
((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) |
(PriorityGroupTmp << 8)); /* Insert write key & priority group */
(PriorityGroupTmp << 8)); // Insert write key & priority group
SCB->AIRCR = reg_value;
}
@@ -187,6 +150,8 @@ static void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
// Public functions
// ------------------------
void flashFirmware(const int16_t) { hal.reboot(); }
//
// Leave PA11/PA12 intact if USBSerial is not used
//
@@ -206,7 +171,11 @@ static void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
void HAL_init() {
// ------------------------
// MarlinHAL class
// ------------------------
void MarlinHAL::init() {
NVIC_SetPriorityGrouping(0x3);
#if PIN_EXISTS(LED)
OUT_WRITE(LED_PIN, LOW);
@@ -225,7 +194,7 @@ void HAL_init() {
}
// HAL idle task
void HAL_idletask() {
void MarlinHAL::idletask() {
#if HAS_SHARED_MEDIA
// If Marlin is using the SD card we need to lock it to prevent access from
// a PC via USB.
@@ -240,14 +209,7 @@ void HAL_idletask() {
#endif
}
void HAL_clear_reset_source() { }
/**
* TODO: Check this and change or remove.
*/
uint8_t HAL_get_reset_source() { return RST_POWER_ON; }
void _delay_ms(const int delay_ms) { delay(delay_ms); }
void MarlinHAL::reboot() { nvic_sys_reset(); }
extern "C" {
extern unsigned int _ebss; // end of bss section
@@ -281,31 +243,76 @@ extern "C" {
}
*/
// ------------------------
//
// ADC
// ------------------------
//
enum ADCIndex : uint8_t {
OPTITEM(HAS_TEMP_ADC_0, TEMP_0)
OPTITEM(HAS_TEMP_ADC_1, TEMP_1)
OPTITEM(HAS_TEMP_ADC_2, TEMP_2)
OPTITEM(HAS_TEMP_ADC_3, TEMP_3)
OPTITEM(HAS_TEMP_ADC_4, TEMP_4)
OPTITEM(HAS_TEMP_ADC_5, TEMP_5)
OPTITEM(HAS_TEMP_ADC_6, TEMP_6)
OPTITEM(HAS_TEMP_ADC_7, TEMP_7)
OPTITEM(HAS_HEATED_BED, TEMP_BED)
OPTITEM(HAS_TEMP_CHAMBER, TEMP_CHAMBER)
OPTITEM(HAS_TEMP_ADC_PROBE, TEMP_PROBE)
OPTITEM(HAS_TEMP_COOLER, TEMP_COOLER)
OPTITEM(HAS_TEMP_BOARD, TEMP_BOARD)
OPTITEM(FILAMENT_WIDTH_SENSOR, FILWIDTH)
OPTITEM(HAS_ADC_BUTTONS, ADC_KEY)
OPTITEM(HAS_JOY_ADC_X, JOY_X)
OPTITEM(HAS_JOY_ADC_Y, JOY_Y)
OPTITEM(HAS_JOY_ADC_Z, JOY_Z)
OPTITEM(POWER_MONITOR_CURRENT, POWERMON_CURRENT)
OPTITEM(POWER_MONITOR_VOLTAGE, POWERMON_VOLTS)
ADC_COUNT
};
static uint16_t adc_results[ADC_COUNT];
// Init the AD in continuous capture mode
void HAL_adc_init() {
void MarlinHAL::adc_init() {
static const uint8_t adc_pins[] = {
OPTITEM(HAS_TEMP_ADC_0, TEMP_0_PIN)
OPTITEM(HAS_TEMP_ADC_1, TEMP_1_PIN)
OPTITEM(HAS_TEMP_ADC_2, TEMP_2_PIN)
OPTITEM(HAS_TEMP_ADC_3, TEMP_3_PIN)
OPTITEM(HAS_TEMP_ADC_4, TEMP_4_PIN)
OPTITEM(HAS_TEMP_ADC_5, TEMP_5_PIN)
OPTITEM(HAS_TEMP_ADC_6, TEMP_6_PIN)
OPTITEM(HAS_TEMP_ADC_7, TEMP_7_PIN)
OPTITEM(HAS_HEATED_BED, TEMP_BED_PIN)
OPTITEM(HAS_TEMP_CHAMBER, TEMP_CHAMBER_PIN)
OPTITEM(HAS_TEMP_ADC_PROBE, TEMP_PROBE_PIN)
OPTITEM(HAS_TEMP_COOLER, TEMP_COOLER_PIN)
OPTITEM(HAS_TEMP_BOARD, TEMP_BOARD_PIN)
OPTITEM(FILAMENT_WIDTH_SENSOR, FILWIDTH_PIN)
OPTITEM(HAS_ADC_BUTTONS, ADC_KEYPAD_PIN)
OPTITEM(HAS_JOY_ADC_X, JOY_X_PIN)
OPTITEM(HAS_JOY_ADC_Y, JOY_Y_PIN)
OPTITEM(HAS_JOY_ADC_Z, JOY_Z_PIN)
OPTITEM(POWER_MONITOR_CURRENT, POWER_MONITOR_CURRENT_PIN)
OPTITEM(POWER_MONITOR_VOLTAGE, POWER_MONITOR_VOLTAGE_PIN)
};
static STM32ADC adc(ADC1);
// configure the ADC
adc.calibrate();
#if F_CPU > 72000000
adc.setSampleRate(ADC_SMPR_71_5); // 71.5 ADC cycles
#else
adc.setSampleRate(ADC_SMPR_41_5); // 41.5 ADC cycles
#endif
adc.setPins((uint8_t *)adc_pins, ADC_PIN_COUNT);
adc.setDMA(HAL_adc_results, (uint16_t)ADC_PIN_COUNT, (uint32_t)(DMA_MINC_MODE | DMA_CIRC_MODE), nullptr);
adc.setSampleRate((F_CPU > 72000000) ? ADC_SMPR_71_5 : ADC_SMPR_41_5); // 71.5 or 41.5 ADC cycles
adc.setPins((uint8_t *)adc_pins, ADC_COUNT);
adc.setDMA(adc_results, uint16_t(ADC_COUNT), uint32_t(DMA_MINC_MODE | DMA_CIRC_MODE), nullptr);
adc.setScanMode();
adc.setContinuous();
adc.startConversion();
}
void HAL_adc_start_conversion(const uint8_t adc_pin) {
void MarlinHAL::adc_start(const pin_t pin) {
#define __TCASE(N,I) case N: pin_index = I; break;
#define _TCASE(C,N,I) TERN_(C, __TCASE(N, I))
//TEMP_PINS pin_index;
TempPinIndex pin_index;
switch (adc_pin) {
ADCIndex pin_index;
switch (pin) {
default: return;
_TCASE(HAS_TEMP_ADC_0, TEMP_0_PIN, TEMP_0)
_TCASE(HAS_TEMP_ADC_1, TEMP_1_PIN, TEMP_1)
@@ -328,23 +335,7 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
_TCASE(POWER_MONITOR_CURRENT, POWER_MONITOR_CURRENT_PIN, POWERMON_CURRENT)
_TCASE(POWER_MONITOR_VOLTAGE, POWER_MONITOR_VOLTAGE_PIN, POWERMON_VOLTS)
}
HAL_adc_result = HAL_adc_results[(int)pin_index] >> (12 - HAL_ADC_RESOLUTION); // shift out unused bits
adc_result = (adc_results[(int)pin_index] & 0xFFF) >> (12 - HAL_ADC_RESOLUTION); // shift out unused bits
}
uint16_t HAL_adc_get_result() { return HAL_adc_result; }
uint16_t analogRead(pin_t pin) {
const bool is_analog = _GET_MODE(pin) == GPIO_INPUT_ANALOG;
return is_analog ? analogRead(uint8_t(pin)) : 0;
}
// Wrapper to maple unprotected analogWrite
void analogWrite(pin_t pin, int pwm_val8) {
if (PWM_PIN(pin)) analogWrite(uint8_t(pin), pwm_val8);
}
void HAL_reboot() { nvic_sys_reset(); }
void flashFirmware(const int16_t) { HAL_reboot(); }
#endif // __STM32F1__

View File

@@ -66,6 +66,10 @@
#endif
#endif
// ------------------------
// Serial ports
// ------------------------
#ifdef SERIAL_USB
typedef ForwardSerial1Class< USBSerial > DefaultSerial1;
extern DefaultSerial1 MSerial0;
@@ -141,11 +145,6 @@
#endif
#endif
// Set interrupt grouping for this MCU
void HAL_init();
#define HAL_IDLETASK 1
void HAL_idletask();
/**
* TODO: review this to return 1 for pins that are not analog input
*/
@@ -158,15 +157,7 @@ void HAL_idletask();
#define NO_COMPILE_TIME_PWM
#endif
#define CRITICAL_SECTION_START() uint32_t primask = __get_primask(); (void)__iCliRetVal()
#define CRITICAL_SECTION_END() if (!primask) (void)__iSeiRetVal()
#define ISRS_ENABLED() (!__get_primask())
#define ENABLE_ISRS() ((void)__iSeiRetVal())
#define DISABLE_ISRS() ((void)__iCliRetVal())
// On AVR this is in math.h?
#define square(x) ((x)*(x))
// Reset Reason
#define RST_POWER_ON 1
#define RST_EXTERNAL 2
#define RST_BROWN_OUT 4
@@ -182,60 +173,17 @@ void HAL_idletask();
typedef int8_t pin_t;
// ------------------------
// Public Variables
// Interrupts
// ------------------------
// Result of last ADC conversion
extern uint16_t HAL_adc_result;
// ------------------------
// Public functions
// ------------------------
// Disable interrupts
#define CRITICAL_SECTION_START() const bool irqon = !__get_primask(); (void)__iCliRetVal()
#define CRITICAL_SECTION_END() if (!irqon) (void)__iSeiRetVal()
#define cli() noInterrupts()
// Enable interrupts
#define sei() interrupts()
// Memory related
#define __bss_end __bss_end__
// Clear reset reason
void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
void HAL_reboot();
void _delay_ms(const int delay);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
/*
extern "C" {
int freeMemory();
}
*/
extern "C" char* _sbrk(int incr);
static inline int freeMemory() {
volatile char top;
return &top - _sbrk(0);
}
#pragma GCC diagnostic pop
//
// ------------------------
// ADC
//
#define HAL_ANALOG_SELECT(pin) pinMode(pin, INPUT_ANALOG);
void HAL_adc_init();
// ------------------------
#ifdef ADC_RESOLUTION
#define HAL_ADC_RESOLUTION ADC_RESOLUTION
@@ -244,43 +192,115 @@ void HAL_adc_init();
#endif
#define HAL_ADC_VREF 3.3
#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);
uint16_t HAL_adc_get_result();
uint16_t analogRead(pin_t pin); // need HAL_ANALOG_SELECT() first
void analogWrite(pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!?
uint16_t analogRead(const pin_t pin); // need hal.adc_enable() first
void analogWrite(const pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!?
//
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#define JTAG_DISABLE() afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY)
#define JTAG_DISABLE() afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY)
#define JTAGSWD_DISABLE() afio_cfg_debug_ports(AFIO_DEBUG_NONE)
#define PLATFORM_M997_SUPPORT
void flashFirmware(const int16_t);
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#ifndef PWM_FREQUENCY
#define PWM_FREQUENCY 1000 // Default PWM Frequency
#endif
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
/**
* set_pwm_frequency
* Set the frequency of the timer corresponding to the provided pin
* All Timer PWM pins run at the same frequency
*/
void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
// ------------------------
// Class Utilities
// ------------------------
/**
* set_pwm_duty
* Set the PWM duty cycle of the provided pin to the provided value
* Optionally allows inverting the duty cycle [default = false]
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
* The timer must be pre-configured with set_pwm_frequency() if the default frequency is not desired.
*/
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
// Memory related
#define __bss_end __bss_end__
void _delay_ms(const int ms);
extern "C" char* _sbrk(int incr);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
static inline int freeMemory() {
volatile char top;
return &top - _sbrk(0);
}
#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() { ((void)__iSeiRetVal()); }
static void isr_off() { ((void)__iCliRetVal()); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source() { return RST_POWER_ON; }
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 pin_t pin) { pinMode(pin, INPUT_ANALOG); }
// 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.
* Optionally invert the duty cycle [default = false]
* Optionally change the maximum size of the provided value to enable finer PWM duty control [default = 255]
* The timer must be pre-configured with set_pwm_frequency() if the default frequency is not desired.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false);
/**
* Set the frequency of the timer for the given pin.
* All Timer PWM pins run at the same frequency.
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

View File

@@ -91,6 +91,14 @@ static const spi_pins board_spi_pins[] __FLASH__ = {
static void *_spi3_this;
#endif
/**
* @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
*/
static inline void waitSpiTxEnd(spi_dev *spi_d) {
while (spi_is_tx_empty(spi_d) == 0) { /* nada */ } // wait until TXE=1
while (spi_is_busy(spi_d) != 0) { /* nada */ } // wait until BSY=0
}
/**
* Constructor
*/

View File

@@ -414,12 +414,4 @@ private:
*/
};
/**
* @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
*/
static void waitSpiTxEnd(spi_dev *spi_d) {
while (spi_is_tx_empty(spi_d) == 0) { /* nada */ } // wait until TXE=1
while (spi_is_busy(spi_d) != 0) { /* nada */ } // wait until BSY=0
}
extern SPIClass SPI;

View File

@@ -35,7 +35,8 @@
#define SERVO_DEFAULT_MIN_ANGLE 0
#define SERVO_DEFAULT_MAX_ANGLE 180
#define HAL_SERVO_LIB libServo
class libServo;
typedef libServo hal_servo_t;
class libServo {
public:

View File

@@ -21,11 +21,9 @@
*/
#ifdef __STM32F1__
#include "../../inc/MarlinConfigPre.h"
#include "../../inc/MarlinConfig.h"
#include <pwm.h>
#include "HAL.h"
#include "timers.h"
#define NR_TIMERS TERN(STM32_XL_DENSITY, 14, 8) // Maple timers, 14 for STM32_XL_DENSITY (F/G chips), 8 for HIGH density (C D E)
@@ -38,7 +36,7 @@ inline uint8_t timer_and_index_for_pin(const pin_t pin, timer_dev **timer_ptr) {
return 0;
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
const uint16_t duty = invert ? v_size - v : v;
if (PWM_PIN(pin)) {
timer_dev *timer; UNUSED(timer);
@@ -54,7 +52,7 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
}
}
void set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
timer_dev *timer; UNUSED(timer);

View File

@@ -188,7 +188,7 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
}
#define HAL_timer_isr_epilogue(T)
#define HAL_timer_isr_epilogue(T) NOOP
// No command is available in framework to turn off ARPE bit, which is turned on by default in libmaple.
// Needed here to reset ARPE=0 for stepper timer