699 lines
22 KiB
Python
699 lines
22 KiB
Python
from functools import lru_cache
|
|
from random import randint
|
|
from time import sleep
|
|
from typing import List, Tuple, Optional, Union, Iterable
|
|
|
|
from biopro.impl.selector import Selector
|
|
from biopro.util.console import pc, GREEN, RED
|
|
from .gpio import P3Pin, OutputPin, InputPin
|
|
from .interface_spi import HardwareImplSpiInterface, LowLevelHardwareInterface
|
|
from datetime import datetime
|
|
|
|
MSM_REG_WRITE = 0x01
|
|
MEM_INS_WRITE = 0x02
|
|
MEM_INS_READ = 0x03
|
|
MEM_REG_READ = 0x05
|
|
DEFAULT_REGISTER_VALUE = 0b0100_0011 # 67
|
|
MEM_SIZE = 0x1000
|
|
|
|
_RUNTIME_COMPILE = False
|
|
|
|
_SLEEP_TIME_ = 0.001
|
|
|
|
|
|
@lru_cache(maxsize=4)
|
|
def zero_buffer(size: int) -> List[int]:
|
|
return [0] * size
|
|
|
|
|
|
class ExtMemSpiInterface(LowLevelHardwareInterface):
|
|
MEM_INS_MARKED = [MEM_INS_WRITE, 0, 2, 1, 1]
|
|
MEM_INS_RESET = [MEM_INS_WRITE, 0, 2, 1, 1, 0, 0xFF]
|
|
|
|
__slots__ = ('_spi', '_tx_buffer', '_tx_buffer_header', '_tx_buffer_data',
|
|
'pin_busy', 'pin_request', 'pin_reset', 'pin_sel',
|
|
'_pin_sel_val',
|
|
'_read_green_times','_read_red_times',
|
|
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
|
|
'_head_wrong_cnt')
|
|
|
|
def __init__(self, device: Tuple[int, int] = None):
|
|
super().__init__()
|
|
self._spi = HardwareImplSpiInterface(device,
|
|
spi_speed=12_000_000 # XXX temp parameter
|
|
)
|
|
|
|
self._elite_data_len = 20
|
|
self._mem_header_len = 3
|
|
self._mem_tailer_len = 8
|
|
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
|
|
|
# buffer
|
|
self._tx_buffer = [0] * 512
|
|
self._tx_buffer_header = [0] * 11
|
|
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
|
|
|
|
# memory control pin
|
|
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True)
|
|
self.pin_request = OutputPin.get_used(P3Pin.MEM_REQ, True)
|
|
self.pin_reset = OutputPin.get_used(P3Pin.MEM_RST, True)
|
|
self.pin_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL)
|
|
|
|
self._pin_sel_val = False
|
|
|
|
self._read_green_times = 0
|
|
self._read_red_times = 0
|
|
|
|
self._head_wrong_cnt = [0, 0, 0, 0, 0, 0, 0, 0]
|
|
|
|
def reset(self):
|
|
self._spi.reset()
|
|
|
|
def close(self):
|
|
self._spi.close()
|
|
|
|
def flush(self):
|
|
self.pin_reset.output(False)
|
|
self.pin_reset.output(True)
|
|
|
|
@property
|
|
def select(self) -> int:
|
|
return 0
|
|
|
|
@select.setter
|
|
def select(self, value: int):
|
|
pass
|
|
|
|
def changed(self, flip=False) -> bool:
|
|
old = self._pin_sel_val
|
|
value = self.pin_sel.input()
|
|
|
|
if flip:
|
|
self._pin_sel_val = value
|
|
|
|
return value != old
|
|
|
|
def send_byte(self, data: bytes):
|
|
raise RuntimeError()
|
|
|
|
def recv_byte(self, size: int) -> Optional[bytes]:
|
|
raise RuntimeError()
|
|
|
|
def request_data(self):
|
|
self.pin_request.output(False)
|
|
sleep(0.001)
|
|
|
|
# count = 0
|
|
# for i in range(300):
|
|
# count = count + 1
|
|
|
|
self.pin_request.output(True)
|
|
|
|
# sleep(0.001) -> 1.2ms
|
|
# no sleep -> 5us ~ 12us (central can't receive)
|
|
|
|
# for i in range
|
|
# (1000) -> 500us ~ 1ms
|
|
# (500) -> 200us ~ 500us
|
|
# (300) -> 120us ~ 270us (seldom)
|
|
# (200) -> 70us ~ 160us (skip req about every 64 time) x
|
|
# (100) -> 40us ~ 100us (skip req sometimes) x
|
|
|
|
def compare_green_data(self, data_first: Union[bytes, List[int]], data_second: Union[bytes, List[int]], data_third: Union[bytes, List[int]], length: int):
|
|
data = []
|
|
data.append(255)
|
|
data.append(255)
|
|
data.append(255)
|
|
|
|
for i in range(3, length):
|
|
if (data_first[i] == data_second[i] or data_first[i] == data_third[i]):
|
|
data.append(data_first[i])
|
|
elif(data_second[i] == data_third[i]):
|
|
data.append(data_second[i])
|
|
else:
|
|
data.append(data_third[i]) # use last data
|
|
self._read_green_times = self._read_green_times + 1
|
|
print("read green data times", self._read_green_times)
|
|
return data
|
|
|
|
def compare_red_data(self, data_first: Union[bytes, List[int]], data_second: Union[bytes, List[int]], data_third: Union[bytes, List[int]], length: int):
|
|
data = []
|
|
data.append(255)
|
|
data.append(255)
|
|
data.append(255)
|
|
|
|
for i in range(3, length):
|
|
if (data_first[i] == data_second[i] or data_first[i] == data_third[i]):
|
|
data.append(data_first[i])
|
|
elif(data_second[i] == data_third[i]):
|
|
data.append(data_second[i])
|
|
else:
|
|
data.append(data_third[i]) # use last data
|
|
self._read_red_times = self._read_red_times + 1
|
|
print("read red data times", self._read_red_times)
|
|
return data
|
|
|
|
def recv_memory(self, device: int) -> Optional[bytes]:
|
|
self.pin_busy.output(False)
|
|
|
|
rx = []
|
|
|
|
try:
|
|
address = 0
|
|
|
|
# first read to get data length
|
|
tx = self._tx_buffer
|
|
tx_h = self._tx_buffer_header
|
|
|
|
tx_h[0] = MEM_INS_READ
|
|
tx_h[1] = 0
|
|
tx_h[2] = 0
|
|
|
|
|
|
# -------------------------------------read one times-------------------------------------------
|
|
data = []
|
|
flag_print = False
|
|
|
|
data = self._spi.send_byte(tx_h)
|
|
|
|
if (data[0] != 255 or data[1] != 255 or data[2] != 255):
|
|
self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
|
if (self._head_wrong_cnt[device] < 6):
|
|
print('data_first[0:3] != [255, 255, 255]', device)
|
|
print(list(data[0:7]))
|
|
|
|
data[0:3] = [255, 255, 255]
|
|
# ----------------------------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------read two times-------------------------------------------
|
|
# data = []
|
|
# data_first = []
|
|
# data_second = []
|
|
# flag_print = False
|
|
|
|
# data_first = self._spi.send_byte(tx_h)
|
|
# data_second = self._spi.send_byte(tx_h)
|
|
|
|
# if (data_first[0] != 255 or data_first[1] != 255 or data_first[2] != 255):
|
|
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
|
# if (self._head_wrong_cnt[device] < 10):
|
|
# print('data_first[0:3] != [255, 255, 255]', device)
|
|
# print(list(data_first[0:7]))
|
|
|
|
# if (data_second[0] != 255 or data_second[1] != 255 or data_second[2] != 255):
|
|
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
|
# if (self._head_wrong_cnt[device] < 10):
|
|
# print('data_second[0:3] != [255, 255, 255]', device)
|
|
# print(list(data_second[0:7]))
|
|
|
|
# if (data_first[3:] == data_second[3:]):
|
|
# data = data_first
|
|
# data[0:3] = [255, 255, 255]
|
|
|
|
# else:
|
|
# data_third = self._spi.send_byte(tx_h)
|
|
# print("read data_third", data_third)
|
|
# data = self.compare_green_data(data_first, data_second, data_third, len(tx_h))
|
|
# ----------------------------------------------------------------------------------------------
|
|
|
|
# debug use
|
|
# green_data = []
|
|
# green_data = data
|
|
# print("_[Debug] @ spi green data = ", green_data)
|
|
|
|
length = (data[3] << 8) | data[4]
|
|
header = data[7]
|
|
elite_data_len = data[9]
|
|
|
|
if length <= 4:
|
|
# print("length <= 4")
|
|
# print("green data print:", data, device, datetime.now())
|
|
return None
|
|
|
|
if data[5] != 0 or data[6] != 0:
|
|
# give a default length if the data header did not update
|
|
length = 7000
|
|
print("green data: is not [0,0], = ", data[5:7])
|
|
print("green data print:", data, device, datetime.now())
|
|
return None
|
|
|
|
if (length >= 7000):
|
|
flag_print = True
|
|
print("green data: big length:", length)
|
|
|
|
if (header != 255):
|
|
flag_print = True
|
|
print("green data: header is not 255: ", header)
|
|
|
|
if (elite_data_len != self._elite_data_len):
|
|
flag_print = True
|
|
print("green data: length is not", self._elite_data_len, ": ", elite_data_len)
|
|
|
|
if (flag_print):
|
|
print("green data print:", data, device, datetime.now())
|
|
|
|
# neulive
|
|
# address += len(data) - 11
|
|
# tx_d = self._tx_buffer_data
|
|
# red_length = len(tx_d)
|
|
|
|
# elite read all data of ram
|
|
# address = 4
|
|
# red_length = length - 1
|
|
# tx_d = [0] * red_length
|
|
|
|
address = 4
|
|
red_length = int(length / 2)
|
|
tx_d = [0] * red_length
|
|
|
|
# elite read len(_tx_buffer_data) byte
|
|
# address = 4
|
|
# tx_d = self._tx_buffer_data
|
|
|
|
while True:
|
|
tx_d[0] = MEM_INS_READ
|
|
tx_d[1] = ((address >> 8) & 0xFF)
|
|
tx_d[2] = (address & 0xFF)
|
|
# -------------------------------------read one times-------------------------------------------
|
|
data = []
|
|
data = self._spi.send_byte(tx_d)
|
|
data[0:3] = [255, 255, 255]
|
|
# ----------------------------------------------------------------------------------------------
|
|
|
|
# -------------------------------------read two times-------------------------------------------
|
|
# data = []
|
|
# data_first = []
|
|
# data_second = []
|
|
|
|
# data_first = self._spi.send_byte(tx_d)
|
|
# data_second = self._spi.send_byte(tx_d)
|
|
|
|
# if (data_first[3:] == data_second[3:]):
|
|
# data = data_first
|
|
# data[0:3] = [255, 255, 255]
|
|
# else:
|
|
# data_third = self._spi.send_byte(tx_d)
|
|
# print("read red data_third", data_third)
|
|
# data = self.compare_red_data(data_first, data_second, data_third, len(tx_d))
|
|
# ----------------------------------------------------------------------------------------------
|
|
if length + 3 <= address + len(data):
|
|
rx.extend(data[3:3 + length - address])
|
|
del data
|
|
|
|
break
|
|
|
|
else:
|
|
rx.extend(data[3:])
|
|
address += len(data) - 3
|
|
del data
|
|
|
|
# print("_[Debug] @ spi recv data rx = ")
|
|
# for i in range(0, len(rx), self._single_data_len):
|
|
# print(rx[i:i+self._single_data_len])
|
|
# print()
|
|
|
|
# /*
|
|
# * red data formate:
|
|
# * ramHdr, ramHdr, ramHdr, (3B)
|
|
# * 255, #, data_length, (3B)
|
|
# * data, (20B)
|
|
# * red_wrong, red_retry_cnt, green_wrong, green_retry_cnt, (4B)
|
|
# * 255, #, data_length, (3B)
|
|
# * */
|
|
|
|
# mark read
|
|
self._spi.send_byte(self.MEM_INS_MARKED)
|
|
|
|
except BaseException as e:
|
|
print(e)
|
|
|
|
finally:
|
|
# print("\n")
|
|
self.pin_busy.output(True)
|
|
|
|
return bytes(rx)
|
|
|
|
def read_register(self) -> int:
|
|
return self._spi.send_byte([MEM_REG_READ, 0])[1]
|
|
|
|
def write_register(self, register: int):
|
|
self._spi.send_byte([MSM_REG_WRITE, register])
|
|
|
|
def read_memory(self, address: int, length: int) -> List[int]:
|
|
tx = [MEM_INS_READ, ((address >> 8) & 0xFF), (address & 0xFF)]
|
|
tx.extend(zero_buffer(length))
|
|
|
|
return self._spi.send_byte(tx)[3:]
|
|
|
|
def write_memory(self, address: int, data: Union[bytes, List[int]]):
|
|
tx = [MEM_INS_WRITE, ((address >> 8) & 0xFF), (address & 0xFF)]
|
|
|
|
if isinstance(data, bytes):
|
|
tx.extend(iter(data))
|
|
else:
|
|
tx.extend(data)
|
|
|
|
self._spi.send_byte(tx)
|
|
|
|
def flush_all(self):
|
|
self.flush()
|
|
|
|
def foreach(self) -> Iterable[int]:
|
|
yield 0
|
|
|
|
|
|
class MultiExtMemSpiInterface(ExtMemSpiInterface):
|
|
__slots__ = ('_selector', '_wait_for_first_data')
|
|
|
|
def __init__(self,
|
|
select: Selector,
|
|
device: Tuple[int, int] = None):
|
|
super().__init__(device)
|
|
|
|
self._selector = select
|
|
|
|
self._pin_sel_val = [False for _ in range(Selector.SIZE)]
|
|
self._wait_for_first_data = [True for _ in range(Selector.SIZE)]
|
|
|
|
@property
|
|
def select(self) -> int:
|
|
return self._selector.channel
|
|
|
|
@select.setter
|
|
def select(self, value: int):
|
|
self._selector.select(value)
|
|
|
|
def changed(self, flip=False) -> bool:
|
|
channel = self._selector.channel
|
|
old = self._pin_sel_val[channel]
|
|
value = bool(self.pin_sel)
|
|
|
|
if flip:
|
|
self._pin_sel_val[channel] = value
|
|
|
|
return value != old
|
|
|
|
def reset(self):
|
|
self._spi.reset()
|
|
|
|
def close(self):
|
|
self._selector.close()
|
|
super().close()
|
|
|
|
def flush_all(self):
|
|
for _ in self._selector.foreach():
|
|
self.pin_reset.output(False)
|
|
self.pin_reset.output(True)
|
|
|
|
def foreach(self) -> Iterable[int]:
|
|
for channel in self._selector.foreach():
|
|
yield channel
|
|
|
|
def set_wait_flag(self, spi_idx:int = None, value:bool = None):
|
|
self._wait_for_first_data[spi_idx] = value
|
|
|
|
def get_wait_flag(self, spi_idx:int = None) -> Optional[bool]:
|
|
if spi_idx < Selector.SIZE:
|
|
return self._wait_for_first_data[spi_idx]
|
|
else:
|
|
return None
|
|
|
|
|
|
class ExtMemManager:
|
|
def __init__(self, ext_mem: ExtMemSpiInterface):
|
|
self._mem_sel = InputPin.get_used(P3Pin.MEM_SEL, pull_up_down=True)
|
|
self._mem_req = OutputPin.get_used(P3Pin.MEM_REQ, initial=True)
|
|
|
|
self._ext_mem = ext_mem
|
|
|
|
@property
|
|
def mem_sel(self) -> int:
|
|
return int(self._mem_sel)
|
|
|
|
@property
|
|
def mem_req(self) -> int:
|
|
return int(self._mem_req)
|
|
|
|
def mem_request(self):
|
|
self._mem_req.pulse()
|
|
sleep(_SLEEP_TIME_)
|
|
|
|
def get_ext_mem_register(self) -> List[Tuple[Optional[int], Optional[int]]]:
|
|
ret = [(None, None) for _ in range(Selector.SIZE)]
|
|
|
|
for channel in self._ext_mem.foreach():
|
|
r = [None, None]
|
|
|
|
self.mem_request()
|
|
sleep(0.01)
|
|
m1 = int(self._mem_sel)
|
|
# print("m1 = ", m1)
|
|
self._ext_mem.write_register(DEFAULT_REGISTER_VALUE)
|
|
r[m1] = self._ext_mem.read_register()
|
|
|
|
self.mem_request()
|
|
sleep(0.01)
|
|
m2 = int(self._mem_sel)
|
|
# print("m2 = ", m2)
|
|
self._ext_mem.write_register(DEFAULT_REGISTER_VALUE)
|
|
r[m2] = self._ext_mem.read_register()
|
|
|
|
ret[channel] = tuple(r)
|
|
|
|
return ret
|
|
|
|
@staticmethod
|
|
def is_no_device(result: Tuple[Optional[int], Optional[int]]) -> bool:
|
|
r1, r2 = result
|
|
return (r1 is None or r2 is None) and (r1 is None or r1 == 0) and (r2 is None or r2 == 0)
|
|
|
|
@staticmethod
|
|
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]]) -> int:
|
|
r1, r2 = result
|
|
|
|
if r1 is None or r2 is None:
|
|
return 1
|
|
|
|
if r1 is not None and r1 > 0 and r1 != DEFAULT_REGISTER_VALUE:
|
|
return 2
|
|
|
|
if r2 is not None and r2 > 0 and r2 != DEFAULT_REGISTER_VALUE:
|
|
return 3
|
|
|
|
return 0
|
|
|
|
def get_no_device_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
|
if result is None:
|
|
result = self.get_ext_mem_register()
|
|
|
|
ret = []
|
|
|
|
for channel, result in enumerate(result):
|
|
if self.is_no_device(result):
|
|
ret.append(channel)
|
|
|
|
return ret
|
|
|
|
def get_memory_test_fail(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
|
if result is None:
|
|
result = self.get_ext_mem_register()
|
|
|
|
ret = []
|
|
|
|
for channel, result in enumerate(result):
|
|
if self.is_no_device(result):
|
|
continue
|
|
|
|
if self.is_memory_test_fail(result) != 0:
|
|
ret.append(channel)
|
|
|
|
return ret
|
|
|
|
def get_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
|
if result is None:
|
|
result = self.get_ext_mem_register()
|
|
|
|
ret = []
|
|
|
|
for channel, result in enumerate(result):
|
|
if self.is_no_device(result):
|
|
continue
|
|
|
|
if self.is_memory_test_fail(result) != 0:
|
|
continue
|
|
|
|
ret.append(channel)
|
|
|
|
return ret
|
|
|
|
def test_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
|
if result is None:
|
|
result = self.get_ext_mem_register()
|
|
|
|
available_channel = []
|
|
|
|
for channel, result in enumerate(result):
|
|
r1, r2 = result
|
|
|
|
if self.is_no_device(result):
|
|
print('channel', channel, 'no device')
|
|
continue
|
|
|
|
test_pass = True
|
|
|
|
if r1 is None or r2 is None:
|
|
test_pass = False
|
|
print('channel', channel, 'mem_sel', 'x', 'not change')
|
|
|
|
if r1 is not None and r1 > 0 and r1 != DEFAULT_REGISTER_VALUE:
|
|
test_pass = False
|
|
print('channel', channel, 'mem_sel', 0, 'register', r1)
|
|
|
|
if r2 is not None and r2 > 0 and r2 != DEFAULT_REGISTER_VALUE:
|
|
test_pass = False
|
|
print('channel', channel, 'mem_sel', 1, 'register', r2)
|
|
|
|
if test_pass:
|
|
print('channel', channel, 'mem_sel', 0, 'register', r1)
|
|
print('channel', channel, 'mem_sel', 1, 'register', r2)
|
|
available_channel.append(channel)
|
|
|
|
return available_channel
|
|
|
|
def test_memory_read_write(self, channel: int, print_result=False) -> bool:
|
|
self._ext_mem.select = channel
|
|
|
|
addr = 4
|
|
size = 100
|
|
test_pass = True
|
|
|
|
while addr < MEM_SIZE:
|
|
d1 = [randint(10, 99) for _ in range(size)]
|
|
d2 = [randint(10, 99) for _ in range(size)]
|
|
|
|
self.mem_request()
|
|
m1 = int(self._mem_sel)
|
|
self._ext_mem.write_memory(addr, d1)
|
|
|
|
self.mem_request()
|
|
m2 = int(self._mem_sel)
|
|
self._ext_mem.write_memory(addr, d2)
|
|
|
|
self.mem_request()
|
|
m11 = int(self._mem_sel)
|
|
r1 = self._ext_mem.read_memory(addr, size)
|
|
|
|
if m1 != m11:
|
|
test_pass = False
|
|
if print_result:
|
|
print('channel', channel, 'mem_sel not change')
|
|
|
|
if d1 != r1:
|
|
test_pass = False
|
|
if print_result:
|
|
self.print_bytes_diff(d1, r1)
|
|
|
|
self.mem_request()
|
|
m22 = int(self._mem_sel)
|
|
r2 = self._ext_mem.read_memory(addr, size)
|
|
|
|
if m2 != m22:
|
|
test_pass = False
|
|
if print_result:
|
|
print('channel', channel, 'mem_sel not change')
|
|
|
|
if d2 != r2:
|
|
test_pass = False
|
|
if print_result:
|
|
self.print_bytes_diff(d2, r2)
|
|
|
|
addr += size
|
|
|
|
return test_pass
|
|
|
|
@staticmethod
|
|
def print_bytes_diff(_1: List[int], _2: List[int]):
|
|
s1 = ''
|
|
s2 = ''
|
|
|
|
l1 = len(_1)
|
|
l2 = len(_2)
|
|
|
|
for i in range(min(l1, l2)):
|
|
v1 = _1[i]
|
|
v2 = _2[i]
|
|
|
|
if v1 == v2:
|
|
s1 += '%02X ' % v1
|
|
s2 += '%02X ' % v2
|
|
else:
|
|
s1 += '%02X ' % v1
|
|
s2 += pc('%02X' % v2, RED) + ' '
|
|
|
|
if l1 == l2:
|
|
pass
|
|
|
|
elif l1 < l2:
|
|
for i in range(l1, l2):
|
|
s2 += pc('%02X' % _2[i], GREEN) + ' '
|
|
else:
|
|
for i in range(l2, l1):
|
|
s1 += pc('%02X' % _1[i], RED) + ' '
|
|
|
|
print(s1)
|
|
print(s2)
|
|
|
|
|
|
def hardware_test():
|
|
ext_mem = MultiExtMemSpiInterface(Selector.get(Selector.MEM_SELECTOR))
|
|
|
|
fake_mode = False
|
|
|
|
try:
|
|
ext_mem.reset()
|
|
except FileNotFoundError:
|
|
fake_mode = True
|
|
|
|
ret = {
|
|
'channel_count': Selector.SIZE,
|
|
'memory_size': MEM_SIZE,
|
|
'pin_mem_req': P3Pin.MEM_REQ,
|
|
'pin_mem_sel': P3Pin.MEM_SEL,
|
|
}
|
|
|
|
if not fake_mode:
|
|
tester = ExtMemManager(ext_mem)
|
|
|
|
result = tester.get_ext_mem_register()
|
|
no_device = tester.get_no_device_channel(result)
|
|
reg_fail = tester.get_memory_test_fail(result)
|
|
available = tester.get_available_channel(result)
|
|
|
|
channel = ['unknown' for _ in range(Selector.SIZE)]
|
|
|
|
for ch in range(len(channel)):
|
|
if ch in no_device:
|
|
channel[ch] = 'no_device'
|
|
|
|
elif ch in reg_fail:
|
|
channel[ch] = 'reg_fail'
|
|
|
|
elif not tester.test_memory_read_write(ch):
|
|
channel[ch] = 'mem_fail'
|
|
|
|
else:
|
|
channel[ch] = 'available'
|
|
|
|
ret['register'] = result
|
|
ret['available'] = available
|
|
ret['channel'] = channel
|
|
|
|
return ret
|
|
|
|
|
|
if __name__ == '__main__':
|
|
from pprint import pprint
|
|
|
|
pprint(hardware_test())
|