Commit 077d77d1 authored by Qiang Du's avatar Qiang Du

Update Etherbone IO classes. Support of multiple register IO using eb_cycle_read/write.

parent 9b3842f3
...@@ -48,5 +48,5 @@ ...@@ -48,5 +48,5 @@
# communication-type-specific parameters is the elma.write() and elma.read() # communication-type-specific parameters is the elma.write() and elma.read()
# methods, in the case of the ELMA_I2C_MULTIBOOT type. # methods, in the case of the ELMA_I2C_MULTIBOOT type.
ELMA_I2C_MULTIBOOT = 0; ELMA_I2C_MULTIBOOT = 0;
ETHERBONE_MULTIBOOT = 1; ETHERBONE = 1;
...@@ -27,7 +27,6 @@ class EB: ...@@ -27,7 +27,6 @@ class EB:
self.port_ip = 'udp/' + ip self.port_ip = 'udp/' + ip
self.write_cnt = 0 self.write_cnt = 0
self.read_cnt = 0 self.read_cnt = 0
self.open()
def open(self): def open(self):
self.socket = eb.Socket() self.socket = eb.Socket()
...@@ -36,148 +35,32 @@ class EB: ...@@ -36,148 +35,32 @@ class EB:
self.device = eb.Device(self.socket, self.port_ip) self.device = eb.Device(self.socket, self.port_ip)
self.device.__enter__() self.device.__enter__()
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
def close(self): def close(self):
self.cycle.close()
self.device.close() self.device.close()
self.socket.close() self.socket.close()
def write(self, addr, val): def write(self, addr, val):
self.device.write(addr, 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()
def read(self, addr): def read(self, addr):
return self.device.read(addr) return self.device.read(addr)
class EI2C: def readmregs(self, addr, nrregs):
curr_addr = addr
"""Access a VME crate through Telnet.""" dlist = []
self.cycle = eb.Cycle(self.device, 0, 0)
def __init__(self, ip, user, pwd): self.cycle.__enter__()
for i in xrange(nrregs):
"""Initialize EI2C class. curr_addr += i
dlist[i] = self.cycle.read(curr_addr)
The arguments to init the class are mandatory: self.cycle.close()
ip -- IP address of VME crate return dlist
user -- username to login to VME crate
pwd -- password to login to VME crate
"""
self.ip = ip
self.user = user
self.pwd = pwd
self.write_cnt = 0
self.read_cnt = 0
if (ei2cdefine.DUMP):
self.f = open("dump.txt", 'w')
def open(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
try:
s.connect((self.ip, 23))
s.recv(30)
except (socket.gaierror, socket.error) as e:
raise BadHostnameError
s.send(self.user + "\r\n")
if "password" not in s.recv(30):
raise BadUsernameError
s.send(self.pwd + "\r\n")
if "Wrong password" in s.recv(30):
raise BadPasswordError
self.handle = s
def close(self):
self.handle.close()
if (ei2cdefine.DUMP):
self.f.close()
def write(self, slot, addr, val):
self.write_cnt += 1
#reg = addr/4 + 1
cmd = "writereg %d %x %x\r\n" % (slot, addr, val)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
self._strip_resp(self.handle.recv(30))
def read(self, slot, addr):
self.read_cnt += 1
#reg = addr/4 + 1
cmd = "readreg %d %x\r\n" % (slot, addr)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
resp = self._strip_resp(self.handle.recv(30))
return resp
def writemregs(self, slot, addr, val):
self.write_cnt += 1
#reg = addr/4 + 1
#print '%02x' % sl
cmd = "writemregs %d %x %s\r\n" % (slot, addr, ' '.join(format(b,'x') for b in val))
if (ei2cdefine.DUMP):
self.f.write(cmd);
#print cmd
self.handle.send(cmd)
self._strip_resp(self.handle.recv(30))
def readmregs(self, slot, addr, nrregs):
self.read_cnt += 1
#reg = addr/4 + 1
cmd = "readmregs %d %x %d\r\n" % (slot, addr, nrregs)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
resp = self._strip_resp(self.handle.recv(30))
return resp
def _strip_resp(self, msg):
"""Strip useful message from SysMon response.
The response string from the SysMon is stripped of unnecessary characters
and a "useful" string is returned. In case one of the error messages appear,
the function raises one of the EI2C exceptions."""
#print msg.splitlines()
msg = msg.splitlines()[1]
if (ei2cdefine.DUMP):
self.f.write(msg + "\n")
if "Not Ack" in msg:
raise NAckError
if "Invalid register number!" in msg:
raise RegNumberError
if "Bad command!" in msg:
raise InvalidCmdError
if "I2C Timer expired" in msg:
raise TimerExpiredError
if "Invalid slot number!" in msg:
raise SlotError
if "Read Data:" in msg:
msg = msg.split(" ")[3]
msg = int(msg,16)
return msg
# MAIN "FUNCTION"
if __name__ == "__main__":
address = 0x20810
if (0):
with eb.Socket() as socket:
with eb.Device(socket, 'udp/rflab2') as device:
with eb.Cycle(device, 0, 0) as cycle:
data = cycle.read(address)
print hex(data.value)
print 'EB test'
ebi = EB('rflab2')
print hex(ebi.read(address).value)
...@@ -104,14 +104,6 @@ class Socket(): ...@@ -104,14 +104,6 @@ class Socket():
All method return codes are identical to their plain C interface All method return codes are identical to their plain C interface
counterparts. counterparts.
""" """
#_fields_ = [
# ('device_ring', Ring),
# ('vdevice_ring', Ring),
# ('socket', POINTER(eb_socket_t)),
# ('response_table', POINTER(Response)),
# ('response_index', c_int),
#]
def __init__(self, port=0, widths=EB_ADDRX|EB_DATAX): def __init__(self, port=0, widths=EB_ADDRX|EB_DATAX):
self.abi_code = EB_ABI_CODE self.abi_code = EB_ABI_CODE
self.socket = eb_socket_t() self.socket = eb_socket_t()
...@@ -193,14 +185,10 @@ class Device(): ...@@ -193,14 +185,10 @@ class Device():
""" """
return lib.eb_device_width(self.device) return lib.eb_device_width(self.device)
def flush(self):
"""flush commands queued on the device out the socket
"""
return lib.eb_device_flush(self.device)
def read(self, address): def read(self, address):
"""perform a single-read wishbone cycle """perform a single-read wishbone cycle
Semantically equivalent to cycle_open, cycle_read, cycle_close, device_flush. Semantically equivalent to cycle_open, cycle_read, cycle_close.
The given address is read on the remote device. The given address is read on the remote device.
The callback cb(user, status, data) is invoked with the result. The callback cb(user, status, data) is invoked with the result.
...@@ -210,12 +198,12 @@ class Device(): ...@@ -210,12 +198,12 @@ class Device():
user_data = None user_data = None
callback = None callback = None
lib.eb_device_read(self.device, address, self.data_format, byref(data), user_data, callback) lib.eb_device_read(self.device, address, self.data_format, byref(data), user_data, callback)
return data return data.value
def write(self, address, data): def write(self, address, data):
"""perform a single-write wishbone cycle """perform a single-write wishbone cycle
Semantically equivalent to cycle_open, cycle_write, cycle_close, device_flush. Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device. data is written to the given address on the remote device.
""" """
user_data = None user_data = None
...@@ -268,7 +256,7 @@ class Cycle(): ...@@ -268,7 +256,7 @@ class Cycle():
""" """
data = eb_data_t() data = eb_data_t()
lib.eb_cycle_read(self.cycle, address, self.data_format, byref(data)) lib.eb_cycle_read(self.cycle, address, self.data_format, byref(data))
return data return data.value
def write(self, address, data): def write(self, address, data):
"""perform a wishbone write phase """perform a wishbone write phase
...@@ -400,52 +388,10 @@ def eb_device_socket(device): ...@@ -400,52 +388,10 @@ def eb_device_socket(device):
""" """
return lib.eb_device_socket(device) return lib.eb_device_socket(device)
def eb_device_flush(socket):
"""
Flush commands queued on the device out the socket.
"""
return lib.eb_device_flush(socket)
def eb_cycle_open_read_only(device, userdata, cycle_callback):
"""
Begin a wishbone cycle on the remote device.
Read/write phases within a cycle hold the device locked.
All reads are executed first followed by all writes.
Until the cycle is closed, the operations are not queued.
If data was read, the callback is run upon cycle completion.
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
OVERFLOW - too many operations queued for this cycle
"""
return lib.eb_cycle_open_read_only(device, userdata, cycle_callback)
def eb_cycle_open_read_write(device, user, cb, write_base, write_mode):
"""
Begin a wishbone cycle on the remote device.
Read/write phases within a cycle hold the device locked.
All reads are executed first followed by all writes.
Until the cycle is closed, the operations are not queued.
If data was read, the callback is run upon cycle completion.
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
OVERFLOW - too many operations queued for this cycle
"""
return lib.eb_cycle_open_read_write(device, user, cb, write_base, write_mode)
def eb_cycle_close(cycle): def eb_cycle_close(cycle):
""" """
End a wishbone cycle. End a wishbone cycle.
This places the complete cycle at end of the device''s send queue. This places the complete cycle at end of the device''s send queue.
You will probably want to eb_flush_device soon after calling eb_cycle_close.
""" """
return lib.eb_cycle_close(cycle) return lib.eb_cycle_close(cycle)
...@@ -473,7 +419,7 @@ def eb_device_read(device, address, userdata, cb): ...@@ -473,7 +419,7 @@ def eb_device_read(device, address, userdata, cb):
""" """
Perform a single-read wishbone cycle. Perform a single-read wishbone cycle.
Semantically equivalent to cycle_open, cycle_read, cycle_close, device_flush. Semantically equivalent to cycle_open, cycle_read, cycle_close.
The given address is read on the remote device. The given address is read on the remote device.
The callback cb(user, status, data) is invoked with the result. The callback cb(user, status, data) is invoked with the result.
...@@ -489,7 +435,7 @@ def eb_device_read(device, address, userdata, cb): ...@@ -489,7 +435,7 @@ def eb_device_read(device, address, userdata, cb):
def eb_device_write(device, address, data): def eb_device_write(device, address, data):
""" """
Perform a single-write wishbone cycle. Perform a single-write wishbone cycle.
Semantically equivalent to cycle_open, cycle_write, cycle_close, device_flush. Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device. data is written to the given address on the remote device.
""" """
......
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