From d9d337ed9ad27d0e8b2460203cd0117920e5291e Mon Sep 17 00:00:00 2001 From: Martin Teichmann <martin.teichmann@xfel.eu> Date: Thu, 7 Sep 2023 11:46:19 +0200 Subject: [PATCH] allow reading eeprom without terminal this breaks a bit the logic of terminals, but is necessary for bootstrapping: you want to know which type of terminal it is before we initialize it. --- ebpfcat/ethercat.py | 27 +++++++++++++++++++++++---- ebpfcat/scripts.py | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ebpfcat/ethercat.py b/ebpfcat/ethercat.py index aa1b477..0cd07a7 100644 --- a/ebpfcat/ethercat.py +++ b/ebpfcat/ethercat.py @@ -30,7 +30,7 @@ from asyncio import ( ensure_future, Event, Future, gather, get_event_loop, Protocol, Queue, Lock) from contextlib import asynccontextmanager -from enum import Enum +from enum import Enum, IntEnum from itertools import count from random import randint from socket import socket, AF_PACKET, SOCK_DGRAM @@ -128,6 +128,11 @@ class ODCmd(Enum): SEG_UP_REQ = 0x60 ABORT = 0x80 +class EEPROM(IntEnum): + VENDOR_ID = 8 + PRODUCT_CODE = 10 + REVISION = 12 + SERIAL_NO = 14 class ObjectDescription: def __init__(self, terminal): @@ -346,7 +351,7 @@ class EtherCat(Protocol): fmt = "<" + "".join(arg for arg in args[:-1] if isinstance(arg, str)) out = pack(fmt, *[arg for arg in args if not isinstance(arg, str)]) if args and isinstance(args[-1], str): - out += b"\0" * calcsize(args[-1]) + out += b"\0" * calcsize("<" + args[-1]) fmt += args[-1] if isinstance(data, int): out += b"\0" * data @@ -382,6 +387,18 @@ class EtherCat(Protocol): except EtherCatError: return i # this address is not in use + async def eeprom_read(self, position, start): + """read 4 bytes from the eeprom of terminal `position` at `start`""" + while (await self.roundtrip(ECCmd.APRD, position, + 0x502, "H"))[0] & 0x8000: + pass + await self.roundtrip(ECCmd.APWR, position, 0x502, "HI", 0x100, start) + busy = 0x8000 + while busy & 0x8000: + busy, data = await self.roundtrip(ECCmd.APRD, position, + 0x502, "H4xI") + return data + def connection_made(self, transport): """start the send loop once the connection is made""" transport.get_extra_info("socket").bind(self.addr) @@ -425,8 +442,10 @@ class Terminal: async def read_eeprom(no, fmt): return unpack(fmt, await self._eeprom_read_one(no)) - self.vendorId, self.productCode = await read_eeprom(8, "<II") - self.revisionNo, self.serialNo = await read_eeprom(0xc, "<II") + self.vendorId, self.productCode = \ + await read_eeprom(EEPROM.VENDOR_ID, "<II") + self.revisionNo, self.serialNo = \ + await read_eeprom(EEPROM.REVISION, "<II") # this reads the mailbox configuration from the EEPROM header. # weirdly this does not match with the later EEPROM SM configuration # self.mbx_in_off, self.mbx_in_sz, self.mbx_out_off, self.mbx_out_sz = \ diff --git a/ebpfcat/scripts.py b/ebpfcat/scripts.py index 2a26968..0605b45 100644 --- a/ebpfcat/scripts.py +++ b/ebpfcat/scripts.py @@ -22,7 +22,7 @@ async def scanbus(): no = await ec.count() for i in range(no): r, = await ec.roundtrip(ECCmd.APRD, -i, 0x10, "H", 44) - print(i, r) + print(i, r, await ec.eeprom_read(-i, 0xa)) @entrypoint async def info(): -- GitLab