Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
Conv TTL Blocking
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Conv TTL Blocking
Commits
1c09a3a4
Commit
1c09a3a4
authored
Oct 14, 2013
by
Theodor-Adrian Stana
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Made multiboot bitstream write faster
Signed-off-by:
Theodor Stana
<
t.stana@cern.ch
>
parent
b271de9b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
170 additions
and
93 deletions
+170
-93
conv-ttl-blo-gw
conv-ttl-blo-gw
+1
-1
multiboot.py
test/multiboot/multiboot.py
+163
-87
vbcp.py
test/vbcp/vbcp.py
+6
-5
No files found.
conv-ttl-blo-gw
@
bfa6c70e
Subproject commit
a8a7895b66140533af2e580c9898c4f58dab747f
Subproject commit
bfa6c70eec6fe363e70c99ffab3266e0a6bd92a5
test/multiboot/multiboot.py
View file @
1c09a3a4
...
...
@@ -13,6 +13,8 @@
# dependencies:
#
# references:
# [1] M25P32 32Mb 3V NOR Serial Flash Embedded Memory
# http://cern.ch/go/z7pw
#===============================================================================
# GNU LESSER GENERAL PUBLIC LICENSE
#===============================================================================
...
...
@@ -37,84 +39,132 @@ import sys
import
time
sys
.
path
.
append
(
"../vbcp"
)
from
vbcp
import
*
from
vbcpexcept
import
*
def
spi_transfer
(
cs
,
dat
):
# This function handles the OR-ing together of the data bytes and the control
# byte in FAR.
#
# Formatting of data bytes in the FAR register should be done outside this
# function.
def
spi_transfer
(
nbytes
,
cs
,
dat
):
retval
=
0
wval
=
[]
# control byte, to be shifted left by 24
ctrl
=
((
cs
<<
3
)
|
0x4
)
|
(
nbytes
-
1
)
# Use appropriate command by type
#
# write - we send up to three data bytes in one FAR register write
# writemregs - we send up to 24 data bytes in eight FAR register writes
if
isinstance
(
dat
,
int
):
ctb
.
write
(
0x90
,
(
((
cs
<<
10
)
|
0x100
)
|
dat
)
)
ctb
.
write
(
0x90
,
(
ctrl
<<
24
)
|
dat
)
else
:
for
i
in
xrange
(
len
(
dat
)):
wval
.
append
((
((
cs
<<
10
)
|
0x100
)
|
dat
[
i
])
)
wval
.
append
((
ctrl
<<
24
)
|
dat
[
i
]
)
ctb
.
writemregs
(
0x90
,
wval
)
while
(
retval
&
(
1
<<
9
)
==
0
):
# Read the data and prepare the return value
while
(
retval
&
(
1
<<
28
)
==
0
):
retval
=
ctb
.
read
(
0x90
)
return
retval
&
0xFF
# while (retval & (1 << 9) == 0):
# retval = ctb.read(0x90)
# return retval & 0xFF
return
retval
&
0xFFFFFF
# This function is used to write data bytes to flash. It calls spi_transfer
# and sends the commands to the flash chip. You can follow the logic of this
# function by looking at the sequence of the write command in [1]
def
flash_write
(
addr
,
dat
):
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
0x06
)
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,[
0x02
,(
addr
&
0xFF0000
)
>>
16
,(
addr
&
0xFF00
)
>>
8
,
(
addr
&
0xFF
)])
for
i
in
xrange
(
0
,
len
(
dat
),
4
):
spi_transfer
(
1
,[
dat
[
i
],
dat
[
i
+
1
],
dat
[
i
+
2
],
dat
[
i
+
3
]])
spi_transfer
(
0
,
0
)
# spi_transfer(0,0)
# spi_transfer(1,0x06)
# spi_transfer(0,0)
# spi_transfer(1,0x02)
# spi_transfer(1,(addr & 0xFF0000) >> 16)
# spi_transfer(1,(addr & 0xFF00) >> 8)
# spi_transfer(1,(addr & 0xFF))
# for i in range(len(dat)):
# spi_transfer(1,dat[i])
# spi_transfer(0,0)
# write enable cmd
spi_transfer
(
1
,
1
,
0x06
)
spi_transfer
(
1
,
0
,
0
)
# write page cmd
spi_transfer
(
1
,
1
,
0x02
)
# send address in reverse order
addr
=
((
addr
&
0xff0000
)
>>
16
)
|
(((
addr
&
0xff00
)
>>
8
)
<<
8
)
|
((
addr
&
0xff
)
<<
16
)
spi_transfer
(
3
,
1
,
addr
)
# Now, massage the data array into 3-byte commands sent into 32-bit register,
# in batches of eight registers (writemregs command).
i
=
0
l
=
len
(
dat
)
while
(
l
):
wval
=
[]
# If we have more than 24 bytes left in the data array, we can use the full
# writemregs
if
(
int
(
l
/
24
)):
for
j
in
xrange
(
0
,
8
):
wval
.
append
((
dat
[(
i
+
2
)
+
3
*
j
]
<<
16
)
|
(
dat
[(
i
+
1
)
+
3
*
j
]
<<
8
)
|
dat
[
i
+
3
*
j
])
spi_transfer
(
3
,
1
,
wval
)
i
+=
24
;
l
-=
24
;
# When we're left to fewer than 24 bytes in the array, try to use one more
# writemregs with as many regs as possible
elif
(
int
(
l
/
3
)):
for
j
in
xrange
(
0
,
l
/
3
):
wval
.
append
((
dat
[(
i
+
2
)
+
3
*
j
]
<<
16
)
|
(
dat
[(
i
+
1
)
+
3
*
j
]
<<
8
)
|
dat
[
i
+
3
*
j
])
spi_transfer
(
3
,
1
,
wval
);
i
+=
3
*
int
(
l
/
3
)
l
-=
3
*
int
(
l
/
3
)
# When we're down to less than three bytes, just use simple one-byte xfers
elif
(
l
):
for
j
in
xrange
(
0
,
l
):
spi_transfer
(
1
,
1
,
dat
[
i
])
i
+=
1
l
-=
1
spi_transfer
(
1
,
0
,
0
)
# This function is used to read a number of data bytes from the flash memory
# It returns the values of the three consecutive flash registers packed into
# one 24-bit data value in little-endian order
def
flash_read
(
addr
,
nrbytes
):
ret
=
[]
spi_transfer
(
0
,
0
)
#spi_transfer(1,0x0b)
#spi_transfer(1,(addr & 0xFF0000) >> 16)
#spi_transfer(1,(addr & 0xFF00) >> 8)
#spi_transfer(1,(addr & 0xFF))
spi_transfer
(
1
,[
0x0b
,
(
addr
&
0xFF0000
)
>>
16
,(
addr
&
0xFF00
)
>>
8
,
(
addr
&
0xFF
)])
spi_transfer
(
1
,
0
)
spi_transfer
(
1
,
1
,
0x0b
)
# send address in reverse order
addr
=
((
addr
&
0xff0000
)
>>
16
)
|
(((
addr
&
0xff00
)
>>
8
)
<<
8
)
|
((
addr
&
0xff
)
<<
16
)
spi_transfer
(
3
,
1
,
addr
)
spi_transfer
(
1
,
1
,
0
)
# Read bytes in groups of three
for
i
in
range
(
nrbytes
):
ret
.
append
(
spi_transfer
(
1
,
0
))
spi_transfer
(
0
,
0
)
ret
.
append
(
spi_transfer
(
3
,
1
,
0
))
spi_transfer
(
1
,
0
,
0
)
return
ret
# Send a sector erase command
def
flash_serase
(
addr
):
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
0x06
)
spi_transfer
(
0
,
0
)
#spi_transfer(1,0xd8)
#spi_transfer(1,(addr & 0xFF0000) >> 16)
#spi_transfer(1,(addr & 0xFF00) >> 8)
#spi_transfer(1,(addr & 0xFF))
spi_transfer
(
1
,[
0xd8
,
(
addr
&
0xFF0000
)
>>
16
,(
addr
&
0xFF00
)
>>
8
,
(
addr
&
0xFF
)])
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
1
,
0x06
)
spi_transfer
(
1
,
0
,
0
)
# send address in reverse order
addr
=
((
addr
&
0xff0000
)
>>
16
)
|
(((
addr
&
0xff00
)
>>
8
)
<<
8
)
|
((
addr
&
0xff
)
<<
16
)
spi_transfer
(
3
,
1
,
addr
)
spi_transfer
(
1
,
0
,
0
)
# Send a block erase command
def
flash_berase
():
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
0x06
)
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
0xc7
)
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
1
,
0x06
)
spi_transfer
(
1
,
0
,
0
)
spi_transfer
(
1
,
1
,
0xc7
)
spi_transfer
(
1
,
0
,
0
)
# Read status register command
def
flash_rsr
():
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
0x05
)
ret
=
spi_transfer
(
1
,
0
)
spi_transfer
(
0
,
0
)
spi_transfer
(
1
,
1
,
0x05
)
ret
=
spi_transfer
(
1
,
1
,
0
)
spi_transfer
(
1
,
0
,
0
)
return
ret
# MAIN "FUNCTION"
if
__name__
==
"__main__"
:
ip
=
"192.168.20.22"
# raw_input("Crate IP? ")
user
=
"admin"
# raw_input("Username? ")
...
...
@@ -137,60 +187,51 @@ if __name__ == "__main__":
except
:
print
"Unexpected error: "
,
sys
.
exc_info
()[
0
]
# Ask for multiboot address
while
1
:
try
:
multiboot_addr
=
raw_input
(
"MultiBoot bitstream address (hex): "
)
multiboot_addr
=
int
(
multiboot_addr
,
16
)
print
'0x
%06
x'
%
multiboot_addr
break
except
TypeError
as
e
:
print
"Please input a hexadecimal address!"
except
KeyboardInterrupt
:
sys
.
exit
()
except
:
print
"Unexpected error: "
,
sys
.
exc_info
()[
0
]
ts
=
time
.
time
()
# Open VBCP connection
ctb
.
open_conn
()
# Init counters
#wexcep_cnt = 0
#rexcep_cnt = 0
#mismatch_cnt = 0
# print "erasing"
#
# flash_berase()
# while (flash_rsr() & 0x01):
# pass
#
# print "done!"
# read from flash
print
"BEFORE"
tr0
=
time
.
time
()
rd
=
flash_read
(
0x000000
,
256
)
rd
=
flash_read
(
multiboot_addr
,
256
)
tr1
=
time
.
time
()
rd
=
""
.
join
([
"0x
%02
X "
%
b
for
b
in
rd
])
print
rd
tr2
=
time
.
time
()
rd
=
flash_read
(
0x000100
,
256
)
tr3
=
time
.
time
()
rd
=
""
.
join
([
"0x
%02
X "
%
b
for
b
in
rd
])
rd
=
""
.
join
([
"0x
%06
X "
%
b
for
b
in
rd
])
print
rd
# print "ERASE"
# te1 = time.time()
# flash_serase(0x0010)
# while (flash_rsr() & 0x01):
# pass
# te2 = time.time()
# print "erase time: %2.6f" % (te2-te1)
# Ookay, now we start to write the flash
print
"WRITE"
# Prepare time arrays, to calculate average time each operation takes
addr
=
0
tdat
=
[]
twr
=
[]
twa
=
[]
te
=
[]
# Open bitstream file
f
=
open
(
"conv.txt"
,
'r'
)
# Each line in the input file contains the data for one page
for
fdata
in
f
:
print
addr
data
=
[]
# Erase on sector boundary
if
not
(
addr
%
0x10000
):
print
'erase'
te1
=
time
.
time
()
...
...
@@ -199,18 +240,26 @@ if __name__ == "__main__":
pass
te2
=
time
.
time
()
te
.
append
(
te2
-
te1
)
#rd = flash_read(0x000100,256)
#rd = "".join(["0x%02X " % b for b in rd])
#print rd
# Read the hex values from the input file, which contains page data as
# strings of hex values, one hex value (i.e., one character) per nibble
try
:
t1
=
time
.
time
()
for
i
in
xrange
(
256
):
data
.
append
(
int
(
fdata
[
0
:
2
],
16
))
fdata
=
fdata
[
2
:]
t2
=
time
.
time
()
# The last page of the flash will not be filled up with bytes, so
# data.append() above will throw a ValueError; catch this exception
# and use it to mark the end
except
ValueError
:
print
"reached end"
break
# The finally block gets executed no matter what, so we use it to actually
# write data to the flash, one page at a time. After every write, the
# address is incremented to the next page address.
finally
:
t3
=
time
.
time
()
flash_write
(
addr
,
data
)
...
...
@@ -232,6 +281,7 @@ if __name__ == "__main__":
# Close file handle
f
.
close
()
# Phew! We're ready, so calculate the mean time it took for each process
print
"DONE!"
print
"read1 time:
%2.6
f"
%
float
(
tr1
-
tr0
)
print
"read2 time:
%2.6
f"
%
float
(
tr3
-
tr2
)
...
...
@@ -240,9 +290,35 @@ if __name__ == "__main__":
print
"write time:
%2.6
f"
%
float
(
sum
(
twr
)
/
len
(
twr
))
#(t4-t3)
print
"wait time:
%2.6
f"
%
float
(
sum
(
twa
)
/
len
(
twa
))
#(t5-t4)
# Finally, issue the reprogramming (IPROG) command
print
"Issuing IPROG command..."
try
:
ctb
.
write
(
0x88
,
0x44
|
(
0x0b
<<
24
))
ctb
.
write
(
0x8c
,
multiboot_addr
|
(
0x0b
<<
24
))
ctb
.
write
(
0x80
,
0x10000
)
ctb
.
write
(
0x80
,
0x20000
)
except
NAckError
:
pass
# Set timeout to be sixty seconds from now...
t0
=
time
.
time
()
t1
=
t0
+
60
# and wait for the FPGA to gracefully respond, or die trying
while
(
1
):
try
:
if
((
ctb
.
read
(
0x4
)
&
0xFFFF
)
==
0x0201
):
print
"IPROG successful!"
break
if
(
time
.
time
()
>=
t1
):
print
"Timeout, IPROG unsuccessful!"
break
except
NAckError
:
continue
# Close VBCP connection and print final values
ctb
.
close_conn
()
# Woohoo!
tf
=
time
.
time
()
print
"run time:
%2.6
f"
%
float
(
tf
-
ts
)
test/vbcp/vbcp.py
View file @
1c09a3a4
...
...
@@ -28,6 +28,9 @@
#===============================================================================
# last changes:
# 2013-08-13 Theodor Stana t.stana@cern.ch File created
# 2013-10-14 Theodor Stana t.stana@cern.ch Updated VBCP protocol
# with hex addresses
# instead of reg numbers
#===============================================================================
# TODO: -
#===============================================================================
...
...
@@ -76,8 +79,6 @@ class VBCP:
def
writemregs
(
self
,
addr
,
val
):
self
.
write_cnt
+=
1
#reg = addr/4 + 1
#print '%02x' % sl
cmd
=
"writemregs
%
d
%
x
%
s
\r\n
"
%
(
self
.
slot
,
addr
,
' '
.
join
(
format
(
b
,
'x'
)
for
b
in
val
))
#print cmd
self
.
handle
.
send
(
cmd
)
...
...
@@ -85,7 +86,7 @@ class VBCP:
def
readmregs
(
self
,
addr
,
nrregs
):
self
.
read_cnt
+=
1
#
reg
= addr/4 + 1
#
addr
= addr/4 + 1
cmd
=
"readmregs
%
d
%
x
%
d
\r\n
"
%
(
self
.
slot
,
addr
,
nrregs
)
self
.
handle
.
send
(
cmd
)
resp
=
_strip_resp
(
self
.
handle
.
recv
(
30
))
...
...
@@ -93,7 +94,7 @@ class VBCP:
def
write
(
self
,
addr
,
val
):
self
.
write_cnt
+=
1
#
reg
= addr/4 + 1
#
addr
= addr/4 + 1
cmd
=
"writereg
%
d
%
x
%
x
\r\n
"
%
(
self
.
slot
,
addr
,
val
)
#print cmd
self
.
handle
.
send
(
cmd
)
...
...
@@ -101,7 +102,7 @@ class VBCP:
def
read
(
self
,
addr
):
self
.
read_cnt
+=
1
#
reg
= addr/4 + 1
#
addr
= addr/4 + 1
cmd
=
"readreg
%
d
%
x
\r\n
"
%
(
self
.
slot
,
addr
)
#print cmd
self
.
handle
.
send
(
cmd
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment