bootromfun/dtprog: programmer fuers BootROM \o/
authorBernhard Urban <lewurm@gmail.com>
Tue, 11 Jan 2011 17:11:30 +0000 (18:11 +0100)
committerBernhard Urban <lewurm@gmail.com>
Tue, 11 Jan 2011 17:12:32 +0000 (18:12 +0100)
for usage see tools/dtprog.py

2_isa/src/bootrom.s
3_test/uartint.s
cpu/src/rom_b.vhd
tools/.gitignore [new file with mode: 0644]
tools/Makefile [new file with mode: 0644]
tools/SerialPort_linux.py [new file with mode: 0644]
tools/dtprog.py [new file with mode: 0755]

index 87b7f83f1a508bbd913707b723f90962ada6ad48..bfc81890abd408ba06dc782e3e5249a2b978ad45 100644 (file)
@@ -1,3 +1,29 @@
+;* 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
+;*
+;* 'Q'0xZZZZZZZZ0xYYYYYYYY| H -> C    | write data (0xYY...Y) to
+;*                                    | address (0xZZ...Z)
+;* 'A'                    | C -> H    | data write done
+;*
+;* 'T'0xZZZZZZZZ          | H -> C    | read data from address (0xZZ..Z)
+;* 'G'0xYYYYYYYY          | C -> H    | read done and return data
+;*
+;* 'J'0xZZZZZZZZ          | H -> C    | jump to address (0xZZ...Z)
+;*/
        .data
 
        .text
@@ -77,9 +103,9 @@ recv_word:
 
        call recv_byte
        lls r1, r1, 8
-       or r1, r0, r1
+       or r0, r0, r1
+       xor r1, r1, r1
 
-       addi r0, r1, 0
        ret
 
 ;-----
@@ -90,8 +116,8 @@ bootrom:
        cmpi r0, 0x57 ; 'W'
        breq- bt_W
 
-       cmpi r0, 0x52 ; 'R'
-       breq- bt_R
+       ;cmpi r0, 0x52 ; 'R'
+       ;breq- bt_R
 
        cmpi r0, 0x51 ; 'Q'
        breq- bt_Q
@@ -112,15 +138,17 @@ bt_H:
        br bootrom
 
 bt_W:
-       ; call recv_word ; receive addr
-       ; stw r0, PADDR(r11)
-       ; call recv_word ; receive instr
-       ; stw r0, PDATA(r11)
-       ; ldi r1, 0x44 ; 'D'
-       ; call send_byte
+       ldi r1, 0x57 ; 'W'
+       call send_byte
+       call recv_word ; receive addr
+       stw r0, PADDR(r11)
+       call recv_word ; receive instr
+       stw r0, PDATA(r11)
+       ldi r1, 0x44 ; 'D'
+       call send_byte
        br bootrom
 
-bt_R:
+;bt_R: ;lesen von IRAM wird nicht unterstuetzt
        ;call recv_word ; receive addr
        ;mov r2, r0
        ;ldi r1, 0x46 ; 'F'
@@ -128,11 +156,12 @@ bt_R:
        ;ldx r1, 0(r2)
        ;call send_word
        ;br bootrom
-       br tehend
 
 bt_Q:
+       ldi r1, 0x51 ; 'Q'
+       call send_byte
        call recv_word ; receive addr
-       mov r6, r0
+       addi r6, r0, 0
        call recv_word ; receive data
        stw r0, 0(r6)
        ldi r1, 0x41 ; 'A'
@@ -149,9 +178,6 @@ bt_T:
        br bootrom
 
 bt_J:
-       call recv_word
-       brr r0
-
 tehend:
        xor r1, r1, r1
        ldi r1, 0x41 ; 'A'
index 8afa8f23fa081bddfce80f9d4fd8f02e5c474166..ed9df5776258c2cc11677adae29e800d20111f5b 100644 (file)
@@ -1,22 +1,66 @@
+.data
+str:
+       .fill 0x41424344
+       .fill 0x0a0d0000
 .text
+       .define UART_BASE, 0x2000
+       .define UART_STATUS, 0x0
+       .define UART_RECV, 0xc
+       .define UART_TRANS, 0x8
+
+       .define UART_TRANS_EMPTY, 0x1
+       .define UART_RECV_NEW, 0x2
 start:
        br+ main ;br+ 
        br+ main
        ret
 main:
-       ldi r0, 0x2000 ; status...
-       ldi r1, 0x200b ;ldi r1, 8203
-       ldi r2, 0x200c ;ldi r2, 8204
-       ; ldi r4, 0x2024 ;ldi r4, 8228
-       ; ldi r5, 3 ; enable interrupts
-       ; stw r5, 0(r4)
-       ldw r5, 0(r0)
-       andx r5, 0x2
+       ldi r10, UART_BASE@lo
+       ldih r10, UART_BASE@hi
+       ldw r5, UART_STATUS(r10)
+       andx r5, UART_RECV_NEW
        brzs+ main ; no new data?
-       ldw r7, 0(r2) ; load data
+       ldw r7, UART_RECV(r10) ; load data
+
+       xor r1, r1, r1
+       xor r2, r2, r2
+       xor r3, r3, r3
+       ; ldi r1, str
+       ; ldi r1, 0x58
+       ; stb r1, str(r3)
+       ldw r1, str(r3) 
+       ldi r2, 6
+       ;call send_string
+       call send_byte
+
+main2:
+       ldw r5, UART_STATUS(r10)
+       andx r5, UART_RECV_NEW
+       brzs+ main2 ; no new data?
+       ldw r7, UART_RECV(r10) ; load data
 uartnrdy:
        ldw r5, 0(r0)
-       andx r5, 0x1
+       andx r5, UART_TRANS_EMPTY
        brnz+ uartnrdy ; transmitter not ready yet?
-       stw r7, 0(r1) ; send zeh shit!
-       br main ; back to usual stuff
+       stw r7, UART_TRANS(r10) ; send zeh shit!
+       br main2 ; back to usual stuff
+
+send_string:
+       ; r1 = addr
+       ; r2 = len
+       addi r3, r1, 0
+send_string_int:
+       cmpi r2, 0
+       reteq-
+       ldb r1, 0(r3)
+       call send_byte
+       addi r2, r2, 0-1
+       addi r3, r3, 1
+       br send_string_int
+
+send_byte:
+       ldw r9, UART_STATUS(r10)
+       andx r9, UART_TRANS_EMPTY
+       brnz+ send_byte ; branch if not zero
+       stw r1, UART_TRANS(r10)
+       ret
index 82c954b32a5362cf43e17e6518009d601c96f14f..8606702a0e322ce036b8b0f5ae9d4965f91f4d5a 100644 (file)
@@ -133,7 +133,7 @@ begin
        when "0000111" => data_out <= x"eb000985"; -- call recv_byte
        when "0001000" => data_out <= x"e4088800"; -- xor r1, r1, r1
        when "0001001" => data_out <= x"ec800240"; -- cmpi r0, 0x48 
-       when "0001010" => data_out <= x"1b001803"; -- breq+ bt_H
+       when "0001010" => data_out <= x"1b001703"; -- breq+ bt_H
        when "0001011" => data_out <= x"eb7ffe01"; -- br poll 
        when "0001100" => data_out <= x"e71d0000"; -- ldw r3, UART_STATUS(r10)
        when "0001101" => data_out <= x"e2980008"; -- andx r3, UART_TRANS_EMPTY
@@ -166,51 +166,56 @@ begin
        when "0101000" => data_out <= x"e3080800"; -- or r1, r0, r1
        when "0101001" => data_out <= x"eb7ff885"; -- call recv_byte
        when "0101010" => data_out <= x"e508a000"; -- lls r1, r1, 8
-       when "0101011" => data_out <= x"e3080800"; -- or r1, r0, r1
-       when "0101100" => data_out <= x"e1008000"; -- addi r0, r1, 0
+       when "0101011" => data_out <= x"e3000800"; -- or r0, r0, r1
+       when "0101100" => data_out <= x"e4088800"; -- xor r1, r1, r1
        when "0101101" => data_out <= x"eb000008"; -- ret
        when "0101110" => data_out <= x"eb7ff605"; -- call recv_byte
        when "0101111" => data_out <= x"e4088800"; -- xor r1, r1, r1
        when "0110000" => data_out <= x"ec8002b8"; -- cmpi r0, 0x57 
-       when "0110001" => data_out <= x"1b000601"; -- breq- bt_W
-       when "0110010" => data_out <= x"ec800290"; -- cmpi r0, 0x52 
-       when "0110011" => data_out <= x"1b000581"; -- breq- bt_R
-       when "0110100" => data_out <= x"ec800288"; -- cmpi r0, 0x51 
-       when "0110101" => data_out <= x"1b000501"; -- breq- bt_Q
-       when "0110110" => data_out <= x"ec8002a0"; -- cmpi r0, 0x54 
-       when "0110111" => data_out <= x"1b000781"; -- breq- bt_T
-       when "0111000" => data_out <= x"ec800250"; -- cmpi r0, 0x4a 
-       when "0111001" => data_out <= x"1b000a01"; -- breq- bt_J
-       when "0111010" => data_out <= x"ed080278"; -- ldi r1, 0x4f 
-       when "0111011" => data_out <= x"eb7fe885"; -- call send_byte
-       when "0111100" => data_out <= x"eb7ff901"; -- br bootrom
-       when "0111101" => data_out <= x"eb7ff881"; -- br bootrom
-       when "0111110" => data_out <= x"eb000881"; -- br tehend
+       when "0110001" => data_out <= x"1b000501"; -- breq- bt_W
+       when "0110010" => data_out <= x"ec800288"; -- cmpi r0, 0x51 
+       when "0110011" => data_out <= x"1b000881"; -- breq- bt_Q
+       when "0110100" => data_out <= x"ec8002a0"; -- cmpi r0, 0x54 
+       when "0110101" => data_out <= x"1b000c01"; -- breq- bt_T
+       when "0110110" => data_out <= x"ec800250"; -- cmpi r0, 0x4a 
+       when "0110111" => data_out <= x"1b000e81"; -- breq- bt_J
+       when "0111000" => data_out <= x"ed080278"; -- ldi r1, 0x4f 
+       when "0111001" => data_out <= x"eb7fe985"; -- call send_byte
+       when "0111010" => data_out <= x"eb7ffa01"; -- br bootrom
+       when "0111011" => data_out <= x"ed0802b8"; -- ldi r1, 0x57 
+       when "0111100" => data_out <= x"eb7fe805"; -- call send_byte
+       when "0111101" => data_out <= x"eb7ff185"; -- call recv_word 
+       when "0111110" => data_out <= x"e7858004"; -- stw r0, PADDR(r11)
        when "0111111" => data_out <= x"eb7ff085"; -- call recv_word 
-       when "1000000" => data_out <= x"e1300000"; -- mov r6, r0
-       when "1000001" => data_out <= x"eb7fef85"; -- call recv_word 
-       when "1000010" => data_out <= x"e7830000"; -- stw r0, 0(r6)
-       when "1000011" => data_out <= x"ed080208"; -- ldi r1, 0x41 
-       when "1000100" => data_out <= x"eb7fe405"; -- call send_byte
-       when "1000101" => data_out <= x"eb7ff481"; -- br bootrom
+       when "1000000" => data_out <= x"e7858008"; -- stw r0, PDATA(r11)
+       when "1000001" => data_out <= x"ed080220"; -- ldi r1, 0x44 
+       when "1000010" => data_out <= x"eb7fe505"; -- call send_byte
+       when "1000011" => data_out <= x"eb7ff581"; -- br bootrom
+       when "1000100" => data_out <= x"ed080288"; -- ldi r1, 0x51 
+       when "1000101" => data_out <= x"eb7fe385"; -- call send_byte
        when "1000110" => data_out <= x"eb7fed05"; -- call recv_word 
-       when "1000111" => data_out <= x"e1100000"; -- mov r2, r0
-       when "1001000" => data_out <= x"ed080238"; -- ldi r1, 0x47 
-       when "1001001" => data_out <= x"eb7fe185"; -- call send_byte
-       when "1001010" => data_out <= x"e7090000"; -- ldw r1, 0(r2)
-       when "1001011" => data_out <= x"eb7fe305"; -- call send_word
+       when "1000111" => data_out <= x"e1300000"; -- addi r6, r0, 0
+       when "1001000" => data_out <= x"eb7fec05"; -- call recv_word 
+       when "1001001" => data_out <= x"e7830000"; -- stw r0, 0(r6)
+       when "1001010" => data_out <= x"ed080208"; -- ldi r1, 0x41 
+       when "1001011" => data_out <= x"eb7fe085"; -- call send_byte
        when "1001100" => data_out <= x"eb7ff101"; -- br bootrom
-       when "1001101" => data_out <= x"eb7fe985"; -- call recv_word
-       when "1001110" => data_out <= x"eb800000"; -- brr r0
-       when "1001111" => data_out <= x"e4088800"; -- xor r1, r1, r1
-       when "1010000" => data_out <= x"ed080208"; -- ldi r1, 0x41 
-       when "1010001" => data_out <= x"eb7fdd85"; -- call send_byte
-       when "1010010" => data_out <= x"e4088800"; -- xor r1, r1, r1
-       when "1010011" => data_out <= x"ed080210"; -- ldi r1, 0x42 
-       when "1010100" => data_out <= x"eb7fdc05"; -- call send_byte
-       when "1010101" => data_out <= x"e4088800"; -- xor r1, r1, r1
-       when "1010110" => data_out <= x"ed080218"; -- ldi r1, 0x43 
-       when "1010111" => data_out <= x"eb7fda85"; -- call send_byte
+       when "1001101" => data_out <= x"eb7fe985"; -- call recv_word 
+       when "1001110" => data_out <= x"e1100000"; -- mov r2, r0
+       when "1001111" => data_out <= x"ed080238"; -- ldi r1, 0x47 
+       when "1010000" => data_out <= x"eb7fde05"; -- call send_byte
+       when "1010001" => data_out <= x"e7090000"; -- ldw r1, 0(r2)
+       when "1010010" => data_out <= x"eb7fdf85"; -- call send_word
+       when "1010011" => data_out <= x"eb7fed81"; -- br bootrom
+       when "1010100" => data_out <= x"e4088800"; -- xor r1, r1, r1
+       when "1010101" => data_out <= x"ed080208"; -- ldi r1, 0x41 
+       when "1010110" => data_out <= x"eb7fdb05"; -- call send_byte
+       when "1010111" => data_out <= x"e4088800"; -- xor r1, r1, r1
+       when "1011000" => data_out <= x"ed080210"; -- ldi r1, 0x42 
+       when "1011001" => data_out <= x"eb7fd985"; -- call send_byte
+       when "1011010" => data_out <= x"e4088800"; -- xor r1, r1, r1
+       when "1011011" => data_out <= x"ed080218"; -- ldi r1, 0x43 
+       when "1011100" => data_out <= x"eb7fd805"; -- call send_byte
        -- just nop until rom end!
        when others => data_out <= x"fd000000";
                        end case;
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644 (file)
index 0000000..05f4883
--- /dev/null
@@ -0,0 +1 @@
+SerialPort_linux.pyc
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644 (file)
index 0000000..38ccd0d
--- /dev/null
@@ -0,0 +1,4 @@
+all: pylint
+
+pylint: frprog.py
+       pylint --indent-string="\t" $<
diff --git a/tools/SerialPort_linux.py b/tools/SerialPort_linux.py
new file mode 100644 (file)
index 0000000..de8d697
--- /dev/null
@@ -0,0 +1,329 @@
+# -*- coding: iso-8859-1 -*-\r
+\r
+##########################################################################\r
+# USPP Library (Universal Serial Port Python Library)\r
+#\r
+# Copyright (C) 2006 Isaac Barona <ibarona@gmail.com>\r
+# \r
+# This library is free software; you can redistribute it and/or\r
+# modify it under the terms of the GNU Lesser General Public\r
+# License as published by the Free Software Foundation; either\r
+# version 2.1 of the License, or (at your option) any later version.\r
+# \r
+# This library is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+# Lesser General Public License for more details.\r
+\r
+# You should have received a copy of the GNU Lesser General Public\r
+# License along with this library; if not, write to the Free Software\r
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+##########################################################################\r
+\r
+#------------------------------------------------------------------------\r
+# Project:   USPP Library (Universal Serial Port Python Library)\r
+# Name:      SerialPort_linux.py\r
+# Purpose:   Handle low level access to serial port in linux.\r
+#\r
+# Author:    Isaac Barona Martinez <ibarona@gmail.com>\r
+# Copyright: (c) 2006 by Isaac Barona Martínez\r
+# Licence:   LGPL\r
+#\r
+# Created:   26 June 2001\r
+# History:\r
+# 20 January 2002 : Damien Geranton <dgeranton@voila.fr>\r
+#  - NCCS worry fixed. We must not use TERMIOS\r
+#  - inWaiting call fixed.\r
+# 09 Sept 2005: Douglas Jones <dfj23@drexel.edu>\r
+#  - readline method.\r
+#\r
+#-------------------------------------------------------------------------\r
+\r
+"""\r
+SerialPort_linux.py - Handle low level access to serial port in linux.\r
+\r
+See also uspp module docstring.\r
+\r
+\r
+"""\r
+\r
+import os\r
+from termios import *\r
+import fcntl\r
+import exceptions\r
+import struct\r
+import array\r
+\r
+\r
+class SerialPortException(exceptions.Exception):\r
+    """Exception raise in the SerialPort methods"""\r
+    def __init__(self, args=None):\r
+        self.args=args\r
+\r
+\r
+class SerialPort:\r
+    """Encapsulate methods for accesing to a serial port."""\r
+\r
+    BaudRatesDic={\r
+        110: B110,\r
+        300: B300,\r
+        600: B600,\r
+        1200: B1200,\r
+        2400: B2400,\r
+        4800: B4800, \r
+        9600: B9600,\r
+        19200: B19200,\r
+        38400: B38400,\r
+        57600: B57600,\r
+        115200: B115200\r
+        }\r
+    buf = array.array('h', '\000'*4)\r
+\r
+    def __init__(self, dev, timeout=None, speed=None, mode='232', params=None):\r
+        """Open the serial port named by the string 'dev'\r
+\r
+        'dev' can be any of the following strings: '/dev/ttyS0', '/dev/ttyS1',\r
+        ..., '/dev/ttySX' or '/dev/cua0', '/dev/cua1', ..., '/dev/cuaX'.\r
+        \r
+        'timeout' specifies the inter-byte timeout or first byte timeout\r
+        (in miliseconds) for all subsequent reads on SerialPort.\r
+        If we specify None time-outs are not used for reading operations\r
+        (blocking reading).\r
+        If 'timeout' is 0 then reading operations are non-blocking. It\r
+        specifies that the reading operation is to return inmediately\r
+        with the bytes that have already been received, even if\r
+        no bytes have been received.\r
+        \r
+        'speed' is an integer that specifies the input and output baud rate to\r
+        use. Possible values are: 110, 300, 600, 1200, 2400, 4800, 9600,\r
+        19200, 38400, 57600 and 115200.\r
+        If None a default speed of 9600 bps is selected.\r
+        \r
+        'mode' specifies if we are using RS-232 or RS-485. The RS-485 mode\r
+        is half duplex and use the RTS signal to indicate the\r
+        direction of the communication (transmit or recive).\r
+        Default to RS232 mode (at moment, only the RS-232 mode is\r
+        implemented).\r
+\r
+        'params' is a list that specifies properties of the serial \r
+        communication.\r
+        If params=None it uses default values for the number of bits\r
+        per byte (8), the parity (NOPARITY) and the number of stop bits (1)\r
+        else params is the termios package mode array to use for \r
+        initialization.\r
+\r
+        """\r
+        self.__devName, self.__timeout, self.__speed=dev, timeout, speed\r
+        self.__mode=mode\r
+        self.__params=params\r
+        try:\r
+               self.__handle=os.open(dev, os.O_RDWR)\r
+        except:\r
+            raise SerialPortException('Unable to open port')\r
+\r
+        self.__configure()\r
+\r
+    def __del__(self):\r
+        """Close the serial port and restore its initial configuration\r
+        \r
+        To close the serial port we have to do explicity: del s\r
+        (where s is an instance of SerialPort)\r
+        """\r
+       \r
+       tcsetattr(self.__handle, TCSANOW, self.__oldmode)\r
+       \r
+        try:\r
+            os.close(self.__handle)\r
+        except IOError:\r
+            raise SerialPortException('Unable to close port')\r
+\r
+\r
+    def __configure(self):\r
+        """Configure the serial port.\r
+\r
+        Private method called in the class constructor that configure the \r
+        serial port with the characteristics given in the constructor.\r
+        """\r
+        if not self.__speed:\r
+            self.__speed=9600\r
+        \r
+        # Save the initial port configuration\r
+        self.__oldmode=tcgetattr(self.__handle)\r
+        if not self.__params:\r
+            # self.__params is a list of attributes of the file descriptor\r
+            # self.__handle as follows:\r
+            # [c_iflag, c_oflag, c_cflag, c_lflag, c_ispeed, c_ospeed, cc]\r
+            # where cc is a list of the tty special characters.\r
+            self.__params=[]\r
+            # c_iflag\r
+            self.__params.append(IGNPAR)           \r
+            # c_oflag\r
+            self.__params.append(0)                \r
+            # c_cflag\r
+            self.__params.append(CS8|CLOCAL|CREAD) \r
+            # c_lflag\r
+            self.__params.append(0)                \r
+            # c_ispeed\r
+            self.__params.append(SerialPort.BaudRatesDic[self.__speed]) \r
+            # c_ospeed\r
+            self.__params.append(SerialPort.BaudRatesDic[self.__speed]) \r
+           cc=[0]*NCCS\r
+        if self.__timeout==None:\r
+            # A reading is only complete when VMIN characters have\r
+            # been received (blocking reading)\r
+            cc[VMIN]=1\r
+            cc[VTIME]=0\r
+        elif self.__timeout==0:\r
+            # Non-blocking reading. The reading operation returns\r
+            # inmeditately, returning the characters waiting to \r
+            # be read.\r
+            cc[VMIN]=0\r
+            cc[VTIME]=0\r
+        else:\r
+            # Time-out reading. For a reading to be correct\r
+            # a character must be recieved in VTIME*100 seconds.\r
+            cc[VMIN]=0\r
+            cc[VTIME]=self.__timeout/100\r
+        self.__params.append(cc)               # c_cc\r
+        \r
+        tcsetattr(self.__handle, TCSANOW, self.__params)\r
+    \r
+\r
+    def fileno(self):\r
+        """Return the file descriptor for opened device.\r
+\r
+        This information can be used for example with the \r
+        select funcion.\r
+        """\r
+        return self.__handle\r
+\r
+\r
+    def __read1(self):\r
+        """Read 1 byte from the serial port.\r
+\r
+        Generate an exception if no byte is read and self.timeout!=0 \r
+        because a timeout has expired.\r
+        """\r
+        byte = os.read(self.__handle, 1)\r
+        if len(byte)==0 and self.__timeout!=0: # Time-out\r
+            raise SerialPortException('Timeout')\r
+        else:\r
+            return byte\r
+            \r
+\r
+    def read(self, num=1):\r
+        """Read num bytes from the serial port.\r
+\r
+        Uses the private method __read1 to read num bytes. If an exception\r
+        is generated in any of the calls to __read1 the exception is reraised.\r
+        """\r
+        s=''\r
+        for i in range(num):\r
+            s=s+SerialPort.__read1(self)\r
+        \r
+        return s\r
+\r
+\r
+    def readline(self):\r
+        """Read a line from the serial port.  Returns input once a '\n'\r
+        character is found.\r
+        Douglas Jones (dfj23@drexel.edu) 09/09/2005.\r
+        """\r
+\r
+        s = ''\r
+        while not '\n' in s:\r
+            s = s+SerialPort.__read1(self)\r
+\r
+        return s \r
+\r
+        \r
+    def write(self, s):\r
+        """Write the string s to the serial port"""\r
+\r
+        os.write(self.__handle, s)\r
+\r
+        \r
+    def inWaiting(self):\r
+        """Returns the number of bytes waiting to be read"""\r
+       data = struct.pack("L", 0)\r
+        data=fcntl.ioctl(self.__handle, TIOCINQ, data)\r
+       return struct.unpack("L", data)[0]\r
+\r
+    def outWaiting(self):\r
+        """Returns the number of bytes waiting to be write\r
+        mod. by J.Grauheding\r
+        result needs some finetunning\r
+        """\r
+        rbuf=fcntl.ioctl(self.__handle, TIOCOUTQ, self.buf)\r
+        return rbuf\r
+\r
+    def getlsr(self):\r
+        """Returns the status of the UART LSR Register\r
+        J.Grauheding\r
+        """\r
+        rbuf=fcntl.ioctl(self.__handle, TIOCSERGETLSR, self.buf)\r
+        return ord(rbuf[0])\r
+\r
+    def get_temt(self):\r
+        """Returns the Tranmitterbuffer Empty Bit of LSR Register\r
+        J.Grauheding\r
+        test result against TIOCSER_TEMT\r
+        """\r
+        rbuf=fcntl.ioctl(self.__handle, TIOCSERGETLSR, self.buf)\r
+        return ord(rbuf[0]) & TIOSER_TEMT\r
+\r
+\r
+    def flush(self):\r
+        """Discards all bytes from the output or input buffer"""\r
+        tcflush(self.__handle, TCIOFLUSH)\r
+\r
+    def rts_on(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, SerialPort.buf)\r
+        SerialPort.buf[1] = ord(rbuf[3]) | TIOCM_RTS\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMSET, SerialPort.buf)\r
+        return rbuf\r
+\r
+    def rts_off(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        self.buf[1]=ord(rbuf[3]) & ~TIOCM_RTS\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMSET, self.buf)\r
+        return rbuf\r
+\r
+    def dtr_on(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, SerialPort.buf)\r
+        SerialPort.buf[1] = ord(rbuf[3]) | TIOCM_DTR\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMSET, SerialPort.buf)\r
+        return rbuf\r
+\r
+    def dtr_off(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        self.buf[1]=ord(rbuf[3]) & ~TIOCM_DTR\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMSET, self.buf)\r
+        return rbuf\r
+\r
+    def cts(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        return ord(rbuf[3]) & TIOCM_CTS\r
+\r
+    def cd(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        return ord(rbuf[3]) & TIOCM_CAR\r
+\r
+    def dsr(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        return ord(rbuf[2]) & (TIOCM_DSR>>8)\r
+\r
+    def ri(self):\r
+        """ J.Grauheding """\r
+        rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf)\r
+        return ord(rbuf[3]) & TIOCM_RNG\r
+\r
+        \r
+\r
diff --git a/tools/dtprog.py b/tools/dtprog.py
new file mode 100755 (executable)
index 0000000..de4633b
--- /dev/null
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+"""
+Aufruf:
+./dtprog.py <dthexfile> [-d /dev/ttyXXX]
+
+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
+
+'Q'0xZZZZZZZZ0xYYYYYYYY| H -> C    | write data (0xYY...Y) to
+                                   | address (0xZZ...Z)
+'A'                    | C -> H    | data write done
+
+'T'0xZZZZZZZZ          | H -> C    | read data from address (0xZZ..Z)
+'G'0xYYYYYYYY          | C -> H    | read done and return data
+
+'J'0xZZZZZZZZ          | H -> C    | jump to address (0xZZ...Z)
+"""
+import sys, time
+from SerialPort_linux import SerialPort, SerialPortException
+
+BAUDRATE = 9600
+SPLIT = 30
+
+class RAMSequence(object):
+       def __init__(self, type, address, data):
+               self.type = type
+               self.addr = address
+               self.data = data
+
+def sendbyte(byte):
+       """
+       send a byte to the TTY-device
+       """
+       tty.write(chr(byte))
+
+def sendword(word):
+       """
+       send a word to the TTY-device
+       """
+       sendbyte(word & 0xFF)
+       sendbyte((word >> 8) & 0xFF)
+
+def senddword(dword):
+       """
+       send a dword to the TTY-device
+       """
+       sendbyte((dword >> 24) & 0xFF)
+       sendbyte((dword >> 16) & 0xFF)
+       sendbyte((dword >> 8) & 0xFF)
+       sendbyte(dword & 0xFF)
+
+def recvbyte():
+       """
+       receive a byte from the TTY-device
+       """
+       return ord(tty.read())
+
+def recvword():
+       return (recvbyte() << 24) & (recvbyte() << 16) & (recvbyte() << 8) & recvbyte()
+
+def bootromexec():
+       sendbyte(0x4a) # 'J'
+
+def brwriteinstr(address, data):
+       """
+       send a WRITE-command (instr) to the bootROM-firmware
+       """
+       # send WRITE instr command
+       sendbyte(0x57) # 'W'
+       # time.sleep(0.01)
+       if (recvbyte() != 0x57): # 'W'
+               print "host: write instr fail (1)"
+               raise Exception
+       senddword(address)
+       senddword(data)
+       time.sleep(0.01)
+       if (recvbyte() != 0x44): # 'D'
+               print "host: write instr fail (2)"
+               raise Exception
+
+def brwritedata(address, data):
+       """
+       send a WRITE-command (data) to the bootROM-firmware
+       """
+       # send WRITE instr command
+       sendbyte(0x51) # 'Q'
+       # time.sleep(0.01)
+       if (recvbyte() != 0x51): # 'Q'
+               print "host: write data fail (1)"
+               raise Exception
+       senddword(address)
+       senddword(data)
+       time.sleep(0.01)
+       if (recvbyte() != 0x41): # 'A'
+               print "host: write data fail (2)"
+               raise Exception
+
+def readdthexfile(filename): # desired dthex filename
+       """
+       proceeds a dthex file
+       """
+       filep = open(filename, "r")
+       retval = [] # returns a list of FlashSequence objects
+       linecount = 0
+       for line in filep:
+               linecount += 1
+               # get rid of newline characters
+               line = line.strip()
+
+               # we're only interested in 0 or 1
+               if line[0:1] == "0" or line[0:1] == "1":
+                       # TODO: checks...
+                       type = int(line[0:1], 10)
+                       addr = int(line[2:10], 16)/4
+                       data = int(line[11:19], 16)
+                       # print "type: ", type, "; addr: ", hex(addr), "; data: ", hex(data)
+                       retval.append(RAMSequence(type, addr, data))
+       filep.close()
+       return retval
+
+def usage(execf):
+       """
+       print usage of dtprog
+       """
+       print "Usage: " + execf + " <target dthex-file> [-d DEVICE]"
+
+def main(argv=None):
+       """
+       main function of frprog
+       """
+       # check command line arguments
+       if argv is None:
+               argv = sys.argv
+
+       if len(argv) == 2 and (argv[1] == "-v" or argv[1] == "--version"):
+               print "Version: lulz"
+               return 0
+
+       if len(argv) != 2 and len(argv) != 4:
+               usage(argv[0])
+               return 1
+
+       # standard serial device to communicate with
+       device = "/dev/ttyS0"
+
+       # overrule standard device if provided with -d
+       if len(argv) == 4:
+               if argv[2] == "-d":
+                       device = argv[3]
+               else:
+                       usage(argv[0])
+                       return 1
+
+       # read in data from mhx-files before starting
+       try:
+               ramseqs = readdthexfile(argv[1])
+       except IOError, error:
+               print argv[0] + ": Error - couldn't open file " + error.filename + "!"
+               return 1
+
+       print "Initializing serial port... (", device, ")"
+       global tty
+       tty = SerialPort(device, 100, BAUDRATE)
+
+       while True:
+               tty.write('H')
+               tty.flush()
+               try:
+                       if tty.read() == 'O':
+                               break
+               except SerialPortException:
+                       # timeout happened, who cares ;-)
+                       print "host: cpu in BootROM?"
+                       pass
+       print "bootrom: OH HAI!"
+
+       # save time at this point for evaluating the duration at the end
+       starttime = time.time()
+       time.sleep(0.1)
+
+       sdots = SPLIT
+       print "host: Transfering program to BootROM",
+       print #TODO: remove ;)
+       # let the fun begin!
+       for seq in ramseqs:
+               print "RAMing(", seq.type, ") ", hex(seq.data), " at address ",
+               if seq.type == 1:
+                       # instruction
+                       print "", hex(seq.addr)
+                       print "host: writing instr"
+                       brwriteinstr(seq.addr, seq.data)
+               elif seq.type == 0:
+                       # data
+                       print "", hex(seq.addr*4)
+                       print "host: writing data"
+                       brwritedata(seq.addr * 4, seq.data)
+               tty.flush()
+
+               sdots = sdots - 1
+               if sdots == 0:
+                       sys.stdout.write(".")
+                       sys.stdout.flush()
+                       sdots = SPLIT
+       print
+
+       bootromexec()
+       print "Program was started. Have fun!"
+       duration = time.time() - starttime
+       print "Procedure complete, took", round(duration, 2), "seconds."
+
+if __name__ == '__main__':
+       sys.exit(main())