Commit 2dc1f007 authored by Qiang Du's avatar Qiang Du

Fix flash writting scripts, enable sector erasing.

Flash programming partially works
parent 077d77d1
......@@ -16,6 +16,7 @@
import etherbone as eb
import sys
import logging
class EB:
""" access a Etherbone device. """
......@@ -40,27 +41,24 @@ class EB:
self.socket.close()
def write(self, addr, val):
logging.debug('write: 0x%08x'% val)
self.device.write(addr, val)
def writemregs(self, addr, dlist):
curr_addr = addr
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
for i in dlist:
curr_addr += i
self.cycle.write(curr_addr, i)
self.cycle.close()
with eb.Cycle(self.device, 0, 0) as cycle:
for v in dlist:
logging.debug('mwrite: 0x%08x'% v)
cycle.write(addr, v)
def read(self, addr):
return self.device.read(addr)
val = self.device.read(addr)
logging.debug('read: 0x%08x'% val)
return val
def readmregs(self, addr, nrregs):
curr_addr = addr
dlist = []
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
for i in xrange(nrregs):
curr_addr += i
dlist[i] = self.cycle.read(curr_addr)
self.cycle.close()
with eb.Cycle(self.device, 0, 0) as cycle:
for i in nrregs:
dlist.append(cycle.read(addr, v))
logging.debug('mread: 0x%08x'% dlist[i])
return dlist
......@@ -37,19 +37,6 @@ eb_device_t = c_uint16
eb_cycle_t = c_uint16
# status codes
eb_status_t = c_int
( EB_OK,
EB_FAIL,
EB_ABORT,
EB_ADDRESS,
EB_OVERFLOW,
EB_ENDIAN,
EB_BUSY,
EB_TIMEOUT,
EB_OOM,
EB_ABI,
EB_SEGFAULT) = range(0,-11,-1)
eb_err_code = {
0: 'EB_OK',
-1: 'EB_FAIL',
......@@ -113,7 +100,7 @@ class Socket():
def __enter__(self):
status = self.open(self.port, self.widths, self.socket)
if (status != 0):
print 'error opening device, code ', eb_err_code[status]
raise IOError('error opening device, code ', eb_err_code[status])
return self
def __exit__(self, type, value, traceback):
......@@ -155,20 +142,20 @@ class Device():
def __enter__(self):
status = self.open(self.socket, self.address, self.widths)
if (status != 0):
print 'error opening device, code ', eb_err_code[status]
raise IOError('error opening device, code ', eb_err_code[status])
return self
def __exit__(self, type, value, traceback):
self.close()
def open(self, socket, ip_port, widths):
def open(self, socket, ip_port, widths, retry=3):
"""open a remote Etherbone device
This resolves the address and performs Etherbone end-point discovery.
From the mask of proposed bus widths, one will be selected.
The default port is taken as 0xEBD0.
"""
return lib.eb_device_open(socket, ip_port, widths, 3, byref(self.device))
return lib.eb_device_open(socket, ip_port, widths, retry, byref(self.device))
def close(self):
"""close a remote Etherbone device
......@@ -185,7 +172,7 @@ class Device():
"""
return lib.eb_device_width(self.device)
def read(self, address):
def read(self, address, user_data = None, callback = None):
"""perform a single-read wishbone cycle
Semantically equivalent to cycle_open, cycle_read, cycle_close.
......@@ -195,19 +182,15 @@ class Device():
The user parameter is passed through uninspected to the callback.
"""
data = eb_data_t()
user_data = None
callback = None
lib.eb_device_read(self.device, address, self.data_format, byref(data), user_data, callback)
return data.value
def write(self, address, data):
def write(self, address, data, user_data = None, callback = None):
"""perform a single-write wishbone cycle
Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device.
"""
user_data = None
callback = None
return lib.eb_device_write(self.device, address, self.data_format, data, user_data, callback)
class Cycle():
......@@ -226,7 +209,7 @@ class Cycle():
def __enter__(self):
status = self.open(self.dev_handle, self.user_data, self.callback)
if (status != 0):
print 'error opening device, code ', eb_err_code[status]
raise IOError('error opening device, code ', eb_err_code[status])
return self
def __exit__(self, type, value, traceback):
......@@ -265,178 +248,3 @@ class Cycle():
If the device was read-only, the operation is discarded.
"""
return lib.eb_cycle_write(self.cycle, address, self.data_format, data)
#
# C99 API
#
def eb_socket_open(port, widths, socket):
"""
Open an Etherbone socket for communicating with remote devices.
The port parameter is optional; 0 lets the operating system choose.
After opening the socket, poll must be hooked into an event loop.
Return codes:
OK - successfully open the socket port
FAIL - operating system forbids access
BUSY - specified port is in use (only possible if port != 0)
"""
return lib.eb_socket_open(EB_ABI_CODE, port, widths, socket)
def eb_socket_close(socket):
"""
Close the Etherbone socket.
Any use of the socket after successful close will probably segfault!
Return codes:
OK - successfully closed the socket and freed memory
BUSY - there are open devices on this socket
"""
return lib.eb_socket_close(socket)
def eb_socket_poll(socket):
"""
Poll the Etherbone socket for activity.
This function must be called regularly to receive incoming packets.
Either call poll very often or hook a read listener on its descriptor.
Callback functions are only executed from within the poll function.
Return codes:
OK - poll complete; no further packets to process
FAIL - socket error (probably closed)
"""
return lib.eb_socket_poll(socket)
def eb_socket_block(socket, timeout_us):
"""
Block until the socket is ready to be polled.
This function is useful if your program has no event loop of its own.
It returns the time spent while waiting.
"""
return lib.eb_socket_block(socket, timeout_us)
def eb_socket_descriptor(socket):
"""
Access the underlying file descriptor of the Etherbone socket.
THIS MUST NEVER BE READ, WRITTEN, CLOSED, OR MODIFIED IN ANY WAY!
It may be used to watch for read readiness to call poll.
"""
return lib.eb_socket_descriptor(socket)
def eb_socket_attach(socket, handler):
"""
Add a device to the virtual bus.
This handler receives all reads and writes to the specified address.
NOTE: the address range [0x0, 0x7fff) is reserved for internal use.
Return codes:
OK - the handler has been installed
FAIL - out of memory
ADDRESS - the specified address range overlaps an existing device.
"""
return lib.eb_socket_attach(socket, handler)
def eb_socket_detach(socket, address):
"""
Detach the device from the virtual bus.
Return codes:
OK - the devices has be removed
FAIL - there is no device at the specified address.
"""
return lib.eb_socket_detach(socket, address)
def eb_device_open(socket, ip_port, proposed_widths, result):
"""
Open a remote Etherbone device.
This resolves the address and performs Etherbone end-point discovery.
From the mask of proposed bus widths, one will be selected.
The default port is taken as 0xEBD0.
Return codes:
OK - the remote etherbone device is ready
FAIL - the remote address did not identify itself as etherbone conformant
ADDRESS - the network address could not be parsed
ABORT - could not negotiate an acceptable data bus width
"""
return lib.eb_device_open(socket, ip_port, proposed_widths, result)
def eb_device_width(device):
"""
Recover the negotiated data width of the target device.
"""
return lib.eb_device_width(device)
def eb_device_close(device):
"""
Close a remote Etherbone device.
Return codes:
OK - associated memory has been freed
BUSY - there are outstanding wishbone cycles on this device
"""
return lib.eb_device_close(device)
def eb_device_socket(device):
"""Access the socket backing this device
"""
return lib.eb_device_socket(device)
def eb_cycle_close(cycle):
"""
End a wishbone cycle.
This places the complete cycle at end of the device''s send queue.
"""
return lib.eb_cycle_close(cycle)
def eb_cycle_device(cycle):
"""Access the device targetted by this cycle
"""
return eb_cycle_device(cycle)
def eb_cycle_read(cycle, address):
"""
Prepare a wishbone read phase.
The given address is read from the remote device.
"""
return lib.eb_cycle_read(cycle, address)
def eb_cycle_write(cycle, data):
"""
Perform a wishbone write phase.
data is written to the current cursor on the remote device.
If the device was read-only, the operation is discarded.
"""
return lib.eb_cycle_write(cycle, data)
def eb_device_read(device, address, userdata, cb):
"""
Perform a single-read wishbone cycle.
Semantically equivalent to cycle_open, cycle_read, cycle_close.
The given address is read on the remote device.
The callback cb(user, status, data) is invoked with the result.
The user parameter is passed through uninspected to the callback.
Status codes:
OK - the operation completed successfully
FAIL - the operation failed due to an wishbone ERR_O signal
ABORT - an earlier operation failed and this operation was thus aborted
"""
return lib.eb_device_read(device, address, userdata, cb)
def eb_device_write(device, address, data):
"""
Perform a single-write wishbone cycle.
Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device.
"""
return lib.eb_device_write(device, address, data)
......@@ -20,6 +20,7 @@
#
import sys
import logging
import struct
sys.path.append("eb")
from eb import *
......@@ -56,7 +57,6 @@ class FlashM25P:
# control byte, to be shifted left by 24
ctrl = ((cs << 3) | 0x4) | (nbytes-1)
if (self.comm == ELMA_I2C_MULTIBOOT):
# Use appropriate command by type
#
# write - we send up to three data bytes in one FAR register write
......@@ -79,6 +79,7 @@ class FlashM25P:
wval.append((ctrl << 24) | dat[i])
self.ebone.writemregs(self.mb_base+0x10, wval)
# Read the data and prepare the return value
while (retval & (1 << 28) == 0):
retval = self.ebone.read(self.mb_base+0x10)
......@@ -88,14 +89,23 @@ class FlashM25P:
# 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 write(self, addr, dat):
logging.debug('Writting to address 0x%x' % addr)
# write enable cmd
self.spi_transfer(1,1,0x06)
self.spi_transfer(1,0,0)
# check status (WIP, WEL) bits
status = 0
retry = 3
while (status != 0x2):
logging.debug('Flash not ready, status: 0x%x' % status)
if (retry <= 0):
raise IOError('Error writing, status not vaild: 0x%x'% status)
logging.debug('retry = %d' % retry)
retry -= 1
status = self.rsr()
# write page cmd
self.spi_transfer(1,1,0x02)
# send address in reverse order
self.spi_transfer(3,1,self.rev_addr(addr))
......@@ -139,6 +149,7 @@ class FlashM25P:
# It returns the values of the three consecutive flash registers packed into
# one 24-bit data value in little-endian order
def read(self, addr, nrbytes):
logging.debug('Reading from 0x%x...' % addr)
ret = []
self.spi_transfer(1,1,0x0b)
......@@ -146,7 +157,7 @@ class FlashM25P:
self.spi_transfer(3,1,self.rev_addr(addr))
self.spi_transfer(1,1,0)
# Read bytes in groups of three
# Read bytes in groups of one
for i in range(nrbytes):
ret.append(self.spi_transfer(1,1,0))
self.spi_transfer(1,0,0)
......@@ -155,12 +166,18 @@ class FlashM25P:
# Send a sector erase command
def serase(self, addr):
logging.debug('Sector Erasing from 0x%x'% addr)
self.spi_transfer(1,1,0x06)
self.spi_transfer(1,0,0)
self.spi_transfer(1,1,0xD8)
# send address in reverse order
self.spi_transfer(3,1,self.rev_addr(addr))
self.spi_transfer(1,0,0)
# wait until finish
status = 1
while (status != 0x0):
logging.debug('Sector erasing...')
status = self.rsr()
# Send a block erase command
def berase(self):
......@@ -174,6 +191,7 @@ class FlashM25P:
self.spi_transfer(1,1,0x05)
ret = self.spi_transfer(1,1,0)
self.spi_transfer(1,0,0)
logging.debug('Status Register: 0x%x'% ret)
return ret
def read_id(self):
......@@ -183,6 +201,7 @@ class FlashM25P:
ret.append(self.spi_transfer(1,1,0))
self.spi_transfer(1,0,0)
ret_pack = struct.pack('B'*20, *ret)
logging.debug('Flash ID: 0x'+ret_pack.encode('hex'))
return ret_pack
def rev_addr(self, addr):
......
......@@ -2,29 +2,42 @@ import os
import sys
import time
import struct
import logging
sys.path.append("eb")
from eb import *
from xil_multiboot import *
if __name__ == "__main__":
def main():
log_level = logging.DEBUG
log_level = logging.INFO
logging.basicConfig(level=log_level)
ip = 'rflab2.lbl.gov'
target = EB(ip)
target.open()
baseaddr = 0x20800
mb = XilMultiboot(ETHERBONE, target, baseaddr, "foo_bit")
mb.write(0)
flash_address = 0x10
flash_length = 0x1f
file_name = 'foo_bit'
mb = XilMultiboot(ETHERBONE, target, baseaddr, file_name)
status = mb.flash.rsr()
print 'Status:' + hex(status)
# read id
id = mb.flash.read_id()
logging.info('Flash ID: 0x' + id.encode('hex'))
#logging.info('Programming file %s'% file_name)
#mb.write(flash_address)
#mb.read(0,0xff)
# read id
id = mb.flash.read_id()
print 'ID: 0x' + id.encode('hex')
# mb.flash.serase(flash_address)
mb.flash.write(flash_address,range(0x15, 0x15 + flash_length))
status = mb.flash.rsr()
logging.info('Status: 0x%x', status)
#mb.flash.serase(0x0)
# mb.flash.write(0x0,range(0,255))
dat = mb.flash.read(0x0,0xff)
dat = mb.flash.read(flash_address, flash_length)
dat_pack = struct.pack('B'*len(dat), *dat)
print 'Flash: 0x' + dat_pack.encode('hex')
if __name__ == "__main__":
main()
......@@ -19,6 +19,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
import logging
import sys
sys.path.append("eb")
from eb import *
......@@ -64,8 +65,7 @@ class XilMultiboot:
progress = (float(actual)/float(total)) * 100
if (progress > 100.00):
progress = 100.00
sys.stdout.write("\r %3.2f%% (0x%06x)" % (progress, ca))
sys.stdout.flush()
logging.info("\r %3.2f%% (0x%06x)" % (progress, ca))
#
# Read from flash
......@@ -76,14 +76,13 @@ class XilMultiboot:
f = open(fname,'wb')
# Read the data and dump to file
print("Reading flash contents from board in slot %d" % self.slot)
logging.info("Reading flash contents from board in slot %d" % self.slot)
dat = []
for i in range(sa, ea, 256):
dat += self.flash.read(i, 256)
self._progress(sa, ea, i)
i += 256
self._progress(sa, ea, i)
print("")
dat = ''.join(map(chr,dat))
f.write(dat)
f.close()
......@@ -93,7 +92,7 @@ class XilMultiboot:
#
def write(self, addr):
print("Writing bitstream to board in slot %d" % self.slot)
logging.info("Writing bitstream to board in slot %d" % self.slot)
# Ask for and open bitstream file
f = open(self.bitstream,'rb')
......@@ -108,7 +107,7 @@ class XilMultiboot:
# Erase on sector boundary
if not (addr % 0x10000):
print 'erase sector boundary'
logging.info('erase sector boundary')
self.flash.serase(addr)
while (self.flash.rsr() & 0x01):
pass
......@@ -122,18 +121,17 @@ class XilMultiboot:
addr += 256
self._progress(sta, end, addr)
print("")
# Close file handle
f.close()
print("DONE!")
logging.info("DONE!")
#
# Start IPROG sequence
#
def iprog(self, addr):
if (self.comm == ELMA_I2C_MULTIBOOT):
print("Issuing IPROG command to board in slot %d..." % self.slot)
logging.info("Issuing IPROG command to board in slot %d..." % self.slot)
self.elma.write(self.slot, self.mb_base+MB_GBBAR_OFS, 0x44 | (0x0b << 24))
self.elma.write(self.slot, self.mb_base+MB_MBBAR_OFS, addr | (0x0b << 24))
self.elma.write(self.slot, self.mb_base+MB_CR_OFS, 0x10000)
......@@ -150,13 +148,13 @@ class XilMultiboot:
while (1):
try:
if (time.time() >= t1):
print("Timeout, IPROG unsuccessful!")
logging.error("Timeout, IPROG unsuccessful!")
break
if ((self.elma.read(self.slot, 0x4) & 0xf0) == 0x00):
print("IPROG unsuccessful, fallback to Golden bitstream occured!")
logging.info("IPROG unsuccessful, fallback to Golden bitstream occured!")
break
else:
print("IPROG successful!")
logging.info("IPROG successful!")
break
except NAckError:
continue
......@@ -165,7 +163,7 @@ class XilMultiboot:
# Sequence to read FPGA configuration register
#
def rdcfgreg(self):
print("Press 'q' to end config reg readout")
logging.info("Press 'q' to end config reg readout")
while 1:
try:
reg = raw_input('Address (hex): ')
......@@ -176,13 +174,13 @@ class XilMultiboot:
self.elma.write(self.slot, self.mb_base+MB_CR_OFS, (1 << 6) | reg)
val = self.elma.read(self.slot, self.mb_base+MB_SR_OFS)
if (val & (1 << 16)):
print("REG(0x%02X) = 0x%04X" % (reg, val & 0xffff))
logging.info("REG(0x%02X) = 0x%04X" % (reg, val & 0xffff))
else:
print("CFGREGIMG invalid!")
logging.error("CFGREGIMG invalid!")
except ValueError:
if (reg == 'q'):
break
print("Please input a hex value in the range [0x00, 0x22] or 'q' to quit")
logging.error("Please input a hex value in the range [0x00, 0x22] or 'q' to quit")
#
# Set bitstream file path
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment