build/openocd: add stream method for JTAG UART
This commit is contained in:
parent
b356204f95
commit
bd6ec63be4
|
@ -1,9 +1,11 @@
|
|||
# This file is Copyright (c) 2015 Robert Jordens <jordens@gmail.com>
|
||||
# This file is Copyright (c) 2015-2017 Robert Jordens <jordens@gmail.com>
|
||||
# This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
|
||||
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
import subprocess
|
||||
|
||||
from litex.build.tools import write_to_file
|
||||
from litex.build.generic_programmer import GenericProgrammer
|
||||
|
||||
|
||||
|
@ -32,3 +34,107 @@ class OpenOCD(GenericProgrammer):
|
|||
"exit"
|
||||
])
|
||||
subprocess.call(["openocd", "-f", self.config, "-c", script])
|
||||
|
||||
|
||||
def stream(self, port=20000):
|
||||
"""
|
||||
Create a Telnet server to stream data to/from the internal JTAG TAP of the FPGA
|
||||
|
||||
Wire format: 10 bits LSB first
|
||||
Host to Target:
|
||||
- TX ready : bit 0
|
||||
- RX data: : bit 1 to 8
|
||||
- RX valid : bit 9
|
||||
|
||||
Target to Host:
|
||||
- RX ready : bit 0
|
||||
- TX data : bit 1 to 8
|
||||
- TX valid : bit 9
|
||||
"""
|
||||
cfg = """
|
||||
proc jtagstream_poll {tap tx n} {
|
||||
set m [string length $tx]
|
||||
set n [expr ($m>$n)?$m:$n]
|
||||
set txi [lrepeat $n {10 0x001}]
|
||||
set i 0
|
||||
foreach txj [split $tx ""] {
|
||||
lset txi $i 1 [format 0x%4.4X [expr 0x201 | ([scan $txj %c] << 1)]]
|
||||
incr i
|
||||
}
|
||||
set txi [concat {*}$txi]
|
||||
set rxi [split [drscan $tap {*}$txi -endstate DRPAUSE] " "]
|
||||
#echo $txi:$rxi
|
||||
set rx ""
|
||||
set writable 1
|
||||
foreach {rxj} $rxi {
|
||||
set readable [expr 0x$rxj & 0x200]
|
||||
set writable [expr 0x$rxj & $writable]
|
||||
if {$readable} {
|
||||
append rx [format %c [expr (0x$rxj >> 1) & 0xff]]
|
||||
}
|
||||
}
|
||||
return [list $rx $readable $writable]
|
||||
}
|
||||
|
||||
proc jtagstream_drain {tap tx chunk_rx max_rx} {
|
||||
lassign [jtagstream_poll $tap $tx $chunk_rx] rx readable writable
|
||||
while {[expr $writable && ($readable > 0) && ([string length $rx] < $max_rx)]} {
|
||||
lassign [jtagstream_poll $tap "" $chunk_rx] rxi readable writable
|
||||
append rx $rxi
|
||||
}
|
||||
if {!$writable} {
|
||||
echo "write overflow"
|
||||
}
|
||||
return $rx
|
||||
}
|
||||
|
||||
proc jtagstream_rxtx {tap client is_poll} {
|
||||
if {![$client eof]} {
|
||||
if {!$is_poll} {
|
||||
set tx [$client gets]
|
||||
} else {
|
||||
set tx ""
|
||||
}
|
||||
set rx [jtagstream_drain $tap $tx 64 4096]
|
||||
if {[string length $rx]} {
|
||||
$client puts -nonewline $rx
|
||||
}
|
||||
if {$is_poll} {
|
||||
after 1 [list jtagstream_rxtx $tap $client 1]
|
||||
}
|
||||
} else {
|
||||
$client readable {}
|
||||
$client onexception {}
|
||||
$client close
|
||||
}
|
||||
}
|
||||
|
||||
proc jtagstream_client {tap sock} {
|
||||
set client [$sock accept]
|
||||
fconfigure $client -buffering none
|
||||
$client readable [list jtagstream_rxtx $tap $client 0]
|
||||
$client onexception [list $client close]
|
||||
after 1 [list jtagstream_rxtx $tap $client 1]
|
||||
}
|
||||
|
||||
proc jtagstream_exit {sock} {
|
||||
stdin readable {}
|
||||
$sock readable {}
|
||||
}
|
||||
|
||||
proc jtagstream_serve {tap port} {
|
||||
set sock [socket stream.server $port]
|
||||
$sock readable [list jtagstream_client $tap $sock]
|
||||
stdin readable [list jtagstream_exit $sock]
|
||||
vwait forever
|
||||
$sock close
|
||||
}
|
||||
"""
|
||||
write_to_file("stream.cfg", cfg)
|
||||
script = "; ".join([
|
||||
"init",
|
||||
"irscan $_CHIPNAME.tap $_USER1",
|
||||
"jtagstream_serve $_CHIPNAME.tap {:d}".format(port),
|
||||
"exit",
|
||||
])
|
||||
subprocess.call(["openocd", "-f", self.config, "-f", "stream.cfg", "-c", script])
|
||||
|
|
Loading…
Reference in New Issue