Added more infrastructure to VM.
authorethereal <ethereal@ethv.net>
Wed, 12 Mar 2014 03:45:09 +0000 (21:45 -0600)
committerethereal <ethereal@ethv.net>
Wed, 12 Mar 2014 03:45:09 +0000 (21:45 -0600)
14 files changed:
vm/src/debug.c [new file with mode: 0644]
vm/src/debug.h [new file with mode: 0644]
vm/src/peripherals.c [new file with mode: 0644]
vm/src/peripherals.h [new file with mode: 0644]
vm/src/pio.c [new file with mode: 0644]
vm/src/pio.h [new file with mode: 0644]
vm/src/pmc.c
vm/src/pmc.h
vm/src/registers.h
vm/src/spi.c [new file with mode: 0644]
vm/src/spi.h [new file with mode: 0644]
vm/src/startup.c
vm/src/uart.c
vm/src/uart.h

diff --git a/vm/src/debug.c b/vm/src/debug.c
new file mode 100644 (file)
index 0000000..d1ce84c
--- /dev/null
@@ -0,0 +1,7 @@
+#include "debug.h"
+#include "uart.h"
+
+void debug_init(void) {
+    uart_init();
+    DEBUG("VM starting");
+}
diff --git a/vm/src/debug.h b/vm/src/debug.h
new file mode 100644 (file)
index 0000000..2ab88d3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define DEBUG_HELPER(msg) uart_send((uint8_t *)msg, sizeof(msg))
+
+#define DEBUG(msg) DEBUG_HELPER(msg "\n\r")
+
+void debug_init(void);
+
+#endif
diff --git a/vm/src/peripherals.c b/vm/src/peripherals.c
new file mode 100644 (file)
index 0000000..c1c1f73
--- /dev/null
@@ -0,0 +1,3 @@
+#include "peripherals.h"
+
+
diff --git a/vm/src/peripherals.h b/vm/src/peripherals.h
new file mode 100644 (file)
index 0000000..1aa9ea2
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef PERIPHERALS_H
+#define PERIPHERALS_H
+
+#define PERIPHERAL_ID_UART_0    8
+#define PERIPHERAL_ID_UART_1    9
+
+#define PERIPHERAL_ID_SPI       21
+
+#endif
diff --git a/vm/src/pio.c b/vm/src/pio.c
new file mode 100644 (file)
index 0000000..b89e0ef
--- /dev/null
@@ -0,0 +1,30 @@
+#include "pio.h"
+#include "registers.h"
+
+void pio_init(void) {
+    // ...
+}
+
+void pio_set_per(int bank, int id, int to) {
+    uint32_t off = 0;
+    if(bank == 0) bank = PIO_A;
+    else if(bank == 1) bank = PIO_B;
+    else if(bank == 2) bank = PIO_C;
+    if(to == 0) {
+        register_write(PIO_PER + off, 1U<<id);
+    }
+    else {
+        to --;
+        uint32_t old = register_read(PIO_ABCDSR1 + off);
+        old &= ~(1U<<id);
+        old |= (to & 1) << id;
+        register_write(PIO_ABCDSR1 + off, old);
+
+        old = register_read(PIO_ABCDSR2 + off);
+        old &= ~(1U<<id);
+        old |= ((to & 2)>>1) << id;
+        register_write(PIO_ABCDSR2 + off, old);
+
+        register_write(PIO_PDR + off, (1U<<id));
+    }
+}
diff --git a/vm/src/pio.h b/vm/src/pio.h
new file mode 100644 (file)
index 0000000..bfe6a48
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef PIO_H
+#define PIO_H
+
+void pio_init(void);
+
+#define PIO_PER_NONE 0
+#define PIO_PER_A 1
+#define PIO_PER_B 2
+#define PIO_PER_C 3
+#define PIO_PER_D 4
+void pio_set_per(int bank, int id, int to);
+
+#endif
index 367848d..361f13b 100644 (file)
@@ -4,25 +4,17 @@
 static void pmc_setup_mclk(void);
 
 void pmc_init() {
-    /* set master clock speed to 12MHz */
+    /* set master clock speed to 24MHz */
     pmc_setup_mclk();
 }
 
 static void pmc_setup_mclk(void) {
-    /* begin by slowing down the flash */
-    //register_write(EEFC_FMR, 0xf << 8);
-
     /* set main oscillator to 12MHz */
-    register_write(CKGR_MOR, (0x37 << 16) | (0 << 4) | (1<<3));
+    register_write(CKGR_MOR, (0x37 << 16) | (2 << 4) | (1<<3));
     while((register_read(PMC_SR) & 8) == 0) {}
 
-    #if 0
-    /* enable main oscillator */
-    register_write(CKGR_MOR, (0x37 << 16) | 1);
-    /* wait for oscillator to settle */
-    while((register_read(PMC_SR) & 1) == 0) {}
-    /* set up PLL to multiply main clock by 4 */
-    register_write(CKGR_PLLR, (1) | ((4-1) << 16) | (64) << 8);
+    /* set up PLL to multiply main clock by 2 (24MHz) */
+    register_write(CKGR_PLLR, (1) | ((2-1) << 16) | (64) << 8 | (1<<29));
     /* wait for PLL to lock */
     while((register_read(PMC_SR) & 2) == 0) {}
 
@@ -35,5 +27,12 @@ static void pmc_setup_mclk(void) {
     register_write(PMC_MCKR, 2);
     /* wait for clock selection to finish */
     while((register_read(PMC_SR) & 8) == 0) {}
-    #endif
+}
+
+void pmc_enable_perclock(uint32_t which) {
+    register_write(PMC_PCER, 1U<<which);
+}
+
+void pmc_disable_perclock(uint32_t which) {
+    register_write(PMC_PCDR, 1U<<which);
 }
index 6cf06d3..ef3acb2 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef PMC_H
 #define PMC_H
 
+#include <stdint.h>
+
 void pmc_init(void);
 
+void pmc_enable_perclock(uint32_t which);
+void pmc_disable_perclock(uint32_t which);
+
 #endif
index 1f45acb..9959ea4 100644 (file)
@@ -3,15 +3,55 @@
 
 #include <stdint.h>
 
+/* Watchdog registers */
+#define WDT_MR      0x400E1454
+
 /* EEFC registers */
-#define EEFC_FMR 0x400e0a00
+#define EEFC_FMR    0x400e0a00
 
 /* PMC registers */
-#define PMC_SR   0x400E0468
-#define PMC_PCSR 0x400E0418
-#define CKGR_MOR 0x400E0420
-#define CKGR_PLLR 0x400E0428
-#define PMC_MCKR 0x400E0430
+#define PMC_PCER    0x400E0410
+#define PMC_PCDR    0x400E0414
+#define PMC_PCSR    0x400E0418
+#define CKGR_MOR    0x400E0420
+#define CKGR_PLLR   0x400E0428
+#define PMC_MCKR    0x400E0430
+#define PMC_SR      0x400E0468
+
+/* PIO registers */
+#define PIO_A       0x000
+#define PIO_B       0x200
+#define PIO_C       0x400
+#define PIO_PER     0x400e0e00
+#define PIO_PDR     0x400e0e04
+#define PIO_OER     0x400e0e10
+#define PIO_ODR     0x400e0e14
+#define PIO_ABCDSR1 0x400e0e70
+#define PIO_ABCDSR2 0x400e0e74
+
+/* UART registers */
+#define UART_CR     0x400e0600
+#define UART_MR     0x400e0604
+#define UART_IDR    0x400e060c
+#define UART_SR     0x400e0614
+#define UART_THR    0x400e061c
+#define UART_BRGR   0x400e0620
+#define UART_PTCR   0x400e0720
+
+/* SPI registers */
+#define SPI_CR      0x40008000
+#define SPI_MR      0x40008004
+#define SPI_RDR     0x40008008
+#define SPI_TDR     0x4000800c
+#define SPI_SR      0x40008010
+#define SPI_IER     0x40008014
+#define SPI_IDR     0x40008018
+#define SPI_IMR     0x4000801c
+#define SPI_BRGR    0x40008020
+#define SPI_CSR0    0x40008030
+#define SPI_CSR1    0x40008034
+#define SPI_CSR2    0x40008038
+#define SPI_CSR3    0x4000803c
 
 void register_write(uint32_t which, uint32_t value);
 uint32_t register_read(uint32_t which);
diff --git a/vm/src/spi.c b/vm/src/spi.c
new file mode 100644 (file)
index 0000000..95bb734
--- /dev/null
@@ -0,0 +1,53 @@
+#include "spi.h"
+#include "pmc.h"
+#include "peripherals.h"
+#include "pio.h"
+#include "registers.h"
+#include "uart.h"
+
+static void spi_wait_tdre(void);
+static void spi_wait_rdrf(void);
+
+void spi_init(void) {
+    /* enable perclock */
+    pmc_enable_perclock(PERIPHERAL_ID_SPI);
+
+    /* enable peripheral I/O lines */
+    pio_set_per(0, 11, PIO_PER_A);
+    pio_set_per(0, 12, PIO_PER_A);
+    pio_set_per(0, 13, PIO_PER_A);
+    pio_set_per(0, 14, PIO_PER_A);
+
+    /* enable SPI */
+    register_write(SPI_CR, 1);
+
+    /* set master mode, fixed-peripheral mode, no decoder */
+    register_write(SPI_MR, (1<<0) | (1<<4));
+
+    /* configure slave 0 */
+    /* CSNAAT, SPCK = MCK/2 */
+    register_write(SPI_CSR0, (1<<2) | (2<<8));
+}
+
+static void spi_wait_tdre(void) {
+    while(!(register_read(SPI_SR) & 2)) {}
+}
+
+static void spi_wait_rdrf(void) {
+    while(!(register_read(SPI_SR) & 1)) {}
+}
+
+void spi_test(void) {
+    uint8_t val[] = {0x03, 0x0, 0x0, 0x0};
+    for(int i = 0; i < sizeof(val); i ++) {
+        spi_wait_tdre();
+        register_write(SPI_TDR, val[i]);
+    }
+    spi_wait_rdrf();
+    uint8_t ret = register_read(SPI_RDR) & 0xff;
+
+    const char *hex = "0123456789abcdef";
+
+    uart_send((uint8_t *)&hex[ret & 0xf], 1);
+    uart_send((uint8_t *)&hex[(ret>>4) & 0xf], 1);
+}
diff --git a/vm/src/spi.h b/vm/src/spi.h
new file mode 100644 (file)
index 0000000..aa23f8e
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef SPI_H
+#define SPI_H
+
+void spi_init(void);
+void spi_test(void);
+
+#endif
index adb9395..388956a 100644 (file)
@@ -1,6 +1,10 @@
 #include "interrupt.h"
+#include "spi.h"
 
 #include "pmc.h"
+#include "debug.h"
+
+#include "registers.h"
 
 /* Segment symbols */
 extern uint32_t _sfixed;
@@ -89,23 +93,36 @@ static void startup_reset_handler(void) {
         *dest = 0;
     }
 
-    /* at this point, should be all good to go... */
+    /* disable watchdog timer */
+    register_write(WDT_MR, (1<<15));
 
-    /* need to initialize PIOC */
-    /* TODO: not required for just outputs etc. */
+    /* at this point, should be all good to go... */
 
     pmc_init();
 
-    /* make PA3 high */
+    debug_init();
+
+    /*spi_init();
+    spi_test();*/
+
     *(uint32_t *)(0x400e0e00) = 0x8;
     *(uint32_t *)(0x400e0e10) = 0x8;
+    *(uint32_t *)(0x400e0e30) = 0x8;
 
+    uint8_t v = 'A';
     while(1) {
-        *(uint32_t *)(0x400e0e30) = 0x8;
-        for(int i = 0; i < 100000; i ++) {}
-        *(uint32_t *)(0x400e0e34) = 0x8;
-        for(int i = 0; i < 50000; i ++) {}
+        //uart_send(&v, 1);
+        for(int i = 0; i < 1000000; i ++) {}
+        v ++;
+        if(v > 'Z') v = 'A';
     }
 
+    /* make PA3 high */
+    *(uint32_t *)(0x400e0e00) = 0x8;
+    *(uint32_t *)(0x400e0e10) = 0x8;
+    *(uint32_t *)(0x400e0e30) = 0x8;
+    for(int i = 0; i < 500000; i ++) {}
+    *(uint32_t *)(0x400e0e34) = 0x8;
+
     while(1) {}
 }
index eb7c211..3aec4f6 100644 (file)
@@ -1,9 +1,42 @@
 #include "uart.h"
+#include "pmc.h"
+#include "peripherals.h"
+#include "registers.h"
+#include "pio.h"
 
-void uart_initialize() {
-    
+void uart_init() {
+    pmc_enable_perclock(PERIPHERAL_ID_UART_0);
+
+    /* reset + disable */
+    register_write(UART_CR, (1<<5) | (1<<7) | (1<<2) | (1<<3));
+
+    /* enable PIO peripheral pins */
+    pio_set_per(0, 9, PIO_PER_A);
+    pio_set_per(0, 10, PIO_PER_A);
+
+    /* disable all interrupts relating to the UART */
+    register_write(UART_IDR, 0xffffffff);
+
+    /* set no parity */
+    register_write(UART_MR, (4<<9));
+
+    /* disable PDC (for now) */
+    register_write(UART_PTCR, (1<<1) | (1<<9));
+
+    /* use baud-rate divider of 26, because
+        48e6 / (16*26) \approx 115384 \approx 115200 */
+    //register_write(UART_BRGR, 26);
+    register_write(UART_BRGR, 13);
+
+    /* enable receiver and transmitter */
+    register_write(UART_CR, (1<<4) | (1<<6));
 }
 
-void uart_send(uint8_t *data, uint32_t count) {
-    
+void uart_send(const uint8_t *data, uint32_t count) {
+    for(uint32_t i = 0; i < count; i ++) {
+        /* pause until character can be written into buffer */
+        while((register_read(UART_SR) & 2) == 0) {}
+        /* write character into send buffer */
+        register_write(UART_THR, data[i]);
+    }
 }
index 368a84e..012604c 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <stdint.h>
 
-void uart_initialize(void);
+void uart_init(void);
 
-void uart_send(uint8_t *data, uint32_t count);
+void uart_send(const uint8_t *data, uint32_t count);
 
 #endif