aboutsummaryrefslogtreecommitdiff
path: root/src/lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.c')
-rw-r--r--src/lib.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/lib.c b/src/lib.c
new file mode 100644
index 0000000..2d8a596
--- /dev/null
+++ b/src/lib.c
@@ -0,0 +1,121 @@
+#include "lib.h"
+
+extern void uart_char(unsigned char c);
+extern void uart_hex(unsigned long data);
+extern void uart_string(char* message);
+
+extern unsigned long read_cntv_tval();
+extern unsigned long read_cntfrq();
+extern void write_cntv_tval(unsigned long); // Clear cntv interrupt and set next 1 second timer
+extern void routing_core0cntv_to_core0irq();
+extern void enable_cntv();
+
+extern unsigned long cntfrq;
+
+static char* irq_on = " \033[92mEnabled\033[0m\n";
+static char* irq_off = " \033[91mDisabled\033[0m\n";
+
+static inline unsigned long load32(unsigned long addr) {
+ return *(volatile unsigned long*)addr;
+}
+
+static inline void store32(unsigned long value, unsigned long addr) {
+ *(volatile unsigned long*)addr = value;
+}
+
+static inline void delay(unsigned long cycles) {
+ asm volatile("__delay_%=: subs%[cycles], %[cycles], #1;bne __delay_%=\n"
+ : "=r"(cycles): [cycles]"0"(cycles) : "cc");
+}
+
+void uart_hexn(unsigned long c_val) {
+ uart_hex(c_val);
+ uart_char(0x0a);
+}
+
+void sysinit() {
+ // Mask Overrun of UART0
+ store32(1<<4, UART0_IMSC);
+
+ // Enable UART GPU IRQ
+ store32(1<<25, IRQ_ENABLE2);
+
+ // Route GPU interrupts to Core 0
+ store32(0x00, GPU_INTERRUPTS_ROUTING);
+ //*(unsigned long*)
+
+ // Enable Timer
+ // As an IRQ
+ store32(1<<0, IRQ_BASIC_ENABLE);
+ // As a FIQ
+ //store32(0xC0, FIQ_CONTROL);
+ // Get the frequency
+ cntfrq = read_cntfrq();
+ // Clear cntv interrupt and set next 1 second timer
+ write_cntv_tval(cntfrq);
+ // Route timer to core0 irq
+ routing_core0cntv_to_core0irq();
+ // Enable timer
+ enable_cntv();
+}
+
+void c_timer() {
+ // Reset the counter
+ write_cntv_tval(cntfrq);
+
+ // Output the value
+ uart_string((char*)"CNTV_TVAL: ");
+ uart_hexn(read_cntv_tval());
+}
+
+// Checks IRQ statuses
+void chk_irq_stat() {
+ uart_string((char*)"Checking Enabled Services...\n");
+
+ // Basic IRQ
+ unsigned long ib_val = load32(IRQ_BASIC_ENABLE);
+ uart_string((char*)"IRQB Status: ");
+ uart_hexn(ib_val);
+
+ // IRQ 1
+ unsigned long i1_val = load32(IRQ_ENABLE1);
+ uart_string((char*)"IRQ1 Status: ");
+ uart_hexn(i1_val);
+
+ // IRQ 2
+ unsigned long i2_val = load32(IRQ_ENABLE2);
+ uart_string((char*)"IRQ2 Status: ");
+ uart_hexn(i2_val);
+
+ // Check UART IRQ
+ uart_string((char*)" UART:");
+ if (i2_val & (1<<25)) {
+ uart_string(irq_on);
+ } else {
+ uart_string(irq_off);
+ }
+
+ // Check TIMER IRQ
+ uart_string((char*)" TIMER:");
+ if (ib_val & (1<<0)) {
+ uart_string(irq_on);
+ // Output the frequency
+ uart_string((char*)" w/ CNTFRQ : ");
+ cntfrq = read_cntfrq();
+ uart_hexn(cntfrq);
+ } else {
+ uart_string(irq_off);
+ }
+
+ // Check FIQ
+ unsigned long f_val = load32(FIQ_CONTROL);
+ uart_string((char*)"FIQ Status: ");
+ uart_hexn(f_val);
+ if (f_val & 0x80) {
+ uart_string(irq_on);
+ } else {
+ uart_string(irq_off);
+ }
+
+ uart_char(0x0a);
+}