Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix potential bootloop after WD timeout on AVR #23075

Merged
merged 4 commits into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4224,3 +4224,6 @@
*/
//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller
//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL

// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR.
//#define OPTIBOOT_RESET_REASON
21 changes: 20 additions & 1 deletion Marlin/src/HAL/AVR/HAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,31 @@
// Public Variables
// ------------------------

//uint8_t MCUSR;
// Don't initialize/override variable (which would happen in .init4)
uint8_t reset_reason __attribute__((section(".noinit")));

// ------------------------
// Public functions
// ------------------------

__attribute__((naked)) // Don't output function pro- and epilogue
__attribute__((used)) // Output the function, even if "not used"
__attribute__((section(".init3"))) // Put in an early user definable section
void HAL_save_reset_reason() {
#if ENABLED(OPTIBOOT_RESET_REASON)
__asm__ __volatile__(
A("STS %0, r2")
: "=m"(reset_reason)
);
#else
reset_reason = MCUSR;
#endif

// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
MCUSR = 0;
wdt_disable();
}

void HAL_init() {
// Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
Expand Down
6 changes: 3 additions & 3 deletions Marlin/src/HAL/AVR/HAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ typedef int8_t pin_t;
// Public Variables
// ------------------------

//extern uint8_t MCUSR;
extern uint8_t reset_reason;

// Serial ports
#ifdef USBCON
Expand Down Expand Up @@ -152,8 +152,8 @@ void HAL_init();

//void _delay_ms(const int delay);

inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
inline void HAL_clear_reset_source() { }
inline uint8_t HAL_get_reset_source() { return reset_reason; }

void HAL_reboot();

Expand Down
5 changes: 5 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -2489,6 +2489,11 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "An encoder button is required or SOFT_RESET_ON_KILL will reset the printer without notice!"
#endif

// Reset reason for AVR
#if ENABLED(OPTIBOOT_RESET_REASON) && !defined(__AVR__)
#error "OPTIBOOT_RESET_REASON only applies to AVR."
#endif

/**
* I2C bus
*/
Expand Down