From 5615b8e50fe3adabbdf4da3078245c9e47700ffc Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 11 Jan 2011 18:11:30 +0100 Subject: [PATCH] bootromfun/dtprog: programmer fuers BootROM \o/ for usage see tools/dtprog.py --- 2_isa/src/bootrom.s | 58 +++++-- 3_test/uartint.s | 68 ++++++-- cpu/src/rom_b.vhd | 83 +++++----- tools/.gitignore | 1 + tools/Makefile | 4 + tools/SerialPort_linux.py | 329 ++++++++++++++++++++++++++++++++++++++ tools/dtprog.py | 226 ++++++++++++++++++++++++++ 7 files changed, 702 insertions(+), 67 deletions(-) create mode 100644 tools/.gitignore create mode 100644 tools/Makefile create mode 100644 tools/SerialPort_linux.py create mode 100755 tools/dtprog.py diff --git a/2_isa/src/bootrom.s b/2_isa/src/bootrom.s index 87b7f83..bfc8189 100644 --- a/2_isa/src/bootrom.s +++ b/2_isa/src/bootrom.s @@ -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' diff --git a/3_test/uartint.s b/3_test/uartint.s index 8afa8f2..ed9df57 100644 --- a/3_test/uartint.s +++ b/3_test/uartint.s @@ -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 diff --git a/cpu/src/rom_b.vhd b/cpu/src/rom_b.vhd index 82c954b..8606702 100644 --- a/cpu/src/rom_b.vhd +++ b/cpu/src/rom_b.vhd @@ -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 index 0000000..05f4883 --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1 @@ +SerialPort_linux.pyc diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..38ccd0d --- /dev/null +++ b/tools/Makefile @@ -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 index 0000000..de8d697 --- /dev/null +++ b/tools/SerialPort_linux.py @@ -0,0 +1,329 @@ +# -*- coding: iso-8859-1 -*- + +########################################################################## +# USPP Library (Universal Serial Port Python Library) +# +# Copyright (C) 2006 Isaac Barona +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +########################################################################## + +#------------------------------------------------------------------------ +# Project: USPP Library (Universal Serial Port Python Library) +# Name: SerialPort_linux.py +# Purpose: Handle low level access to serial port in linux. +# +# Author: Isaac Barona Martinez +# Copyright: (c) 2006 by Isaac Barona Martínez +# Licence: LGPL +# +# Created: 26 June 2001 +# History: +# 20 January 2002 : Damien Geranton +# - NCCS worry fixed. We must not use TERMIOS +# - inWaiting call fixed. +# 09 Sept 2005: Douglas Jones +# - readline method. +# +#------------------------------------------------------------------------- + +""" +SerialPort_linux.py - Handle low level access to serial port in linux. + +See also uspp module docstring. + + +""" + +import os +from termios import * +import fcntl +import exceptions +import struct +import array + + +class SerialPortException(exceptions.Exception): + """Exception raise in the SerialPort methods""" + def __init__(self, args=None): + self.args=args + + +class SerialPort: + """Encapsulate methods for accesing to a serial port.""" + + BaudRatesDic={ + 110: B110, + 300: B300, + 600: B600, + 1200: B1200, + 2400: B2400, + 4800: B4800, + 9600: B9600, + 19200: B19200, + 38400: B38400, + 57600: B57600, + 115200: B115200 + } + buf = array.array('h', '\000'*4) + + def __init__(self, dev, timeout=None, speed=None, mode='232', params=None): + """Open the serial port named by the string 'dev' + + 'dev' can be any of the following strings: '/dev/ttyS0', '/dev/ttyS1', + ..., '/dev/ttySX' or '/dev/cua0', '/dev/cua1', ..., '/dev/cuaX'. + + 'timeout' specifies the inter-byte timeout or first byte timeout + (in miliseconds) for all subsequent reads on SerialPort. + If we specify None time-outs are not used for reading operations + (blocking reading). + If 'timeout' is 0 then reading operations are non-blocking. It + specifies that the reading operation is to return inmediately + with the bytes that have already been received, even if + no bytes have been received. + + 'speed' is an integer that specifies the input and output baud rate to + use. Possible values are: 110, 300, 600, 1200, 2400, 4800, 9600, + 19200, 38400, 57600 and 115200. + If None a default speed of 9600 bps is selected. + + 'mode' specifies if we are using RS-232 or RS-485. The RS-485 mode + is half duplex and use the RTS signal to indicate the + direction of the communication (transmit or recive). + Default to RS232 mode (at moment, only the RS-232 mode is + implemented). + + 'params' is a list that specifies properties of the serial + communication. + If params=None it uses default values for the number of bits + per byte (8), the parity (NOPARITY) and the number of stop bits (1) + else params is the termios package mode array to use for + initialization. + + """ + self.__devName, self.__timeout, self.__speed=dev, timeout, speed + self.__mode=mode + self.__params=params + try: + self.__handle=os.open(dev, os.O_RDWR) + except: + raise SerialPortException('Unable to open port') + + self.__configure() + + def __del__(self): + """Close the serial port and restore its initial configuration + + To close the serial port we have to do explicity: del s + (where s is an instance of SerialPort) + """ + + tcsetattr(self.__handle, TCSANOW, self.__oldmode) + + try: + os.close(self.__handle) + except IOError: + raise SerialPortException('Unable to close port') + + + def __configure(self): + """Configure the serial port. + + Private method called in the class constructor that configure the + serial port with the characteristics given in the constructor. + """ + if not self.__speed: + self.__speed=9600 + + # Save the initial port configuration + self.__oldmode=tcgetattr(self.__handle) + if not self.__params: + # self.__params is a list of attributes of the file descriptor + # self.__handle as follows: + # [c_iflag, c_oflag, c_cflag, c_lflag, c_ispeed, c_ospeed, cc] + # where cc is a list of the tty special characters. + self.__params=[] + # c_iflag + self.__params.append(IGNPAR) + # c_oflag + self.__params.append(0) + # c_cflag + self.__params.append(CS8|CLOCAL|CREAD) + # c_lflag + self.__params.append(0) + # c_ispeed + self.__params.append(SerialPort.BaudRatesDic[self.__speed]) + # c_ospeed + self.__params.append(SerialPort.BaudRatesDic[self.__speed]) + cc=[0]*NCCS + if self.__timeout==None: + # A reading is only complete when VMIN characters have + # been received (blocking reading) + cc[VMIN]=1 + cc[VTIME]=0 + elif self.__timeout==0: + # Non-blocking reading. The reading operation returns + # inmeditately, returning the characters waiting to + # be read. + cc[VMIN]=0 + cc[VTIME]=0 + else: + # Time-out reading. For a reading to be correct + # a character must be recieved in VTIME*100 seconds. + cc[VMIN]=0 + cc[VTIME]=self.__timeout/100 + self.__params.append(cc) # c_cc + + tcsetattr(self.__handle, TCSANOW, self.__params) + + + def fileno(self): + """Return the file descriptor for opened device. + + This information can be used for example with the + select funcion. + """ + return self.__handle + + + def __read1(self): + """Read 1 byte from the serial port. + + Generate an exception if no byte is read and self.timeout!=0 + because a timeout has expired. + """ + byte = os.read(self.__handle, 1) + if len(byte)==0 and self.__timeout!=0: # Time-out + raise SerialPortException('Timeout') + else: + return byte + + + def read(self, num=1): + """Read num bytes from the serial port. + + Uses the private method __read1 to read num bytes. If an exception + is generated in any of the calls to __read1 the exception is reraised. + """ + s='' + for i in range(num): + s=s+SerialPort.__read1(self) + + return s + + + def readline(self): + """Read a line from the serial port. Returns input once a '\n' + character is found. + Douglas Jones (dfj23@drexel.edu) 09/09/2005. + """ + + s = '' + while not '\n' in s: + s = s+SerialPort.__read1(self) + + return s + + + def write(self, s): + """Write the string s to the serial port""" + + os.write(self.__handle, s) + + + def inWaiting(self): + """Returns the number of bytes waiting to be read""" + data = struct.pack("L", 0) + data=fcntl.ioctl(self.__handle, TIOCINQ, data) + return struct.unpack("L", data)[0] + + def outWaiting(self): + """Returns the number of bytes waiting to be write + mod. by J.Grauheding + result needs some finetunning + """ + rbuf=fcntl.ioctl(self.__handle, TIOCOUTQ, self.buf) + return rbuf + + def getlsr(self): + """Returns the status of the UART LSR Register + J.Grauheding + """ + rbuf=fcntl.ioctl(self.__handle, TIOCSERGETLSR, self.buf) + return ord(rbuf[0]) + + def get_temt(self): + """Returns the Tranmitterbuffer Empty Bit of LSR Register + J.Grauheding + test result against TIOCSER_TEMT + """ + rbuf=fcntl.ioctl(self.__handle, TIOCSERGETLSR, self.buf) + return ord(rbuf[0]) & TIOSER_TEMT + + + def flush(self): + """Discards all bytes from the output or input buffer""" + tcflush(self.__handle, TCIOFLUSH) + + def rts_on(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, SerialPort.buf) + SerialPort.buf[1] = ord(rbuf[3]) | TIOCM_RTS + rbuf = fcntl.ioctl(self.__handle, TIOCMSET, SerialPort.buf) + return rbuf + + def rts_off(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + self.buf[1]=ord(rbuf[3]) & ~TIOCM_RTS + rbuf = fcntl.ioctl(self.__handle, TIOCMSET, self.buf) + return rbuf + + def dtr_on(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, SerialPort.buf) + SerialPort.buf[1] = ord(rbuf[3]) | TIOCM_DTR + rbuf = fcntl.ioctl(self.__handle, TIOCMSET, SerialPort.buf) + return rbuf + + def dtr_off(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + self.buf[1]=ord(rbuf[3]) & ~TIOCM_DTR + rbuf = fcntl.ioctl(self.__handle, TIOCMSET, self.buf) + return rbuf + + def cts(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + return ord(rbuf[3]) & TIOCM_CTS + + def cd(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + return ord(rbuf[3]) & TIOCM_CAR + + def dsr(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + return ord(rbuf[2]) & (TIOCM_DSR>>8) + + def ri(self): + """ J.Grauheding """ + rbuf = fcntl.ioctl(self.__handle, TIOCMGET, self.buf) + return ord(rbuf[3]) & TIOCM_RNG + + + diff --git a/tools/dtprog.py b/tools/dtprog.py new file mode 100755 index 0000000..de4633b --- /dev/null +++ b/tools/dtprog.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +""" +Aufruf: +./dtprog.py [-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 + " [-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()) -- 2.25.1