#pragma once #include enum clock_selection { CLOCK_SELECTION_PLL = 0, CLOCK_SELECTION_LSE, CLOCK_SELECTION_LSI, CLOCK_SELECTION_HSE, }; typedef struct { enum clock_selection sel; union { /* Divisor for the PLL. If set to 0, the default value of 5 is used. */ uint8_t pll_clock_divisor; /* Divisor for the HSE. If set to 0, the default value of 5 is used. */ uint8_t hse_clock_divisor; }; } clock_cfg_t; // Called when the system clock is changed. typedef struct { void (*on_clk_change)(const clock_cfg_t* cfg); } clock_chg_evt_listener_t; /* Set the system clock configuration. */ int set_system_clock(const clock_cfg_t* clk_cfg); /* Returns the clock configuration the system is currently in. */ int get_system_clock(clock_cfg_t* out); /* Returns the frequency for the provided clock config. */ uint32_t get_clock_freq(const clock_cfg_t* clk_cfg); void configure_lse(void); #define on_system_clock_changed(name) \ void on_system_clock_changed__##name(const clock_cfg_t*); \ __attribute__(( \ __section__(".clock_change_listeners"))) clock_chg_evt_listener_t name = \ ((clock_chg_evt_listener_t){.on_clk_change = \ on_system_clock_changed__##name}); \ void on_system_clock_changed__##name