Skip to content

Commit

Permalink
stm32xx-sys: statically ensure absence of panics
Browse files Browse the repository at this point in the history
At least in some configurations.
  • Loading branch information
cbiffle committed Apr 3, 2024
1 parent fec7fdc commit afbbf4c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/demo-stm32h7-nucleo/app-h753.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ request_reset = ["hiffy"]

[tasks.sys]
name = "drv-stm32xx-sys"
features = ["h753", "exti"]
features = ["h753", "exti", "no-panic"]
priority = 1
uses = ["rcc", "gpios", "system_flash", "syscfg", "exti"]
start = true
Expand Down
1 change: 1 addition & 0 deletions drv/stm32xx-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ g070 = ["family-stm32g0", "stm32g0/stm32g070", "drv-stm32xx-sys-api/g070", "drv-
g0b1 = ["family-stm32g0", "stm32g0/stm32g0b1", "drv-stm32xx-sys-api/g0b1", "drv-stm32xx-gpio-common/model-stm32g0b1"]

no-ipc-counters = ["idol/no-counters"]
no-panic = ["userlib/no-panic"]

# Enable external interrupt controller support.
exti = ["dep:hubris-num-tasks", "dep:counters"]
Expand Down
39 changes: 27 additions & 12 deletions drv/stm32xx-sys/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,13 @@ fn main() -> ! {
// API the way we use peripherals.
let syscfg = unsafe { &*device::SYSCFG::ptr() };

for (i, entry) in generated::EXTI_DISPATCH_TABLE.iter().enumerate() {
for i in 0..16 {
// TODO: this sure looks like it should be using
// iter.enumerate, doesn't it? Unfortunately that's not
// currently getting inlined by rustc, resulting in rather
// silly code containing panics. This is significantly
// smaller.
let entry = &generated::EXTI_DISPATCH_TABLE[i];
// Process entries that are filled in...
if let &Some(ExtiDispatch { port, .. }) = entry {
let register = i >> 2;
Expand Down Expand Up @@ -685,7 +691,7 @@ impl idl::InOrderSysImpl for ServerImpl<'_> {

for (i, _) in exti_dispatch_for(rm.sender, mask) {
// What bit do we touch for this entry?
let bit = 1 << i;
let bit = 1 << (i & 0xF);

// Record that these bits meant something.
slot_mask |= bit;
Expand Down Expand Up @@ -774,15 +780,17 @@ impl idl::InOrderSysImpl for ServerImpl<'_> {
let mut used_bits = 0u32;

for (i, entry) in exti_dispatch_for(rm.sender, mask) {
let imask = 1 << (i & 0xF);

used_bits |= entry.mask;

// Set or clear Rising Trigger Selection
// Register bit according to the rising flag
self.exti.rtsr1.modify(|r, w| {
let new_value = if edge.is_rising() {
r.bits() | (1 << i)
r.bits() | imask
} else {
r.bits() & !(1 << i)
r.bits() & !imask
};
unsafe {
w.bits(new_value)
Expand All @@ -793,9 +801,9 @@ impl idl::InOrderSysImpl for ServerImpl<'_> {
// Register bit according to the rising flag
self.exti.ftsr1.modify(|r, w| {
let new_value = if edge.is_falling() {
r.bits() | (1 << i)
r.bits() | imask
} else {
r.bits() & !(1 << i)
r.bits() & !imask
};
unsafe {
w.bits(new_value)
Expand Down Expand Up @@ -849,9 +857,12 @@ fn exti_dispatch_for(
task: TaskId,
mask: u32,
) -> impl Iterator<Item = (usize, &'static ExtiDispatch)> {
generated::EXTI_DISPATCH_TABLE
.iter()
.enumerate()
// This is semantically equivalent to iter.enumerate, but winds up handing
// the compiler very different code that avoids an otherwise-difficult panic
// site on an apparently-overflowing addition (that was not actually capable
// of overflowing).
(0..generated::EXTI_DISPATCH_TABLE.len())
.zip(&generated::EXTI_DISPATCH_TABLE)
.filter_map(move |(i, entry)| {
let entry = entry.as_ref()?;
if task.index() == entry.task.index() && mask & entry.mask != 0 {
Expand Down Expand Up @@ -898,9 +909,13 @@ impl NotificationHandler for ServerImpl<'_> {

let mut bits_to_acknowledge = 0u16;

for (pin_idx, entry) in
generated::EXTI_DISPATCH_TABLE.iter().enumerate()
{
for pin_idx in 0..16 {
// TODO: this sure looks like it should be using
// iter.enumerate, doesn't it? Unfortunately that's not
// currently getting inlined by rustc, resulting in rather
// silly code containing panics. This is significantly
// smaller.
let entry = &generated::EXTI_DISPATCH_TABLE[pin_idx];
if pending_and_enabled & 1 << pin_idx != 0 {
// A channel is pending! We need to handle this
// basically like the kernel handles native hardware
Expand Down

0 comments on commit afbbf4c

Please sign in to comment.