diff options
| author | Jeff Epler <jepler@gmail.com> | 2020-09-24 11:20:32 -0500 |
|---|---|---|
| committer | Jeff Epler <jepler@gmail.com> | 2020-09-28 18:55:56 -0500 |
| commit | 726dcdb60aa84b5070e5484a19e896abdaffeb93 (patch) | |
| tree | 24cb3b01a1805353dd8a27335faad09a917df60a /supervisor | |
| parent | 6bfcb01ee79d49f470a1a8ca5e693ba92fadf307 (diff) | |
Add some NORETURN attributes
I have a function where it should be impossible to reach the end, so I put in a safe-mode reset at the bottom:
```
int find_unused_slot(void) {
// precondition: you already verified that a slot was available
for (int i=0; i<NUM_SLOTS; i++) {
if( slot_free(i)) {
return i;
}
}
safe_mode_reset(MICROPY_FATAL_ERROR);
}
```
However, the compiler still gave a diagnostic, because safe_mode_reset was not declared NORETURN.
So I started by teaching the compiler that reset_into_safe_mode never returned. This leads at least one level deeper due to reset_cpu needing to be a NORETURN function. Each port is a little different in this area. I also marked reset_to_bootloader as NORETURN.
Additional notes:
* stm32's reset_to_bootloader was not implemented, but now does a bare reset. Most stm32s are not fitted with uf2 bootloaders anyway.
* ditto cxd56
* esp32s2 did not implement reset_cpu at all. I used esp_restart(). (not tested)
* litex did not implement reset_cpu at all. I used reboot_ctrl_write. But notably this is what reset_to_bootloader already did, so one or the other must be incorrect (not tested). reboot_ctrl_write cannot be declared NORETURN, as it returns unless the special value 0xac is written), so a new unreachable forever-loop is added.
* cxd56's reset is via a boardctl() call which can't generically be declared NORETURN, so a new unreacahble "for(;;)" forever-loop is added.
* In several places, NVIC_SystemReset is redeclared with NORETURN applied. This is accepted just fine by gcc. I chose this as preferable to editing the multiple copies of CMSIS headers where it is normally declared.
* the stub safe_mode reset simply aborts. This is used in mpy-cross.
Diffstat (limited to 'supervisor')
| -rw-r--r-- | supervisor/port.h | 4 | ||||
| -rw-r--r-- | supervisor/shared/safe_mode.h | 4 | ||||
| -rw-r--r-- | supervisor/stub/safe_mode.c | 5 |
3 files changed, 8 insertions, 5 deletions
diff --git a/supervisor/port.h b/supervisor/port.h index ddb96bd52..f5b3c15d1 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -44,7 +44,7 @@ extern uint32_t _ebss; safe_mode_t port_init(void); // Reset the microcontroller completely. -void reset_cpu(void); +void reset_cpu(void) NORETURN; // Reset the microcontroller state. void reset_port(void); @@ -53,7 +53,7 @@ void reset_port(void); void reset_board(void); // Reset to the bootloader -void reset_to_bootloader(void); +void reset_to_bootloader(void) NORETURN; // Get stack limit address uint32_t *port_stack_get_limit(void); diff --git a/supervisor/shared/safe_mode.h b/supervisor/shared/safe_mode.h index 7d3cd63b5..34fc3c8ae 100644 --- a/supervisor/shared/safe_mode.h +++ b/supervisor/shared/safe_mode.h @@ -27,6 +27,8 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_SAFE_MODE_H #define MICROPY_INCLUDED_SUPERVISOR_SAFE_MODE_H +#include "py/mpconfig.h" + typedef enum { NO_SAFE_MODE = 0, BROWNOUT, @@ -48,7 +50,7 @@ typedef enum { safe_mode_t wait_for_safe_mode_reset(void); void safe_mode_on_next_reset(safe_mode_t reason); -void reset_into_safe_mode(safe_mode_t reason); +void reset_into_safe_mode(safe_mode_t reason) NORETURN; void print_safe_mode_message(safe_mode_t reason); diff --git a/supervisor/stub/safe_mode.c b/supervisor/stub/safe_mode.c index 8072be2c6..a70ac6b6d 100644 --- a/supervisor/stub/safe_mode.c +++ b/supervisor/stub/safe_mode.c @@ -26,14 +26,15 @@ #include "supervisor/shared/safe_mode.h" +#include <stdlib.h> + safe_mode_t wait_for_safe_mode_reset(void) { return NO_SAFE_MODE; } void reset_into_safe_mode(safe_mode_t reason) { (void) reason; - for (;;) { - } + abort(); } void print_safe_mode_message(safe_mode_t reason) { |
