aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/boot.s8
-rw-r--r--src/clock.c79
-rw-r--r--src/clock.h10
-rw-r--r--src/main.c4
4 files changed, 101 insertions, 0 deletions
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) {}
}