Skip to content

Commit a2ac0c6

Browse files
committed
Merge branch 'main' into inot_as_class_fix_breaks_workarounds
2 parents e3a4261 + 082d78c commit a2ac0c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1952
-174
lines changed

Diff for: .github/workflows/check-arduino.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ jobs:
1616

1717
steps:
1818
- name: Checkout repository
19-
uses: actions/checkout@v2
19+
uses: actions/checkout@v3
2020

2121
- name: Arduino Lint
2222
uses: arduino/arduino-lint-action@v1
2323
with:
2424
compliance: specification
2525
# Change this to "update" once the library is added to the index.
26-
library-manager: submit
26+
library-manager: update
2727
# Always use this setting for official repositories. Remove for 3rd party projects.
2828
official: true

Diff for: .github/workflows/compile-examples.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,20 @@ jobs:
6060
6161
steps:
6262
- name: Checkout
63-
uses: actions/checkout@v2
63+
uses: actions/checkout@v3
6464

6565
# it's necessary to checkout the platform before installing it so that the ArduinoCore-API dependency can be added
6666
- name: Checkout ArduinoCore-mbed
6767
# this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used
68-
uses: actions/checkout@v2
68+
uses: actions/checkout@v3
6969
with:
7070
repository: arduino/ArduinoCore-mbed
7171
# the arduino/actions/libraries/compile-examples action will install the platform from this path
7272
path: ${{ env.ARDUINOCORE_MBED_STAGING_PATH }}
7373

7474
- name: Checkout ArduinoCore-API
7575
# this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used
76-
uses: actions/checkout@v2
76+
uses: actions/checkout@v3
7777
with:
7878
repository: arduino/ArduinoCore-API
7979
path: ${{ env.ARDUINOCORE_API_STAGING_PATH }}
@@ -99,7 +99,7 @@ jobs:
9999
verbose: 'true'
100100

101101
- name: Save memory usage change report as artifact
102-
uses: actions/upload-artifact@v2
102+
uses: actions/upload-artifact@v3
103103
with:
104104
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
105105
if-no-files-found: error
@@ -114,7 +114,7 @@ jobs:
114114
- name: Download sketches reports artifact
115115
id: download-artifact
116116
continue-on-error: true # If compilation failed for all boards then there are no artifacts
117-
uses: actions/download-artifact@v2
117+
uses: actions/download-artifact@v3
118118
with:
119119
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
120120
path: ${{ env.SKETCHES_REPORTS_PATH }}

Diff for: .github/workflows/spell-check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
steps:
1818
- name: Checkout repository
19-
uses: actions/checkout@v2
19+
uses: actions/checkout@v3
2020

2121
- name: Spell check
2222
uses: codespell-project/actions-codespell@master

Diff for: .github/workflows/sync-labels.yml

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
2+
name: Sync Labels
3+
4+
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
5+
on:
6+
push:
7+
paths:
8+
- ".github/workflows/sync-labels.ya?ml"
9+
- ".github/label-configuration-files/*.ya?ml"
10+
pull_request:
11+
paths:
12+
- ".github/workflows/sync-labels.ya?ml"
13+
- ".github/label-configuration-files/*.ya?ml"
14+
schedule:
15+
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
16+
- cron: "0 8 * * *"
17+
workflow_dispatch:
18+
repository_dispatch:
19+
20+
env:
21+
CONFIGURATIONS_FOLDER: .github/label-configuration-files
22+
CONFIGURATIONS_ARTIFACT: label-configuration-files
23+
24+
jobs:
25+
check:
26+
runs-on: ubuntu-latest
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v3
31+
32+
- name: Download JSON schema for labels configuration file
33+
id: download-schema
34+
uses: carlosperate/download-file-action@v1
35+
with:
36+
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
37+
location: ${{ runner.temp }}/label-configuration-schema
38+
39+
- name: Install JSON schema validator
40+
run: |
41+
sudo npm install \
42+
--global \
43+
ajv-cli \
44+
ajv-formats
45+
46+
- name: Validate local labels configuration
47+
run: |
48+
# See: https://github.com/ajv-validator/ajv-cli#readme
49+
ajv validate \
50+
--all-errors \
51+
-c ajv-formats \
52+
-s "${{ steps.download-schema.outputs.file-path }}" \
53+
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
54+
55+
download:
56+
needs: check
57+
runs-on: ubuntu-latest
58+
59+
strategy:
60+
matrix:
61+
filename:
62+
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
63+
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
64+
- universal.yml
65+
66+
steps:
67+
- name: Download
68+
uses: carlosperate/download-file-action@v1
69+
with:
70+
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
71+
72+
- name: Pass configuration files to next job via workflow artifact
73+
uses: actions/upload-artifact@v3
74+
with:
75+
path: |
76+
*.yaml
77+
*.yml
78+
if-no-files-found: error
79+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
80+
81+
sync:
82+
needs: download
83+
runs-on: ubuntu-latest
84+
85+
steps:
86+
- name: Set environment variables
87+
run: |
88+
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
89+
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
90+
91+
- name: Determine whether to dry run
92+
id: dry-run
93+
if: >
94+
github.event_name == 'pull_request' ||
95+
(
96+
(
97+
github.event_name == 'push' ||
98+
github.event_name == 'workflow_dispatch'
99+
) &&
100+
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
101+
)
102+
run: |
103+
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
104+
# configuration.
105+
echo "::set-output name=flag::--dry-run"
106+
107+
- name: Checkout repository
108+
uses: actions/checkout@v3
109+
110+
- name: Download configuration files artifact
111+
uses: actions/download-artifact@v3
112+
with:
113+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
114+
path: ${{ env.CONFIGURATIONS_FOLDER }}
115+
116+
- name: Remove unneeded artifact
117+
uses: geekyeggo/delete-artifact@v1
118+
with:
119+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
120+
121+
- name: Merge label configuration files
122+
run: |
123+
# Merge all configuration files
124+
shopt -s extglob
125+
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
126+
127+
- name: Install github-label-sync
128+
run: sudo npm install --global github-label-sync
129+
130+
- name: Sync labels
131+
env:
132+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133+
run: |
134+
# See: https://github.com/Financial-Times/github-label-sync
135+
github-label-sync \
136+
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
137+
${{ steps.dry-run.outputs.flag }} \
138+
${{ github.repository }}

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vscode/

Diff for: README.md

+31-26
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,70 @@
22

33
`Arduino_Threads`
44
=================
5+
*Note: This library is currently in [beta](#zap-caveats).*
56

67
[![Compile Examples status](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/compile-examples.yml)
78
[![Check Arduino status](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/check-arduino.yml)
89
[![Spell Check status](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_Threads/actions/workflows/spell-check.yml)
910

10-
This library makes it easy to use the multi-threading capability of [Arduino](https://www.arduino.cc/) boards that use an [Mbed OS](https://os.mbed.com/docs/mbed-os/latest/introduction/index.html)-based core library. Additionally this library provides thread-safe access to `Wire`, `SPI` and `Serial` which is relevant when creating multi-threaded sketches in order to avoid common pitfalls such as race-conditions and invalid state.
11+
This library makes it easy to use the multi-threading capability of [Arduino](https://www.arduino.cc/) boards that use an [Mbed OS](https://os.mbed.com/docs/mbed-os/latest/introduction/index.html)-based core library. Additionally this library provides thread-safe access to `Wire`, `SPI` and `Serial` which is relevant when creating multi-threaded sketches in order to avoid common pitfalls such as race-conditions and invalid state.
1112

12-
## :zap: Features
13+
Preeliminary **documentation** and download links for **required tooling** are available within the [`/docs`](docs/README.md) subfolder.
14+
15+
## :star: Features
1316
### :thread: Multi-threaded sketch execution
14-
Instead of one big state-machine-of-doom you can split your application into multiple independent threads, each with it's own `setup()` and `loop()` function. Instead of implementing your application in a single `.ino` file, each independent thread is implemented in a dedicated `.inot` representing a clear separation of concerns on a file level.
17+
Instead of one big state-machine-of-doom you can split your application into multiple independent threads, each with it's own `setup()` and `loop()` function. Instead of implementing your application in a single `.ino` file, each independent thread is implemented in a dedicated `.inot` file (t suffix stands for **t**hread) representing a clear separation of concerns on a file level.
1518

1619
### :calling: Easy communication between multiple threads
17-
Easy inter-thread-communication is facilitated via a `Shared` abstraction providing thread-safe sink/source semantics allowing to safely exchange data of any type between threads.
20+
Easy inter-thread-communication is facilitated via a `Shared` abstraction object providing thread-safe sink/source semantics allowing to safely exchange data of any type between threads.
1821

19-
### :electric_plug: Threadsafe, asynchronous and convenient Input/Output API
20-
#### Threadsafe
21-
A key problem of multi-tasking is the **prevention of erroneous state when multiple threads share a single resource**. The following example borrowed from a typical application demonstrates the problems resulting from multiple threads sharing a single resource:
22+
### :shield: Thread-safe I/O
23+
A key problem of multi-tasking is the **prevention of erroneous state when multiple threads share a single resource**. The following example borrowed from a typical application demonstrates the problems resulting from multiple threads accessing a single resource:
2224

23-
Imagine a embedded system where multiple `Wire` client devices are physically connected to a single `Wire` server. Each `Wire` client device is managed by a separate software thread. Each thread polls its `Wire` client device periodically. Access to the I2C bus is managed via the `Wire` library and typically follows this pattern:
25+
Imagine an embedded system where multiple `Wire` client devices are physically connected to a single `Wire` server. Each `Wire` client device is managed by a separate software thread. Each thread polls its `Wire` client device periodically. Access to the I<sup>2</sup>C bus is managed via the `Wire` library and typically follows this pattern:
2426

2527
```C++
2628
/* Wire Write Access */
27-
Wire.beginTransmission(addr);
28-
Wire.write(val);
29+
Wire.beginTransmission(address);
30+
Wire.write(value);
31+
// Interrupting the current thread e.g. at this point can lead to an erroneous state
32+
// if another thread performs Wire I/O before the transmission ends.
2933
Wire.endTransmission();
3034

3135
/* Wire Read Access */
32-
Wire.beginTransmission(addr);
33-
Wire.write(val);
34-
Wire.endTransmission();
35-
Wire.requestFrom(addr, bytes)
36+
Wire.requestFrom(address, bytes)
3637
while(Wire.available()) {
37-
int val = Wire.read();
38+
int value = Wire.read();
3839
}
3940
```
4041

41-
Since we are using [ARM Mbed OS](https://os.mbed.com/mbed-os/) which is a [preemptive](https://en.wikipedia.org/wiki/Preemption_(computing)) [RTOS](https://en.wikipedia.org/wiki/Real-time_operating_system) for achieving multi-tasking capability and under the assumption that all threads share the same priority (which leads to a [round-robin](https://en.wikipedia.org/wiki/Round-robin_scheduling) scheduling) it can easily happen that one thread is half-way through its Wire IO access when the scheduler interrupts it and schedules the next thread which in turn starts/continues/ends its own Wire IO access.
42+
Since we are using [ARM Mbed OS](https://os.mbed.com/mbed-os/) which is a [preemptive](https://en.wikipedia.org/wiki/Preemption_(computing)) [RTOS](https://en.wikipedia.org/wiki/Real-time_operating_system) for achieving multi-tasking capability and under the assumption that all threads share the same priority (which leads to a [round-robin](https://en.wikipedia.org/wiki/Round-robin_scheduling) scheduling) it can easily happen that one thread is half-way through its Wire I/O access when the scheduler interrupts its execution and schedules the next thread which in turn starts, continues or ends its own Wire I/O access.
43+
44+
As a result this interruption by the scheduler will break Wire I/O access for both devices and leave the Wire I/O controller in an undefined state :fire:.
45+
46+
`Arduino_Threads` solves this problem by encapsulating the complete I/O access (e.g. reading from a `Wire` client device) within a single function call which generates an I/O request to be asynchronously executed by a high-priority I/O thread. The high-priority I/O thread is the **only** instance which directly communicates with physical hardware.
4247

43-
As a result this interruption by the scheduler will break Wire IO access for both devices and leave the Wire IO controller in an undefined state. :fire:.
48+
### :runner: Asynchronous
49+
The mechanisms implemented in this library allow any thread to dispatch an I/O request asynchronously and either continue its operation or [yield](https://en.wikipedia.org/wiki/Yield_(multithreading)) control to the next scheduled thread. All I/O requests are stored in a queue and are executed within a high-priority I/O thread after a [context-switch](https://en.wikipedia.org/wiki/Context_switch). An example of this can be seen [here](examples/Threadsafe_IO/Threadsafe_SPI/Threadsafe_SPI.ino).
4450

45-
`Arduino_Threads` solves this problem by encapsulating a complete IO access (e.g. reading from a `Wire` client device) within a single function call which generates an IO request to be asynchronously executed by a high-priority IO thread. The high-priority IO thread is the **only** instance which actually directly communicates with physical hardware.
51+
### :relieved: Convenient API
52+
Although you are free to directly manipulate I/O requests and responses (e.g. [Threadsafe_Wire](examples/Threadsafe_IO/Threadsafe_Wire/Threadsafe_Wire.ino)) there are convenient `read`/`write`/`writeThenRead` abstractions inspired by the [Adafruit_BusIO](https://github.com/adafruit/Adafruit_BusIO) library (e.g. [Threadsafe_Wire_BusIO](examples/Threadsafe_IO/Threadsafe_Wire_BusIO/Threadsafe_Wire_BusIO.ino)).
4653

47-
#### Asynchronous
48-
The mechanisms implemented in this library allow any thread to dispatch an IO request asynchronously and either continue operation or [yield](https://en.wikipedia.org/wiki/Yield_(multithreading))-ing control to the next scheduled thread. All IO requests are stored in a queue and are executed within a high-priority IO thread after a context-switch. An example of this can be seen [here](examples/Threadsafe_IO/Threadsafe_SPI/Threadsafe_SPI.ino)).
54+
## :zap: Caveats
4955

50-
#### Convenient API
51-
Although you are free to directly manipulate IO requests and responses (e.g. [Threadsafe_Wire](examples/Threadsafe_IO/Threadsafe_Wire/Threadsafe_Wire.ino)) there do exist convenient `read`/`write`/`write_then_read` abstractions inspired by the [Adafruit_BusIO](https://github.com/adafruit/Adafruit_BusIO) library (e.g. [Threadsafe_Wire_BusIO](examples/Threadsafe_IO/Threadsafe_Wire_BusIO/Threadsafe_Wire_BusIO.ino)).
56+
This library is currently in **BETA** phase. This means that neither the API nor the usage patterns are set in stone and are likely to change. We are publishing this library in the full knowledge that we can't foresee every possible use-case and edge-case. Therefore we would like to treat this library, while it's in beta phase, as an experiment and ask for your input for shaping this library. Please help us by providing feedback in the [issues section](https://github.com/bcmi-labs/Arduino_Threads/issues) or participating in our [discussions](https://github.com/arduino/language/discussions).
5257

5358
## :mag_right: Resources
5459

5560
* [How to install a library](https://www.arduino.cc/en/guide/libraries)
56-
* [Help Center](https://support.arduino.cc/)
57-
* [Forum](https://forum.arduino.cc)
61+
* [Help Center](https://support.arduino.cc/) - Get help from Arduino's official support team
62+
* [Forum](https://forum.arduino.cc) - Get support from the community
5863

5964
## :bug: Bugs & Issues
6065

61-
If you want to report an issue with this library, you can submit it to the [issue tracker](issues) of this repository. Remember to include as much detail as you can about your hardware set-up, code and steps for reproducing the issue. Make sure you're using an original Arduino board.
66+
If you found an issue in this library, you can submit it to the [issue tracker](issues) of this repository. Remember to include as much detail as you can about your hardware set-up, code and steps for reproducing the issue. To prevent hardware related incompatibilities make sure to use an [original Arduino board](https://support.arduino.cc/hc/en-us/articles/360020652100-How-to-spot-a-counterfeit-Arduino).
6267

63-
## :technologist: Development
68+
## :technologist: Contribute
6469

6570
There are many ways to contribute:
6671

0 commit comments

Comments
 (0)