Skip to content

Commit a87bda1

Browse files
committed
monitor: Main modules formatted with black.
1 parent 63d818a commit a87bda1

File tree

3 files changed

+64
-36
lines changed

3 files changed

+64
-36
lines changed

v3/as_demos/monitor/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ The decorator positional args are as follows:
122122
[Pico Pin mapping](./README.md#3-pico-pin-mapping).
123123
2. `max_instances=1` Defines the maximum number of concurrent instances of the
124124
task to be independently monitored (default 1).
125+
3. `verbose=True` If `False` suppress the warning which is printed on the host
126+
if the instance count exceeds `max_instances`.
125127

126128
Whenever the coroutine runs, a pin on the Pico will go high, and when the code
127129
terminates it will go low. This enables the behaviour of the system to be

v3/as_demos/monitor/monitor.py

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,43 @@ def _quit(s):
1414
print("Monitor " + s)
1515
exit(0)
1616

17-
_write = lambda _ : _quit("must run set_device")
18-
_dummy = lambda : None # If UART do nothing.
17+
18+
_write = lambda _: _quit("must run set_device")
19+
_ifrst = lambda: None # Reset interface. If UART do nothing.
1920

2021
# For UART pass initialised UART. Baudrate must be 1_000_000.
2122
# For SPI pass initialised instance SPI. Can be any baudrate, but
2223
# must be default in other respects.
2324
def set_device(dev, cspin=None):
2425
global _write
25-
global _dummy
26+
global _ifrst
2627
if isinstance(dev, UART) and cspin is None: # UART
2728
_write = dev.write
2829
elif isinstance(dev, SPI) and isinstance(cspin, Pin):
2930
cspin(1)
31+
3032
def spiwrite(data):
3133
cspin(0)
3234
dev.write(data)
3335
cspin(1)
36+
3437
_write = spiwrite
38+
3539
def clear_sm(): # Set Pico SM to its initial state
3640
cspin(1)
3741
dev.write(b"\0") # SM is now waiting for CS low.
38-
_dummy = clear_sm
42+
43+
_ifrst = clear_sm
3944
else:
4045
_quit("set_device: invalid args.")
4146

47+
4248
# Justification for validation even when decorating a method
4349
# /mnt/qnap2/data/Projects/Python/AssortedTechniques/decorators
4450
_available = set(range(0, 22)) # Valid idents are 0..21
4551
_reserved = set() # Idents reserved for synchronous monitoring
4652

53+
4754
def _validate(ident, num=1):
4855
if ident >= 0 and ident + num < 22:
4956
try:
@@ -54,83 +61,90 @@ def _validate(ident, num=1):
5461
else:
5562
_quit("error - ident {:02d} out of range.".format(ident))
5663

64+
5765
# Reserve ID's to be used for synchronous monitoring
5866
def reserve(*ids):
5967
for ident in ids:
6068
_validate(ident)
6169
_reserved.add(ident)
6270

71+
6372
# Check whether a synchronous ident was reserved
6473
def _check(ident):
6574
if ident not in _reserved:
6675
_quit("error: synchronous ident {:02d} was not reserved.".format(ident))
6776

77+
6878
# asynchronous monitor
69-
def asyn(n, max_instances=1):
79+
def asyn(n, max_instances=1, verbose=True):
7080
def decorator(coro):
71-
# This code runs before asyncio.run()
7281
_validate(n, max_instances)
7382
instance = 0
83+
7484
async def wrapped_coro(*args, **kwargs):
75-
# realtime
7685
nonlocal instance
7786
d = 0x40 + n + min(instance, max_instances - 1)
7887
v = int.to_bytes(d, 1, "big")
7988
instance += 1
80-
if instance > max_instances: # Warning only
81-
print("Monitor {:02d} max_instances reached.".format(n))
89+
if verbose and instance > max_instances: # Warning only.
90+
print("Monitor ident: {:02d} instances: {}.".format(n, instance))
8291
_write(v)
8392
try:
8493
res = await coro(*args, **kwargs)
8594
except asyncio.CancelledError:
86-
raise
95+
raise # Other exceptions produce traceback.
8796
finally:
8897
d |= 0x20
8998
v = int.to_bytes(d, 1, "big")
9099
_write(v)
91100
instance -= 1
92101
return res
102+
93103
return wrapped_coro
104+
94105
return decorator
95106

107+
96108
# If SPI, clears the state machine in case prior test resulted in the DUT
97109
# crashing. It does this by sending a byte with CS\ False (high).
98110
def init():
99-
_dummy() # Does nothing if UART
111+
_ifrst() # Reset interface. Does nothing if UART.
100112
_write(b"z") # Clear Pico's instance counters etc.
101113

114+
102115
# Optionally run this to show up periods of blocking behaviour
103-
async def hog_detect(i=1, s=(b"\x40", b"\x60")):
116+
async def hog_detect(s=(b"\x40", b"\x60")):
104117
while True:
105-
_write(s[(i := i ^ 1)])
106-
await asyncio.sleep_ms(0)
118+
for v in s:
119+
_write(v)
120+
await asyncio.sleep_ms(0)
121+
107122

108123
# Monitor a synchronous function definition
109124
def sync(n):
110125
def decorator(func):
111126
_validate(n)
112-
dstart = 0x40 + n
113-
vstart = int.to_bytes(dstart, 1, "big")
114-
dend = 0x60 + n
115-
vend = int.to_bytes(dend, 1, "big")
127+
vstart = int.to_bytes(0x40 + n, 1, "big")
128+
vend = int.to_bytes(0x60 + n, 1, "big")
129+
116130
def wrapped_func(*args, **kwargs):
117131
_write(vstart)
118132
res = func(*args, **kwargs)
119133
_write(vend)
120134
return res
135+
121136
return wrapped_func
137+
122138
return decorator
123139

140+
124141
# Runtime monitoring: can't validate because code may be looping.
125142
# Monitor a synchronous function call
126143
class mon_call:
127144
def __init__(self, n):
128145
_check(n)
129-
self.n = n
130-
self.dstart = 0x40 + n
131-
self.vstart = int.to_bytes(self.dstart, 1, "big")
132-
self.dend = 0x60 + n
133-
self.vend = int.to_bytes(self.dend, 1, "big")
146+
self.vstart = int.to_bytes(0x40 + n, 1, "big")
147+
self.vend = int.to_bytes(0x60 + n, 1, "big")
134148

135149
def __enter__(self):
136150
_write(self.vstart)
@@ -140,6 +154,7 @@ def __exit__(self, type, value, traceback):
140154
_write(self.vend)
141155
return False # Don't silence exceptions
142156

157+
143158
# Cause pico ident n to produce a brief (~80μs) pulse
144159
def trigger(n):
145160
_check(n)

v3/as_demos/monitor/monitor_pico.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,23 @@ def spi_in():
3535

3636

3737
class PIOSPI:
38-
3938
def __init__(self):
40-
self._sm = rp2.StateMachine(0, spi_in,
41-
in_shiftdir=rp2.PIO.SHIFT_LEFT,
42-
push_thresh=8, in_base=Pin(0),
43-
jmp_pin=Pin(2, Pin.IN, Pin.PULL_UP))
39+
self._sm = rp2.StateMachine(
40+
0,
41+
spi_in,
42+
in_shiftdir=rp2.PIO.SHIFT_LEFT,
43+
push_thresh=8,
44+
in_base=Pin(0),
45+
jmp_pin=Pin(2, Pin.IN, Pin.PULL_UP),
46+
)
4447
self._sm.active(1)
4548

4649
# Blocking read of 1 char. Returns ord(ch). If DUT crashes, worst case
4750
# is where CS is left low. SM will hang until user restarts. On restart
4851
# the app
4952
def read(self):
50-
return self._sm.get() & 0xff
53+
return self._sm.get() & 0xFF
54+
5155

5256
# ****** Define pins ******
5357

@@ -64,11 +68,14 @@ def read(self):
6468
# ****** Timing *****
6569

6670
pin_t = Pin(28, Pin.OUT)
71+
72+
6773
def _cb(_):
6874
pin_t(1)
6975
print("Timeout.")
7076
pin_t(0)
7177

78+
7279
tim = Timer()
7380

7481
# ****** Monitor ******
@@ -83,38 +90,42 @@ def _cb(_):
8390

8491
# native reduced latency to 10μs but killed the hog detector: timer never timed out.
8592
# Also locked up Pico so ctrl-c did not interrupt.
86-
#@micropython.native
93+
# @micropython.native
8794
def run(period=100, verbose=(), device="uart", vb=True):
8895
if isinstance(period, int):
8996
t_ms = period
9097
mode = SOON
9198
else:
9299
t_ms, mode = period
93100
if mode not in (SOON, LATE, MAX):
94-
raise ValueError('Invalid mode.')
101+
raise ValueError("Invalid mode.")
95102
for x in verbose:
96103
pins[x][2] = True
97104
# A device must support a blocking read.
98105
if device == "uart":
99106
uart = UART(0, 1_000_000) # rx on GPIO 1
107+
100108
def read():
101109
while not uart.any(): # Prevent UART timeouts
102110
pass
103111
return ord(uart.read(1))
112+
104113
elif device == "spi":
105114
pio = PIOSPI()
115+
106116
def read():
107117
return pio.read()
118+
108119
else:
109120
raise ValueError("Unsupported device:", device)
110121

111-
vb and print('Awaiting communication')
122+
vb and print("Awaiting communication.")
112123
h_max = 0 # Max hog duration (ms)
113124
h_start = 0 # Absolute hog start time
114125
while True:
115126
if x := read(): # Get an initial 0 on UART
116-
if x == 0x7a: # Init: program under test has restarted
117-
vb and print('Got communication.')
127+
if x == 0x7A: # Init: program under test has restarted
128+
vb and print("Got communication.")
118129
h_max = 0 # Restart timing
119130
h_start = 0
120131
for pin in pins:
@@ -140,7 +151,7 @@ def read():
140151
pin_t(1)
141152
pin_t(0)
142153
h_start = t
143-
p = pins[x & 0x1f] # Key: 0x40 (ord('@')) is pin ID 0
154+
p = pins[x & 0x1F] # Key: 0x40 (ord('@')) is pin ID 0
144155
if x & 0x20: # Going down
145156
p[1] -= 1
146157
if not p[1]: # Instance count is zero
@@ -149,4 +160,4 @@ def read():
149160
p[0](1)
150161
p[1] += 1
151162
if p[2]:
152-
print(f'ident {i} count {p[1]}')
163+
print(f"ident {i} count {p[1]}")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy