rlvgl 0.2.4

A modular, idiomatic Rust reimplementation of the LVGL graphics library for embedded and simulator use.
Documentation
//! Per-peripheral initialization for {{ ir.board.name }}.
//!
//! Enables and configures each peripheral used by the board.
//! IOMUX pin routing is done in `iomux.rs`; this module handles the
//! peripheral-internal configuration (baud rate, clock frequency, etc.).

/// Initialize every board peripheral in dependency order.
pub fn init() {
    {% for name in peripherals_used %}
    init_{{ name }}();
    {% endfor %}
}

{% for name in peripherals_used %}
{% if ir.chip.peripherals[name] is defined %}
{% set periph = ir.chip.peripherals[name] %}

{% if periph.class == "uart" %}
/// Initialize {{ name | upper }} as console at {{ ir.board.console.baud }} baud.
pub fn init_{{ name }}() {
    let base = {{ periph.base }}u32 as *mut u32;
    unsafe {
        // Disable UART before configuration (CTRL register offset 0x18).
        let ctrl = base.byte_add(0x18);
        core::ptr::write_volatile(ctrl, 0);

        // Set baud rate: BAUD register at offset 0x10.
        // OSR=15 (16x oversampling), SBR = IPG_HZ / (baud * (OSR+1))
        let sbr = super::clocks::IPG_HZ / ({{ ir.board.console.baud }} * 16);
        let baud = base.byte_add(0x10);
        core::ptr::write_volatile(baud, (15 << 24) | (sbr & 0x1FFF));

        // Enable TX and RX (CTRL.TE=1, CTRL.RE=1).
        core::ptr::write_volatile(ctrl, (1 << 19) | (1 << 18));
    }
}
{% elif periph.class == "i2c" %}
/// Initialize {{ name | upper }} as I2C master.
pub fn init_{{ name }}() {
    let base = {{ periph.base }}u32 as *mut u32;
    unsafe {
        // Reset master (MCR offset 0x10, bit 1 = RST).
        let mcr = base.byte_add(0x10);
        core::ptr::write_volatile(mcr, 1 << 1);
        // Wait for reset to clear.
        while core::ptr::read_volatile(mcr) & (1 << 1) != 0 {}

        {% if ir.board.i2c_configs[name] is defined %}
        // Configure clock: MCCR0 at offset 0x48.
        // CLKHI/CLKLO for ~{{ ir.board.i2c_configs[name].scl_hz }} Hz from IPG clock.
        let prescale = 1u32; // PRESCALE = 0 (div by 1)
        let clk_lo = super::clocks::IPG_HZ / ({{ ir.board.i2c_configs[name].scl_hz }} * 2 * (prescale + 1));
        let clk_hi = clk_lo;
        let mccr0 = base.byte_add(0x48);
        core::ptr::write_volatile(mccr0, (clk_hi << 8) | clk_lo);
        {% endif %}

        // Enable master (MCR.MEN = bit 0).
        core::ptr::write_volatile(mcr, 1);
    }
}
{% elif periph.class == "sdmmc" %}
/// Initialize {{ name | upper }} (SD/MMC).
pub fn init_{{ name }}() {
    // TODO: USDHC initialization — set initial clock divider,
    // bus width, and card detect.
}
{% elif periph.class == "display" %}
/// Initialize {{ name | upper }} (LCD interface).
pub fn init_{{ name }}() {
    // TODO: LCDIF initialization — configure timing, pixel format,
    // and framebuffer base address.
}
{% else %}
/// Initialize {{ name }}.
pub fn init_{{ name }}() {
    // TODO: {{ periph.class }} peripheral initialization.
}
{% endif %}
{% endif %}
{% endfor %}