Skip to content

Commit 44eff9a

Browse files
committed
♻️ Refactor HAL as singleton (MarlinFirmware#23357)
1 parent fee85b3 commit 44eff9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1953
-1395
lines changed

Marlin/src/HAL/AVR/HAL.cpp

+20-20
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
// ------------------------
3737

3838
// Don't initialize/override variable (which would happen in .init4)
39-
uint8_t reset_reason __attribute__((section(".noinit")));
39+
uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
4040

4141
// ------------------------
4242
// Public functions
@@ -45,22 +45,22 @@ uint8_t reset_reason __attribute__((section(".noinit")));
4545
__attribute__((naked)) // Don't output function pro- and epilogue
4646
__attribute__((used)) // Output the function, even if "not used"
4747
__attribute__((section(".init3"))) // Put in an early user definable section
48-
void HAL_save_reset_reason() {
48+
void save_reset_reason() {
4949
#if ENABLED(OPTIBOOT_RESET_REASON)
5050
__asm__ __volatile__(
5151
A("STS %0, r2")
52-
: "=m"(reset_reason)
52+
: "=m"(hal.reset_reason)
5353
);
5454
#else
55-
reset_reason = MCUSR;
55+
hal.reset_reason = MCUSR;
5656
#endif
5757

5858
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
59-
MCUSR = 0;
59+
hal.clear_reset_source();
6060
wdt_disable();
6161
}
6262

63-
void HAL_init() {
63+
void MarlinHAL::init() {
6464
// Init Servo Pins
6565
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
6666
#if HAS_SERVO_0
@@ -79,7 +79,7 @@ void HAL_init() {
7979
init_pwm_timers(); // Init user timers to default frequency - 1000HZ
8080
}
8181

82-
void HAL_reboot() {
82+
void MarlinHAL::reboot() {
8383
#if ENABLED(USE_WATCHDOG)
8484
while (1) { /* run out the watchdog */ }
8585
#else
@@ -95,20 +95,20 @@ void HAL_reboot() {
9595

9696
#else // !SDSUPPORT
9797

98-
extern "C" {
99-
extern char __bss_end;
100-
extern char __heap_start;
101-
extern void* __brkval;
102-
103-
int freeMemory() {
104-
int free_memory;
105-
if ((int)__brkval == 0)
106-
free_memory = ((int)&free_memory) - ((int)&__bss_end);
107-
else
108-
free_memory = ((int)&free_memory) - ((int)__brkval);
109-
return free_memory;
98+
extern "C" {
99+
extern char __bss_end;
100+
extern char __heap_start;
101+
extern void* __brkval;
102+
103+
int freeMemory() {
104+
int free_memory;
105+
if ((int)__brkval == 0)
106+
free_memory = ((int)&free_memory) - ((int)&__bss_end);
107+
else
108+
free_memory = ((int)&free_memory) - ((int)__brkval);
109+
return free_memory;
110+
}
110111
}
111-
}
112112

113113
#endif // !SDSUPPORT
114114

Marlin/src/HAL/AVR/HAL.h

+110-74
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,25 @@
7474
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
7575
#define CRITICAL_SECTION_END() SREG = _sreg
7676
#endif
77-
#define ISRS_ENABLED() TEST(SREG, SREG_I)
78-
#define ENABLE_ISRS() sei()
79-
#define DISABLE_ISRS() cli()
77+
78+
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
79+
#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
8080

8181
// ------------------------
8282
// Types
8383
// ------------------------
8484

8585
typedef int8_t pin_t;
8686

87-
#define SHARED_SERVOS HAS_SERVOS
88-
#define HAL_SERVO_LIB Servo
87+
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
88+
89+
class Servo;
90+
typedef Servo hal_servo_t;
8991

9092
// ------------------------
91-
// Public Variables
93+
// Serial ports
9294
// ------------------------
9395

94-
extern uint8_t reset_reason;
95-
96-
// Serial ports
9796
#ifdef USBCON
9897
#include "../../core/serial_hook.h"
9998
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
@@ -142,20 +141,31 @@ extern uint8_t reset_reason;
142141
#endif
143142
#endif
144143

145-
// ------------------------
146-
// Public functions
147-
// ------------------------
144+
//
145+
// ADC
146+
//
147+
#define HAL_ADC_VREF 5.0
148+
#define HAL_ADC_RESOLUTION 10
148149

149-
void HAL_init();
150+
//
151+
// Pin Mapping for M42, M43, M226
152+
//
153+
#define GET_PIN_MAP_PIN(index) index
154+
#define GET_PIN_MAP_INDEX(pin) pin
155+
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
150156

151-
//void cli();
157+
#define HAL_SENSITIVE_PINS 0, 1,
152158

153-
//void _delay_ms(const int delay);
159+
#ifdef __AVR_AT90USB1286__
160+
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
161+
#endif
154162

155-
inline void HAL_clear_reset_source() { }
156-
inline uint8_t HAL_get_reset_source() { return reset_reason; }
163+
// AVR compatibility
164+
#define strtof strtod
157165

158-
void HAL_reboot();
166+
// ------------------------
167+
// Class Utilities
168+
// ------------------------
159169

160170
#pragma GCC diagnostic push
161171
#if GCC_VERSION <= 50000
@@ -166,70 +176,96 @@ extern "C" int freeMemory();
166176

167177
#pragma GCC diagnostic pop
168178

169-
// ADC
170-
#ifdef DIDR2
171-
#define HAL_ANALOG_SELECT(ind) do{ if (ind < 8) SBI(DIDR0, ind); else SBI(DIDR2, ind & 0x07); }while(0)
172-
#else
173-
#define HAL_ANALOG_SELECT(ind) SBI(DIDR0, ind);
174-
#endif
179+
// ------------------------
180+
// MarlinHAL Class
181+
// ------------------------
175182

176-
inline void HAL_adc_init() {
177-
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
178-
DIDR0 = 0;
179-
#ifdef DIDR2
180-
DIDR2 = 0;
181-
#endif
182-
}
183+
class MarlinHAL {
184+
public:
183185

184-
#define SET_ADMUX_ADCSRA(ch) ADMUX = _BV(REFS0) | (ch & 0x07); SBI(ADCSRA, ADSC)
185-
#ifdef MUX5
186-
#define HAL_START_ADC(ch) if (ch > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
187-
#else
188-
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
189-
#endif
186+
// Earliest possible init, before setup()
187+
MarlinHAL() {}
190188

191-
#define HAL_ADC_VREF 5.0
192-
#define HAL_ADC_RESOLUTION 10
193-
#define HAL_READ_ADC() ADC
194-
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
189+
static void init(); // Called early in setup()
190+
static void init_board() {} // Called less early in setup()
191+
static void reboot(); // Restart the firmware from 0x0
195192

196-
#define GET_PIN_MAP_PIN(index) index
197-
#define GET_PIN_MAP_INDEX(pin) pin
198-
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
193+
// Interrupts
194+
static bool isr_state() { return TEST(SREG, SREG_I); }
195+
static void isr_on() { sei(); }
196+
static void isr_off() { cli(); }
199197

200-
#define HAL_SENSITIVE_PINS 0, 1,
198+
static void delay_ms(const int ms) { _delay_ms(ms); }
201199

202-
#ifdef __AVR_AT90USB1286__
203-
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
204-
#endif
200+
// Tasks, called from idle()
201+
static void idletask() {}
205202

206-
// AVR compatibility
207-
#define strtof strtod
203+
// Reset
204+
static uint8_t reset_reason;
205+
static uint8_t get_reset_source() { return reset_reason; }
206+
static void clear_reset_source() { MCUSR = 0; }
208207

209-
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
210-
#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
208+
// Free SRAM
209+
static int freeMemory() { return ::freeMemory(); }
211210

212-
/**
213-
* set_pwm_frequency
214-
* Sets the frequency of the timer corresponding to the provided pin
215-
* as close as possible to the provided desired frequency. Internally
216-
* calculates the required waveform generation mode, prescaler and
217-
* resolution values required and sets the timer registers accordingly.
218-
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
219-
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
220-
*/
221-
void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
211+
//
212+
// ADC Methods
213+
//
222214

223-
/**
224-
* set_pwm_duty
225-
* Set the PWM duty cycle of the provided pin to the provided value
226-
* Optionally allows inverting the duty cycle [default = false]
227-
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
228-
*/
229-
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
215+
// Called by Temperature::init once at startup
216+
static void adc_init() {
217+
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
218+
DIDR0 = 0;
219+
#ifdef DIDR2
220+
DIDR2 = 0;
221+
#endif
222+
}
230223

231-
/*
232-
* init_pwm_timers
233-
* sets the default frequency for timers 2-5 to 1000HZ
234-
*/
235-
void init_pwm_timers();
224+
// Called by Temperature::init for each sensor at startup
225+
static void adc_enable(const uint8_t ch) {
226+
#ifdef DIDR2
227+
if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
228+
#endif
229+
SBI(DIDR0, ch);
230+
}
231+
232+
// Begin ADC sampling on the given channel
233+
static void adc_start(const uint8_t ch) {
234+
#ifdef MUX5
235+
ADCSRB = ch > 7 ? _BV(MUX5) : 0;
236+
#else
237+
ADCSRB = 0;
238+
#endif
239+
ADMUX = _BV(REFS0) | (ch & 0x07);
240+
SBI(ADCSRA, ADSC);
241+
}
242+
243+
// Is the ADC ready for reading?
244+
static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
245+
246+
// The current value of the ADC register
247+
static __typeof__(ADC) adc_value() { return ADC; }
248+
249+
/**
250+
* init_pwm_timers
251+
* Set the default frequency for timers 2-5 to 1000HZ
252+
*/
253+
static void init_pwm_timers();
254+
255+
/**
256+
* Set the PWM duty cycle for the pin to the given value.
257+
* Optionally invert the duty cycle [default = false]
258+
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
259+
*/
260+
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
261+
262+
/**
263+
* Set the frequency of the timer for the given pin as close as
264+
* possible to the provided desired frequency. Internally calculate
265+
* the required waveform generation mode, prescaler, and resolution
266+
* values and set timer registers accordingly.
267+
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
268+
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
269+
*/
270+
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
271+
};

Marlin/src/HAL/AVR/MarlinSerial.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ void MarlinSerial<Cfg>::write(const uint8_t c) {
486486
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
487487

488488
// If global interrupts are disabled (as the result of being called from an ISR)...
489-
if (!ISRS_ENABLED()) {
489+
if (!hal.isr_state()) {
490490

491491
// Make room by polling if it is possible to transmit, and do so!
492492
while (i == tx_buffer.tail) {
@@ -534,7 +534,7 @@ void MarlinSerial<Cfg>::flushTX() {
534534
if (!_written) return;
535535

536536
// If global interrupts are disabled (as the result of being called from an ISR)...
537-
if (!ISRS_ENABLED()) {
537+
if (!hal.isr_state()) {
538538

539539
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
540540
while (tx_buffer.head != tx_buffer.tail || !B_TXC) {

Marlin/src/HAL/AVR/MarlinSerial.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@
191191
rx_framing_errors;
192192
static ring_buffer_pos_t rx_max_enqueued;
193193

194-
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head();
194+
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
195195

196196
static volatile bool rx_tail_value_not_stable;
197197
static volatile uint16_t rx_tail_value_backup;
198198

199-
static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
200-
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
199+
FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
200+
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
201201

202202
public:
203203
FORCE_INLINE static void store_rxd_char();

Marlin/src/HAL/AVR/fast_pwm.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const Timer get_pwm_timer(const pin_t pin) {
107107
return Timer();
108108
}
109109

110-
void set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
110+
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
111111
const Timer timer = get_pwm_timer(pin);
112112
if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
113113

@@ -176,7 +176,7 @@ void set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
176176
_SET_ICRn(timer, res); // Set ICRn value (TOP) = res
177177
}
178178

179-
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
179+
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
180180
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
181181
// Note that digitalWrite also disables PWM output for us (sets COM bit to 0)
182182
if (v == 0)
@@ -201,7 +201,7 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
201201
}
202202
}
203203

204-
void init_pwm_timers() {
204+
void MarlinHAL::init_pwm_timers() {
205205
// Init some timer frequencies to a default 1KHz
206206
const pin_t pwm_pin[] = {
207207
#ifdef __AVR_ATmega2560__

Marlin/src/HAL/AVR/math.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
// C B A is longIn1
3636
// D C B A is longIn2
3737
//
38-
static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
38+
FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
3939
uint8_t tmp1;
4040
uint8_t tmp2;
4141
uint16_t intRes;
@@ -89,7 +89,7 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
8989
// uses:
9090
// r26 to store 0
9191
// r27 to store the byte 1 of the 24 bit result
92-
static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
92+
FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
9393
uint8_t tmp;
9494
uint16_t intRes;
9595
__asm__ __volatile__ (

0 commit comments

Comments
 (0)