From 6d10f951d5c5ebae58f7c24df1066a479b68d5fa Mon Sep 17 00:00:00 2001 From: Victor Mignot Date: Thu, 24 Jul 2025 13:54:25 +0200 Subject: nrf52832: add clock driver --- src/boot.s | 8 +++++++ src/clock.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/clock.h | 10 ++++++++ src/main.c | 4 ++++ 4 files changed, 101 insertions(+) create mode 100644 src/clock.c create mode 100644 src/clock.h diff --git a/src/boot.s b/src/boot.s index 626420c..a2bb4b2 100644 --- a/src/boot.s +++ b/src/boot.s @@ -3,6 +3,10 @@ .section .vector_table, "a" .word __stack_top /* Initial stack pointer */ + +/** + * Exceptions + */ .word _start /* Reset Handler */ .word _hang /* Non Maskable Interrupts */ .word _hang /* Hard Fault */ @@ -15,6 +19,10 @@ .word _hang /* PendSV */ .word _hang /* SysTick */ +/** + * IRQs + */ + .text .align diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..5603693 --- /dev/null +++ b/src/clock.c @@ -0,0 +1,79 @@ +#include "clock.h" +#include "types.h" +#include "peripherals.h" + +#define WRITE_CLK_REG(reg, value) (WRITE_REGISTER(CLOCK, reg, value)) +#define READ_CLK_REG(reg) (READ_REGISTER(CLOCK, reg)) + +enum hfclk_src { + HFINT = 0, + HFXO = 1, +}; + +enum lfclk_src { + LFRC = 0, + LFXO = 1, + LFSYNT = 2, +}; + +/** + * Memory-mapped registers for the CLOCK peripheral with their offset from its base address, + * Check the nrf52832's manual for their description. + */ +enum clock_registers { + TASKS_HFCLKSTART = 0x000, + TASKS_HFCLKSTOP = 0x004, + TASKS_LFCLKSTART = 0x008, + TASKS_LFCLKSTOP = 0x00c, + TASKS_CAL = 0x010, + TASKS_CTSTART = 0x014, + TASKS_CTSTOP = 0x018, + EVENTS_HFCLKSTARTED = 0x100, + EVENTS_LFCLKSTARTED = 0x104, + EVENTS_DONE = 0x10c, + EVENTS_CTTO = 0x110, + INTENSET = 0x304, + INTENCLR = 0x308, + HFCLKRUN = 0x408, + HFCLKSTAT = 0x40c, + LFCLKRUN = 0x414, + LFCLKSTAT = 0x418, + LFCLKSRCCOPY = 0x41c, + LFCLKSRC = 0x518, + CTIV = 0x538, + TRACECONFIG = 0x55c, +}; + +static bool init_hfclk() { + /* We just assert that the source clock is running with the CPU internal clock + * as source */ + u32 hfclk_status = READ_CLK_REG(HFCLKSTAT); + int clk_src = hfclk_status & 0x1; + bool clk_running = (hfclk_status >> 16) & 0x1; + + return (clk_src == HFINT) && clk_running; +} + +static bool init_lfclk() { + bool clk_started = false; + enum lfclk_src src = LFRC; + + /* LFCLK use the LFRC clock by default, so it should be ready + * to be started directly */ + WRITE_CLK_REG(TASKS_LFCLKSTART, 0x1); + + /* Wait for the LFCLK to be started */ + /* TODO: We should rely on the IRQ for the LFCLKSTARTED event instead */ + do { + u32 lfclk_stat = READ_CLK_REG(LFCLKSTAT); + + clk_started = (lfclk_stat >> 16) & 0x1; + src = lfclk_stat & 0x2; + } while (!clk_started); + + return src == LFRC; +} + +bool init_clock() { + return init_hfclk() && init_lfclk(); +} diff --git a/src/clock.h b/src/clock.h new file mode 100644 index 0000000..30cfb44 --- /dev/null +++ b/src/clock.h @@ -0,0 +1,10 @@ +#ifndef CLOCK_H +#define CLOCK_H + +/** + * Init the nrf52832 CLOCK device and ensure that clock sources are correctly + * selected. + */ +bool init_clock(); + +#endif diff --git a/src/main.c b/src/main.c index 62563e2..02c20f8 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,8 @@ +#include "clock.h" + [[noreturn]] void main() { + init_clock(); + while (1) {} } -- cgit v1.2.3