Skip to content

Commit

Permalink
Merge pull request #54 from bxparks/develop
Browse files Browse the repository at this point in the history
merge 1.5.1 into master
  • Loading branch information
bxparks authored Sep 20, 2022
2 parents 8a0666a + dddfd58 commit e50f0b4
Show file tree
Hide file tree
Showing 172 changed files with 2,044 additions and 1,551 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Changelog

* Unreleased
* 1.5.1 (2022-09-20)
* Add Adafruit nRF52 boards to "Tier 2" after validation by community
member.
* Upgrade tool chain
* Arduino CLI from 0.19.2 to 0.27.1
* Arduino AVR Core from 1.8.4 to 1.8.5
* STM32duino from 2.2.0 to 2.3.0
* ESP32 Core from 2.0.2 to 2.0.5
* Teensyduino from 1.56 to 1.57
* 1.5.0 (2022-03-19)
* (Re)add support for human-readable coroutine names.
* See [Coroutine Names](USER_GUIDE.md#CoroutineNames) in the
Expand Down
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ AceRoutine is a self-contained library that works on any platform supporting the
Arduino API (AVR, Teensy, ESP8266, ESP32, etc), and it provides a handful of
additional macros that can reduce boilerplate code.

**Version**: 1.5.0 (2022-03-19)
**Version**: 1.5.1 (2022-09-20)

**Changelog**: [CHANGELOG.md](CHANGELOG.md)

Expand Down Expand Up @@ -510,7 +510,7 @@ The development version can be installed by cloning the following git repos:
You can copy these directories to the `./libraries` directory used by the
Arduino IDE. (You should see 2 directories, named `./libraries/AceRoutine` and
`./libraries/AceCommon). Or you can create symlinks from `/.libraries` to these
`./libraries/AceCommon`). Or you can create symlinks from `/.libraries` to these
directories.
The `develop` branch contains the latest working version.
Expand Down Expand Up @@ -834,13 +834,13 @@ Arduino Nano:
+---------------------------------+--------+-------------+--------+
| Functionality | iters | micros/iter | diff |
|---------------------------------+--------+-------------+--------|
| EmptyLoop | 10000 | 1.900 | 0.000 |
| EmptyLoop | 10000 | 1.700 | 0.000 |
|---------------------------------+--------+-------------+--------|
| DirectScheduling | 10000 | 2.800 | 0.900 |
| DirectSchedulingWithProfiler | 10000 | 5.800 | 3.900 |
| DirectScheduling | 10000 | 2.900 | 1.200 |
| DirectSchedulingWithProfiler | 10000 | 5.700 | 4.000 |
|---------------------------------+--------+-------------+--------|
| CoroutineScheduling | 10000 | 7.000 | 5.100 |
| CoroutineSchedulingWithProfiler | 10000 | 9.300 | 7.400 |
| CoroutineScheduling | 10000 | 7.100 | 5.400 |
| CoroutineSchedulingWithProfiler | 10000 | 9.300 | 7.600 |
+---------------------------------+--------+-------------+--------+
```
Expand All @@ -850,13 +850,13 @@ ESP8266:
+---------------------------------+--------+-------------+--------+
| Functionality | iters | micros/iter | diff |
|---------------------------------+--------+-------------+--------|
| EmptyLoop | 10000 | 0.100 | 0.000 |
| EmptyLoop | 10000 | 0.200 | 0.000 |
|---------------------------------+--------+-------------+--------|
| DirectScheduling | 10000 | 0.500 | 0.400 |
| DirectSchedulingWithProfiler | 10000 | 0.800 | 0.700 |
| DirectScheduling | 10000 | 0.500 | 0.300 |
| DirectSchedulingWithProfiler | 10000 | 0.800 | 0.600 |
|---------------------------------+--------+-------------+--------|
| CoroutineScheduling | 10000 | 0.900 | 0.800 |
| CoroutineSchedulingWithProfiler | 10000 | 1.100 | 1.000 |
| CoroutineScheduling | 10000 | 0.900 | 0.700 |
| CoroutineSchedulingWithProfiler | 10000 | 1.100 | 0.900 |
+---------------------------------+--------+-------------+--------+
```
Expand All @@ -880,12 +880,16 @@ These boards are tested on each release:
**Tier 2: Should work**
These boards should work but I don't test them as often:
These boards should work, but they are not tested frequently by me, or I don't
own the specific hardware so they were tested by a community member:
* ATtiny85 (8 MHz ATtiny85)
* Arduino Pro Mini (16 MHz ATmega328P)
* Mini Mega 2560 (Arduino Mega 2560 compatible, 16 MHz ATmega2560)
* Teensy LC (48 MHz ARM Cortex-M0+)
* [Adafruit nRF52 Boards](https://github.com/adafruit/Adafruit_nRF52_Arduino)
* [Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
tested by a community member
**Tier 3: May work, but not supported**
Expand Down Expand Up @@ -924,6 +928,7 @@ This library was developed and tested using:
* [ESP8266 Arduino 3.0.2](https://github.com/esp8266/Arduino)
* [ESP32 Arduino 2.0.2](https://github.com/espressif/arduino-esp32)
* [Teensyduino 1.56](https://www.pjrc.com/teensy/td_download.html)
* [Adafruit nRF52 1.3.0](https://github.com/adafruit/Adafruit_nRF52_Arduino)
This library is *not* compatible with:
Expand Down
47 changes: 29 additions & 18 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ See the [README.md](README.md) for installation instructions and other
background information. This document describes how to use the library once it
is installed.

**Version**: 1.5.0 (2022-03-19)
**Version**: 1.5.1 (2022-09-20)

## Table of Contents

Expand Down Expand Up @@ -1153,22 +1153,25 @@ about 14 bytes of flash per invocation.

Version 1.5 added the ability to profile the execution time of
`Coroutine::runCoroutine()` and render the information as a formatted table, or
as a JSON object. If the profiling feature is not used, no additional flash
memory is consumed. The static RAM usage does increase by 2 bytes (8-bits) and 4
bytes (32-bits) per coroutine.
as a JSON object. (Thanks to peufeu2@ who proposed the idea and provided the
initial proof of concept in
[Discussion#50](https://github.com/bxparks/AceRoutine/discussions/50)).

If the profiling feature is not used, no additional flash memory is consumed.
The static RAM usage does increase by 2 bytes (8-bits) and 4 bytes (32-bits) per
coroutine even if this feature is not used. The feature seemed useful enough to
accept this small increase in static memory size, because most applications will
not use more than 5-10 coroutines, and that translates into only 10-20 bytes of
additional static RAM usage on 8-bit processors.

The following classes and API methods were added to support the profiling
feature. The `CoroutineProfiler` class is an interface that allows an object to
receive information about the execution time of the `Coroutine::runCoroutine()`
method:
feature. The `CoroutineProfiler` class is an interface whose
`updateElapsedMicros()` should be called with the execution time of the
`Coroutine::runCoroutine()` method:

```C++
class CoroutineProfiler {
public:
/**
* Process the completion of the runCoroutine() method which took
* `micros` microseconds.
*/
virtual void updateElapsedMicros(uint32_t micros) = 0;
};
```
Expand All @@ -1188,14 +1191,17 @@ class Coroutine {
};
```

The `runCoroutineWithProfiler()` method calls `runCoroutine()`, measures the
elapsed time in microseconds, then calls the `profiler->updateElapsedMicros()`.

**Note**: When creating Coroutines with profiling enabled, it will probably be
necessary to assign human-readable names to each coroutine for identification
purposes. See [Coroutine Names](#CoroutineNames) for information on the
`setName()`, `getCName()`, `getFName()`, `getNameType()`, and `printNameTo()`
methods. Each coroutine name will consume additional flash memory.

Currently only a single implementation of `CoroutineProfiler` is provided, the
`LogBinProfiler`. It contains 32 bins of `uint16_t` which tracks the number of
`LogBinProfiler`. It contains 32 bins of `uint16_t` which track the number of
times a `micros` was seen. The bins are logarithmically scaled, so that Bin 0
collects all events `<2us`, Bin 1 collects events `<4us`, Bin 2 collects events
`<8us`, ..., Bin 30 collects events `<2147s`, and the last Bin 31 collects
Expand Down Expand Up @@ -1242,7 +1248,7 @@ COROUTINE(coroutine1) {
...
}
COROUTINE(coroutine1) {
COROUTINE(coroutine2) {
...
}
Expand Down Expand Up @@ -1275,10 +1281,12 @@ COROUTINE(coroutine1) {
...
}

COROUTINE(coroutine1) {
COROUTINE(coroutine2) {
...
}

...

void setup() {
...
LogBinProfiler::createProfilers();
Expand Down Expand Up @@ -1391,7 +1399,7 @@ class LogBinJsonRenderer{

* The `printer` is usually the `Serial` object, but can be changed to something
else if needed.
* The `startBin` (0-31) and `endBin` (0-32) identify the bins which should be
* The `startBin` [0-31] and `endBin` [0-32] identify the bins which should be
printed.
* A range of something like [2, 13) is useful to keep the width of the table
reasonable.
Expand Down Expand Up @@ -1423,6 +1431,9 @@ this:
}
```

The `LogBinProfiler` uses a `uint16_t` counter, so the maximum value is
saturated to `65535`.

<a name="ProfilerResourceConsumption"></a>
### Profiler Resource Consumption

Expand Down Expand Up @@ -1459,13 +1470,13 @@ If the profiling feature is enabled, the

The [AutoBenchmark](examples/AutoBenchmark) program shows that calling the
profiler-enabled methods, `Coroutine::runCoroutineWithProfiler()` and
`CoroutineScheduler::loopWithProfiler(), increases latency by:
`CoroutineScheduler::loopWithProfiler()`, increases latency by:

* 3 - 3.2 micros on AVR
* 2.2 - 3.0 micros on AVR
* 0.4 micros on STM32F1
* 0.2 - 0.3 micros on ESP8266
* 0.1 micros on ESP32
* 0.033 - 0.166 micros on Teensy 3.2
* 0.03 - 0.17 micros on Teensy 3.2

On 32-bit processors, the overhead seems neglegible. On 8-bit processors, the 3
microsecond of overhead might be an issue with sensitive applications.
Expand Down
Loading

0 comments on commit e50f0b4

Please sign in to comment.