1052: stm32: Fix watchdog division by zero for 256 prescaler, add watchdog … r=lulf a=matoushybl …example for H7 The problem is that `2u8.powi(8) == 0`, which causes division by zero. 1053: Disable MMC interrupts r=lulf a=matoushybl MMC interrupts can cause firmware hangup - refer to: https://github.com/stm32-rs/stm32h7xx-hal/issues/275 for more information Fixes #594 Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
This commit is contained in:
commit
d05979c708
@ -116,6 +116,24 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T,
|
|||||||
|
|
||||||
mac.macqtx_fcr().modify(|w| w.set_pt(0x100));
|
mac.macqtx_fcr().modify(|w| w.set_pt(0x100));
|
||||||
|
|
||||||
|
// disable all MMC RX interrupts
|
||||||
|
mac.mmc_rx_interrupt_mask().write(|w| {
|
||||||
|
w.set_rxcrcerpim(true);
|
||||||
|
w.set_rxalgnerpim(true);
|
||||||
|
w.set_rxucgpim(true);
|
||||||
|
w.set_rxlpiuscim(true);
|
||||||
|
w.set_rxlpitrcim(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
// disable all MMC TX interrupts
|
||||||
|
mac.mmc_tx_interrupt_mask().write(|w| {
|
||||||
|
w.set_txscolgpim(true);
|
||||||
|
w.set_txmcolgpim(true);
|
||||||
|
w.set_txgpktim(true);
|
||||||
|
w.set_txlpiuscim(true);
|
||||||
|
w.set_txlpitrcim(true);
|
||||||
|
});
|
||||||
|
|
||||||
mtl.mtlrx_qomr().modify(|w| w.set_rsf(true));
|
mtl.mtlrx_qomr().modify(|w| w.set_rsf(true));
|
||||||
mtl.mtltx_qomr().modify(|w| w.set_tsf(true));
|
mtl.mtltx_qomr().modify(|w| w.set_tsf(true));
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@ pub struct IndependentWatchdog<'d, T: Instance> {
|
|||||||
const MAX_RL: u16 = 0xFFF;
|
const MAX_RL: u16 = 0xFFF;
|
||||||
|
|
||||||
/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler
|
/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler
|
||||||
const fn max_timeout(prescaler: u8) -> u32 {
|
const fn max_timeout(prescaler: u16) -> u32 {
|
||||||
1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32)
|
1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates watchdog reload value for the given prescaler and desired timeout
|
/// Calculates watchdog reload value for the given prescaler and desired timeout
|
||||||
const fn reload_value(prescaler: u8, timeout_us: u32) -> u16 {
|
const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 {
|
||||||
(timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16
|
(timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,12 +33,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
|
|||||||
// Find lowest prescaler value, which makes watchdog period longer or equal to timeout.
|
// Find lowest prescaler value, which makes watchdog period longer or equal to timeout.
|
||||||
// This iterates from 4 (2^2) to 256 (2^8).
|
// This iterates from 4 (2^2) to 256 (2^8).
|
||||||
let psc_power = unwrap!((2..=8).find(|psc_power| {
|
let psc_power = unwrap!((2..=8).find(|psc_power| {
|
||||||
let psc = 2u8.pow(*psc_power);
|
let psc = 2u16.pow(*psc_power);
|
||||||
timeout_us <= max_timeout(psc)
|
timeout_us <= max_timeout(psc)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Prescaler value
|
// Prescaler value
|
||||||
let psc = 2u8.pow(psc_power);
|
let psc = 2u16.pow(psc_power);
|
||||||
|
|
||||||
// Convert prescaler power to PR register value
|
// Convert prescaler power to PR register value
|
||||||
let pr = psc_power as u8 - 2;
|
let pr = psc_power as u8 - 2;
|
||||||
|
24
examples/stm32h7/src/bin/wdg.rs
Normal file
24
examples/stm32h7/src/bin/wdg.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::wdg::IndependentWatchdog;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000);
|
||||||
|
|
||||||
|
unsafe { wdg.unleash() };
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
unsafe { wdg.pet() };
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user