feat(util): opt-in MMWHAL_CRITICAL_SECTION_NOOP for critical-section IRQ masking #124

Closed
opened 2026-07-23 23:05:23 +00:00 by hoogv · 0 comments
Owner

Found while bringing up a downstream consumer project (awr6843_mss_barebones_example) on real AWR6843AOP hardware.

mmwhal_enter_critical()/mmwhal_exit_critical() (hal/util/mmwhal_types.h) unconditionally re-enable IRQ (cpsie i) once the critical-section nesting count unwinds to zero -- regardless of whether IRQ was already unmasked, or deliberately left masked, by whatever called into the critical section in the first place. hal_gpio_pin_init() takes one such section.

For a project that never enables an interrupt source and never installs any real interrupt handling (a valid, common bare-metal design -- confirmed on real hardware in this case), the moment hal_gpio_pin_init() unmasks IRQ, the CPU can silently trap forever the instant anything triggers one (a stray/pending peripheral flag is enough), in that project's own unhandled-IRQ vector -- before the program ever reaches application code past the critical section. This is not a hang the caller can detect or recover from.

This is not proposing a change to the library's default behavior -- the real save/restore-previous-CPSR fix this design actually needs (so masking behaves correctly for downstream consumers who genuinely use interrupts) is a bigger, separate redesign, not something to rush in on the back of one project's bring-up.

Instead: add an opt-in MMWHAL_CRITICAL_SECTION_NOOP define (same customization path as ENABLE_<X>_MODULE, via a project's own hal_config_mss.h copied from template/hal_config_mss_template.h) that turns both MMWHAL_DISABLE_IRQ()/MMWHAL_ENABLE_IRQ() into no-ops -- for projects that can state up front they never enable an interrupt source anywhere. Default (unset) behavior is completely unchanged for every existing consumer.

Found while bringing up a downstream consumer project (`awr6843_mss_barebones_example`) on real AWR6843AOP hardware. `mmwhal_enter_critical()`/`mmwhal_exit_critical()` (`hal/util/mmwhal_types.h`) unconditionally re-enable IRQ (`cpsie i`) once the critical-section nesting count unwinds to zero -- regardless of whether IRQ was already unmasked, or deliberately left masked, by whatever called into the critical section in the first place. `hal_gpio_pin_init()` takes one such section. For a project that never enables an interrupt source and never installs any real interrupt handling (a valid, common bare-metal design -- confirmed on real hardware in this case), the moment `hal_gpio_pin_init()` unmasks IRQ, the CPU can silently trap forever the instant anything triggers one (a stray/pending peripheral flag is enough), in that project's own unhandled-IRQ vector -- before the program ever reaches application code past the critical section. This is not a hang the caller can detect or recover from. This is *not* proposing a change to the library's default behavior -- the real save/restore-previous-CPSR fix this design actually needs (so masking behaves correctly for downstream consumers who genuinely use interrupts) is a bigger, separate redesign, not something to rush in on the back of one project's bring-up. Instead: add an opt-in `MMWHAL_CRITICAL_SECTION_NOOP` define (same customization path as `ENABLE_<X>_MODULE`, via a project's own `hal_config_mss.h` copied from `template/hal_config_mss_template.h`) that turns both `MMWHAL_DISABLE_IRQ()`/`MMWHAL_ENABLE_IRQ()` into no-ops -- for projects that can state up front they never enable an interrupt source anywhere. Default (unset) behavior is completely unchanged for every existing consumer.
hoogv closed this issue 2026-07-23 23:06:06 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
opendutchsolutions.public/hal_awr6843#124
No description provided.