I experienced a painful waste of time yesterday which really made me wish embedded C had Rust's type system to have my back.
Basic issue was as follows: in STM32 HAL, I wanted to handle GPIO EXTI interrupt. Due to how interrupts are wired into NVIC on the Arm Cortex core, lines 5..9 and 10..15 share a single interrupt. So, in the interrupt handler for that IRQ line, you'd have to check which line triggered the interrupt:
if (__HAL_GPIO_EXTI_GET_FLAG(__EXTI_LINE__) != 0) {
...
}
So far so good. However, that __EXTI_LINE__
parameter to the function-like macro must be one of GPIO_PIN_X
, where X
in 0..15.
However, the GPIO_PIN_X
macros are just plain `#define GPIO_PIN_X (1U << X) macros.
Still no big deal. However, there are another similar set of macros defined, EXTI_LINE_X
. They are also just unsigned numbers as far as the compiler is concerned.
So when I saw that the parameter to __HAL_GPIO_EXTI_GET_FLAG()
is named __EXTI_LINE__
, I naturally assumed it was supposed to be one of EXTI_LINE_X
.
Add to all of that the fact that I was having a bit of an off day yesterday when I was writing this, and the fact that my __HAL_GPIO_EXTI_GET_FLAG(EXTI_LINE_6)
compiled just fine, it took me more time than it should have to figure it out.
Rust (or disciplined template C++ in this case) could've saved me from that by making the types of GPIO_PIN_X
and EXTI_LINE_X
different and incompatible.