Skip to content

Commit fc40d0d

Browse files
committed
monitor: Minor corrections/improvements to README.md
1 parent e15e4ed commit fc40d0d

File tree

1 file changed

+46
-30
lines changed

1 file changed

+46
-30
lines changed

v3/as_demos/monitor/README.md

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# 1. A uasyncio monitor
22

33
This library provides a means of examining the behaviour of a running
4-
`uasyncio` system. The device under test is linked to a Raspberry Pi Pico. The
4+
`uasyncio` system. The device under test is linked to a Raspberry Pico. The
55
latter displays the behaviour of the host by pin changes and/or optional print
66
statements. A logic analyser or scope provides an insight into the way an
77
asynchronous application is working; valuable informtion can also be gleaned at
@@ -25,11 +25,13 @@ trigger because another task is hogging the CPU. Lines 02 and 04 show the `foo`
2525
and `bar` tasks. Line 03 shows the `hog` task and line 05 is a trigger issued
2626
by `hog()` when it starts monopolising the CPU. The Pico issues the "hog
2727
detect" trigger 100ms after hogging starts.
28+
2829
![Image](./monitor.jpg)
2930

3031
The following image shows brief (<4ms) hogging while `quick_test.py` ran. The
3132
likely cause is garbage collection on the Pyboard D host. The monitor was able
3233
to demostrate that this never exceeded 5ms.
34+
3335
![Image](./monitor_gc.jpg)
3436

3537
### Status
@@ -43,9 +45,15 @@ The device being monitored must run firmware V1.17 or later. The `uasyncio`
4345
version should be V3 (included in the firmware). The file `monitor.py` should
4446
be copied to the target, and `monitor_pico` to the Pico.
4547

46-
## 1.2 Usage
48+
## 1.2 Quick start guide
4749

48-
A minimal example of a UART-monitored application looks like this:
50+
For UART based monitoring, ensure that the host and Pico `gnd` pins are linked.
51+
Connect the host's `txd` to the Pico pin 2 (UART(0) `rxd`). On the Pico issue:
52+
```python
53+
from monitor_pico import run
54+
run()
55+
```
56+
Adapt the following to match the UART to be used on the host and run it.
4957
```python
5058
import uasyncio as asyncio
5159
from machine import UART # Using a UART for monitoring
@@ -67,6 +75,8 @@ try:
6775
finally:
6876
asyncio.new_event_loop()
6977
```
78+
A square wave of period 200ms should be observed on Pico GPIO 4 (pin 6).
79+
7080
Example script `quick_test.py` provides a usage example. It may be adapted to
7181
use a UART or SPI interface: see commented-out code.
7282

@@ -129,7 +139,9 @@ only go low when all instances associated with that pin have terminated.
129139

130140
Consequently if `max_instances=1` and multiple instances are launched, a
131141
warning will appear on the host; the pin will go high when the first instance
132-
starts and will not go low until all have ended.
142+
starts and will not go low until all have ended. The purpose of the warning is
143+
because the existence of multiple instances may be unexpected behaviour in the
144+
application under test.
133145

134146
## 1.3 Detecting CPU hogging
135147

@@ -161,21 +173,22 @@ asyncio.create_task(monitor.hog_detect())
161173
```
162174
To aid in detecting the gaps in execution, the Pico code implements a timer.
163175
This is retriggered by activity on `ident=0`. If it times out, a brief high
164-
going pulse is produced on pin 28, along with the console message "Hog". The
176+
going pulse is produced on GPIO 28, along with the console message "Hog". The
165177
pulse can be used to trigger a scope or logic analyser. The duration of the
166178
timer may be adjusted. Other modes of hog detection are also supported. See
167179
[section 4](./README.md~4-the-pico-code).
168180

169181
## 1.4 Validation of idents
170182

171-
Re-using idents would lead to confusing behaviour. A `ValueError` is thrown if
172-
an ident is out of range or is assigned to more than one coroutine.
183+
Re-using idents would lead to confusing behaviour. If an ident is out of range
184+
or is assigned to more than one coroutine an error message is printed and
185+
execution terminates.
173186

174187
# 2. Monitoring synchronous code
175188

176189
In the context of an asynchronous application there may be a need to view the
177-
timing of synchronous code, or simply to create a trigger pulse at a known
178-
point in the code. The following are provided:
190+
timing of synchronous code, or simply to create a trigger pulse at one or more
191+
known points in the code. The following are provided:
179192
* A `sync` decorator for synchronous functions or methods: like `async` it
180193
monitors every call to the function.
181194
* A `trigger` function which issues a brief pulse on the Pico.
@@ -192,15 +205,15 @@ monitor.reserve(4, 9, 10)
192205

193206
## 2.1 The sync decorator
194207

195-
This works as per the `@async` decorator, but with no `max_instances` arg. This
196-
will activate GPIO 26 (associated with ident 20) for the duration of every call
197-
to `sync_func()`:
208+
This works as per the `@async` decorator, but with no `max_instances` arg. The
209+
following example will activate GPIO 26 (associated with ident 20) for the
210+
duration of every call to `sync_func()`:
198211
```python
199212
@monitor.sync(20)
200213
def sync_func():
201214
pass
202215
```
203-
Note that the ident must not be reserved.
216+
Note that idents used by decorators must not be reserved.
204217

205218
## 2.2 The mon_call context manager
206219

@@ -217,7 +230,7 @@ with monitor.mon_call(22):
217230
```
218231

219232
It is advisable not to use the context manager with a function having the
220-
`mon_func` decorator. The pin and report behaviour is confusing.
233+
`mon_func` decorator. The behaviour of pins and reports are confusing.
221234

222235
## 2.3 The trigger timing marker
223236

@@ -288,7 +301,7 @@ over 100ms. These behaviours can be modified by the following `run` args:
288301
1. `period=100` Define the hog_detect timer period in ms.
289302
2. `verbose=()` A list or tuple of `ident` values which should produce console
290303
output.
291-
3. `device="uart"` Set to "spi" for an SPI interface.
304+
3. `device="uart"` Set to `"spi"` for an SPI interface.
292305
4. `vb=True` By default the Pico issues console messages reporting on initial
293306
communication status, repeated each time the application under test restarts.
294307
Set `False` to disable these messages.
@@ -356,16 +369,16 @@ only goes low when the last of these three instances is cancelled.
356369
![Image](./tests/full_test.jpg)
357370

358371
`latency.py` Measures latency between the start of a monitored task and the
359-
Pico pin going high. The sequence below is first the task pulses a pin (ident
360-
6). Then the Pico pin monitoring the task goes high (ident 1 after ~20μs). Then
361-
the trigger on ident 2 occurs 112μs after the pin pulse.
372+
Pico pin going high. In the image below the sequence starts when the host
373+
pulses a pin (ident 6). The Pico pin monitoring the task then goes high (ident
374+
1 after ~20μs). Then the trigger on ident 2 occurs 112μs after the pin pulse.
362375

363376
![Image](./tests/latency.jpg)
364377

365378
`syn_test.py` Demonstrates two instances of a bound method along with the ways
366379
of monitoring synchronous code. The trigger on ident 5 marks the start of the
367380
sequence. The `foo1.pause` method on ident 1 starts and runs `foo1.wait1` on
368-
ident 3. 100ms after this ends, `foo`.wait2` on ident 4 is triggered. 100ms
381+
ident 3. 100ms after this ends, `foo.wait2` on ident 4 is triggered. 100ms
369382
after this ends, `foo1.pause` on ident 1 ends. The second instance of `.pause`
370383
(`foo2.pause`) on ident 2 repeats this sequence shifted by 50ms. The 10ms gaps
371384
in `hog_detect` show the periods of deliberate CPU hogging.
@@ -412,9 +425,10 @@ identically to other platforms and can be rebooted at will.
412425

413426
This is for anyone wanting to modify the code. Each ident is associated with
414427
two bytes, `0x40 + ident` and `0x60 + ident`. These are upper and lower case
415-
printable ASCII characters (aside from ident 0 which is `@` and the backtick
416-
character). When an ident becomes active (e.g. at the start of a coroutine),
417-
uppercase is transmitted, when it becomes inactive lowercase is sent.
428+
printable ASCII characters (aside from ident 0 which is `@` paired with the
429+
backtick character). When an ident becomes active (e.g. at the start of a
430+
coroutine), uppercase is transmitted, when it becomes inactive lowercase is
431+
sent.
418432

419433
The Pico maintains a list `pins` indexed by `ident`. Each entry is a 3-list
420434
comprising:
@@ -426,21 +440,23 @@ When a character arrives, the `ident` value is recovered. If it is uppercase
426440
the pin goes high and the instance count is incremented. If it is lowercase the
427441
instance count is decremented: if it becomes 0 the pin goes low.
428442

429-
The `init` function on the host sends `b"z"` to the Pico. This clears down the
430-
instance counters (the program under test may have previously failed, leaving
431-
instance counters non-zero). The Pico also clears variables used to measure
432-
hogging. In the case of SPI communication, before sending the `b"z"`, a 0
433-
character is sent with `cs/` high. The Pico implements a basic SPI slave using
434-
the PIO. This may have been left in an invalid state by a crashing host. It is
435-
designed to reset to a known state if it receives a character with `cs/` high.
443+
The `init` function on the host sends `b"z"` to the Pico. This sets each pin
444+
int `pins` low and clears its instance counter (the program under test may have
445+
previously failed, leaving instance counters non-zero). The Pico also clears
446+
variables used to measure hogging. In the case of SPI communication, before
447+
sending the `b"z"`, a 0 character is sent with `cs/` high. The Pico implements
448+
a basic SPI slave using the PIO. This may have been left in an invalid state by
449+
a crashing host. The slave is designed to reset to a "ready" state if it
450+
receives any character with `cs/` high.
436451

437452
The ident `@` (0x40) is assumed to be used by the `hog_detect()` function. When
438453
the Pico receives it, processing occurs to aid in hog detection and creating a
439454
trigger on GPIO28. Behaviour depends on the mode passed to the `run()` command.
440455
In the following, `thresh` is the time passed to `run()` in `period[0]`.
441456
* `SOON` This retriggers a timer with period `thresh`. Timeout causes a
442457
trigger.
443-
* `LATE` Trigger occurs if the period since the last `@` exceeds `thresh`.
458+
* `LATE` Trigger occurs if the period since the last `@` exceeds `thresh`. The
459+
trigger happens when the next `@` is received.
444460
* `MAX` Trigger occurs if period exceeds `thresh` and also exceeds the prior
445461
maximum.
446462

0 commit comments

Comments
 (0)