std1.0.0-beta-7 SafeC docs

Source hal/watchdog.h

View in the repository

// SafeC Standard Library — Watchdog Timer HAL
// Hardware watchdog feed/enable. Freestanding-safe.
//
// Watchdog<C> is generic over the watchdog block, a compile-time chip type:
//   WatchdogGeneric  reference layout: CTRL +0x00 (bit 0 enable), TIMEOUT
//                    +0x04, FEED +0x08 (write 0x6969), STATUS +0x0C (bit 0:
//                    last reset was a watchdog reset)
//   Stm32F4Iwdg      STM32 independent watchdog (KR/PR/RLR/SR): 'timeout'
//                    is the 12-bit reload value, counted at LSI / 256
//                    (~8 ms per unit at 32 kHz); caused_reset() reads
//                    RCC_CSR.IWDGRSTF at STM32F4's RCC address
#pragma once

#define STM32F4_RCC_CSR 0x40023874UL

namespace std {

// What a watchdog block type provides; Watchdog<C> requires it.
trait WatchdogChip {
    void init(unsigned long base, unsigned int timeout) const;
    void enable(unsigned long base) const;
    void feed(unsigned long base) const;
    int  caused_reset(unsigned long base) const;
}

struct WatchdogGeneric {
    int  unused_;
    void init(unsigned long base, unsigned int timeout) const;
    void enable(unsigned long base) const;
    void feed(unsigned long base) const;
    int  caused_reset(unsigned long base) const;
};
struct Stm32F4Iwdg {
    int  unused_;
    void init(unsigned long base, unsigned int timeout) const;
    void enable(unsigned long base) const;
    void feed(unsigned long base) const;
    int  caused_reset(unsigned long base) const;
};

generic<C: WatchdogChip>
struct Watchdog {
    &volatile unsigned int base; // MMIO base address
    unsigned int timeout;  // timeout period (chip-specific units, see above)
    C            chip;

    // Initialize the watchdog at `base` with the given timeout; the chip type
    // comes from the target.
    static struct Watchdog<C> new(&volatile unsigned int base, unsigned int timeout);

    // Enable the watchdog timer (cannot be disabled on most hardware).
    void         enable();
    // Feed (kick) the watchdog to prevent reset.
    void         feed();
    // Check if a watchdog reset occurred. Returns 1 if the previous reset was a WDT reset.
    int          caused_reset() const;
    unsigned long addr_() const;
};

generic<C: WatchdogChip>
struct Watchdog<C> Watchdog::new(&volatile unsigned int base, unsigned int timeout) {
    struct Watchdog<C> w;
    w.base = base;
    w.timeout = timeout;
    w.chip.init(w.addr_(), timeout);
    return w;
}

generic<C: WatchdogChip>
unsigned long Watchdog::addr_() const { unsafe { return (unsigned long)self.base; } }
generic<C: WatchdogChip>
void Watchdog::enable() { self.chip.enable(self.addr_()); }
generic<C: WatchdogChip>
void Watchdog::feed() { self.chip.feed(self.addr_()); }
generic<C: WatchdogChip>
int Watchdog::caused_reset() const { return self.chip.caused_reset(self.addr_()); }

} // namespace std