isa/examples: C-draft for bootROM
authorBernhard Urban <lewurm@gmail.com>
Mon, 25 Oct 2010 19:38:15 +0000 (21:38 +0200)
committerBernhard Urban <lewurm@gmail.com>
Mon, 25 Oct 2010 19:38:15 +0000 (21:38 +0200)
2_isa/misc.ptex
2_isa/src/bootrom.c [new file with mode: 0644]

index 3942fb59104fc506ae601acdafade9ba690c0143..e6e78ec6b1fd611ec7654563bb312a5541763b7f 100644 (file)
@@ -1,4 +1,4 @@
-ins ('32', 'branch', 'Branch; save pc+1 in stack, jump to pc+imm', '4 | 5 | 16 | 5 | 1 | 1', 'Conditions | OpCode | Immediate | - | +/- | S');
+ins ('32', 'branch', 'Branch; save pc+4 in stack, jump to pc+imm', '4 | 5 | 16 | 5 | 1 | 1', 'Conditions | OpCode | Immediate | - | +/- | S');
 
 ins ('32', 'jump', 'Jump; jump to pc+imm', '4 | 5 | 16 | 5 | 1 | 1', 'Conditions | OpCode | Immediate | - | +/- | S');
 
diff --git a/2_isa/src/bootrom.c b/2_isa/src/bootrom.c
new file mode 100644 (file)
index 0000000..d6e672e
--- /dev/null
@@ -0,0 +1,123 @@
+/* bootROM, a very small bootloader for $NAME
+ *
+ * protocol details:
+ * abbrv: H = Host, CPU = C
+ *
+ * value/cmd              | direction | comment
+ * ------------------------------------------------------------
+ * 'H'                    | H -> C    | enter bootROM ("HI")
+ * 'O'                    | C -> H    | ack bootROM entry ("OH HAI")
+ *
+ * 'W'0xZZZZZZZZ0xYYYYYYYY| H -> C    | write instr (0xYY...Y) to
+ *                                    | address (0xZZ...Z)
+ * 'D'                    | C -> H    | instr write done
+ *
+ * 'R'0xZZZZZZZZ          | H -> C    | read instr from address (0xZZ..Z)
+ * 'F'0xYYYYYYYY          | C -> H    | instr read done and return instr
+ *
+ * 'J'0xZZZZZZZZ          | H -> C    | jump to address (0xZZ...Z)
+ */
+
+#define UART_BASE 0x1000
+#define UART_STATUS (UART_BASE+0x4)
+#define UART_RECV (UART_BASE+0x8)
+#define UART_TRANS (UART_BASE+0xC)
+#define UART_BAUD (UART_BAUD+0x10)
+
+#define UART_TRANS_EMPTY 0
+#define UART_RECV_NEW 1
+
+/* TODO:
+ * - use different read/write functions for instr and data space
+ * - need absolute jump for program entry?
+ */
+
+void send_byte(u8 x)
+{
+       while(!(UART_STATUS & (1 << UART_TRANS_EMPTY)));
+       write8(UART_TRANS, x);
+}
+
+void send_word(u32 x)
+{
+       send_byte((x >> 0) & 0xff);
+       send_byte((x >> 8) & 0xff);
+       send_byte((x >> 16) & 0xff);
+       send_byte((x >> 24) & 0xff);
+}
+
+u8 recv_byte(void)
+{
+       u8 ret;
+       while(!(UART_STATUS & (1 << UART_RECV_NEW)));
+       ret = read8(UART_RECV);
+}
+
+u32 recv_word(void)
+{
+       u32 ret = 0;
+       ret |= recv_byte() << 0;
+       ret |= recv_byte() << 8;
+       ret |= recv_byte() << 16;
+       ret |= recv_byte() << 24;
+}
+
+void bootrom(void)
+{
+       u8 cmd;
+       u32 addr, instr;
+       for(;;) {
+               cmd = recv_byte();
+               switch(cmd) {
+                       case 'W':
+                               addr = recv_word();
+                               instr = recv_word();
+                               /* write to programm space */
+                               write32(addr, instr);
+                               send_byte('D');
+                               break;
+                       case 'R':
+                               addr = recv_word();
+                               instr = read32(addr);
+                               send_byte('F');
+                               send_word(instr);
+                               break;
+                       case 'J':
+                               addr = recv_word();
+                               jump_to_instr_mem(addr);
+                               /* this should never return ;) */
+                               break;
+                       case 'H':
+                       default:
+                               /* OH HAI */
+                               send_byte('O');
+                               break;
+               }
+       }
+}
+
+#define TIMEOUT_START 0x13371337
+#define DEFAULT_PROG_START 0x200
+
+void main(void)
+{
+       /* wait for timeout */
+       u32 to = TIMEOUT_START;
+       u8 rec;
+
+       /* until to overflows */
+       while(to != 0) {
+               /* noob timeout hack */
+               to++;
+               if(UART_STATUS & (1 << UART_RECV_NEW)) {
+                       rec = read8(UART_RECV);
+                       if(rec == 'H') {
+                               send_byte('O');
+                               bootrom();
+                       }
+               }
+       }
+
+       /* after timeout jump to instr. mem plz */
+       jump_to_instr_mem(DEFAULT_PROG_START);
+}