mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 14:52:32 +00:00
Compare commits
488 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94f03bee01 | ||
|
|
859642d2e4 | ||
|
|
8316419a01 | ||
|
|
96f5069742 | ||
|
|
e433249bb1 | ||
|
|
2a6df797ca | ||
|
|
28aa48c8d2 | ||
|
|
582f77e4ec | ||
|
|
5700cf96d5 | ||
|
|
769a98f1f4 | ||
|
|
4ee35a0612 | ||
|
|
64f6741f82 | ||
|
|
6ad5abcab2 | ||
|
|
5480f10184 | ||
|
|
41dfbdd331 | ||
|
|
903268c52a | ||
|
|
b60c630922 | ||
|
|
95588b420c | ||
|
|
b141ec2e35 | ||
|
|
3d0c611896 | ||
|
|
6cb92143ec | ||
|
|
f919eb6a64 | ||
|
|
4147786b12 | ||
|
|
3400bcde85 | ||
|
|
e5fac4b78d | ||
|
|
4d20865c67 | ||
|
|
8b4cf91f1f | ||
|
|
6a6a10fb9b | ||
|
|
44749470a4 | ||
|
|
8fe714d8b1 | ||
|
|
22137ff1bd | ||
|
|
da3b6d1958 | ||
|
|
c7213fb710 | ||
|
|
637960edde | ||
|
|
be7e4fea6a | ||
|
|
d9209ffaea | ||
|
|
9fb94796c8 | ||
|
|
f060f7faad | ||
|
|
55673fcd66 | ||
|
|
2ff94cb11d | ||
|
|
e46bebc06f | ||
|
|
80e8b4adcc | ||
|
|
e9be03b76c | ||
|
|
98dfecdb79 | ||
|
|
8ba8278fb5 | ||
|
|
51267379ab | ||
|
|
e2cf2ba4f2 | ||
|
|
4550cce639 | ||
|
|
f2f17c81d4 | ||
|
|
7c0d13f00a | ||
|
|
f78f3232e2 | ||
|
|
a687aa8e75 | ||
|
|
ed6b89b3b1 | ||
|
|
9d3ca0d0f9 | ||
|
|
05a0405709 | ||
|
|
efd8b70089 | ||
|
|
e12c057c31 | ||
|
|
0b5b18653a | ||
|
|
dc54e7331f | ||
|
|
6fbf6b2986 | ||
|
|
feb9992d7d | ||
|
|
fb4ac82d45 | ||
|
|
acbe8c159b | ||
|
|
63474dd952 | ||
|
|
cc35ed7782 | ||
|
|
d9fd227862 | ||
|
|
1415f2bed7 | ||
|
|
5b07d454b1 | ||
|
|
0c04ba4776 | ||
|
|
b00a936f41 | ||
|
|
5b11c1ca86 | ||
|
|
7802d00031 | ||
|
|
40a15248e8 | ||
|
|
9ba9e82706 | ||
|
|
ea6c33f3d2 | ||
|
|
82e5e1858a | ||
|
|
80b14c0a6f | ||
|
|
6954d0d5f4 | ||
|
|
7e53731fe6 | ||
|
|
c7290e6ccc | ||
|
|
284317cb25 | ||
|
|
311d1a56b4 | ||
|
|
ed589727d6 | ||
|
|
62c9bad183 | ||
|
|
616da8228e | ||
|
|
3a62453b8b | ||
|
|
c3f7829255 | ||
|
|
37d9fb2dad | ||
|
|
4388e72dec | ||
|
|
9803141fe7 | ||
|
|
1f0e9cc1c3 | ||
|
|
92b30ebec6 | ||
|
|
ccadb6a43d | ||
|
|
6f7f540c79 | ||
|
|
d5b8038457 | ||
|
|
0a6059ba13 | ||
|
|
aba5b01fa0 | ||
|
|
09f4943869 | ||
|
|
29c8543f87 | ||
|
|
7bd4940ed8 | ||
|
|
d5116935b5 | ||
|
|
0d320fe29b | ||
|
|
4159461a62 | ||
|
|
f4bd39e3fa | ||
|
|
fbc36a2cfd | ||
|
|
e93ba73adb | ||
|
|
03301f093d | ||
|
|
55a5fa6fb5 | ||
|
|
4d04d10135 | ||
|
|
cda423acab | ||
|
|
0f92678c3b | ||
|
|
8d122f36e3 | ||
|
|
439cdfbb32 | ||
|
|
0a6ab31e10 | ||
|
|
0b6486256d | ||
|
|
da12b93f82 | ||
|
|
6dec6af5dc | ||
|
|
11444621ae | ||
|
|
98f1b3296c | ||
|
|
26c43e7091 | ||
|
|
9b9447858a | ||
|
|
3151cfb064 | ||
|
|
c327fee986 | ||
|
|
a4f53270e8 | ||
|
|
a7456a1126 | ||
|
|
8381512ce4 | ||
|
|
57d968cdcd | ||
|
|
20a669029b | ||
|
|
f2e6c6de58 | ||
|
|
8fa44c3590 | ||
|
|
f5b7c33d4e | ||
|
|
be8e663d39 | ||
|
|
0d4a9748e3 | ||
|
|
bd477f0fb2 | ||
|
|
5317895a5e | ||
|
|
542b8b26ce | ||
|
|
aaca854620 | ||
|
|
64da384fc1 | ||
|
|
a595fc4642 | ||
|
|
ac135be8cd | ||
|
|
ac2d3e2ae0 | ||
|
|
33946af39f | ||
|
|
5ea59a1c4d | ||
|
|
8bafd87b76 | ||
|
|
6b40e9a5e0 | ||
|
|
a2f6fd9298 | ||
|
|
bc604fc9ba | ||
|
|
9baaa13897 | ||
|
|
65e53be8b0 | ||
|
|
7f5283e95d | ||
|
|
ae4ab48ddc | ||
|
|
afccf1da02 | ||
|
|
fc07c7c01f | ||
|
|
aeb906414f | ||
|
|
a6c6b45576 | ||
|
|
13806cce93 | ||
|
|
e7eee0995a | ||
|
|
5687bd09c6 | ||
|
|
f3db895832 | ||
|
|
dd2ffe5d14 | ||
|
|
ec10e784e1 | ||
|
|
649faa1d93 | ||
|
|
669f96b367 | ||
|
|
996821d18e | ||
|
|
2e172b019e | ||
|
|
3df05cd5c1 | ||
|
|
8bb85cdc69 | ||
|
|
9f6e23754c | ||
|
|
5a7cfdffb3 | ||
|
|
caafddfdfa | ||
|
|
ee0e31be97 | ||
|
|
f1da6469a3 | ||
|
|
68e57dd3a7 | ||
|
|
2504311671 | ||
|
|
aa29315624 | ||
|
|
e3bcb87cf0 | ||
|
|
2530dc44c7 | ||
|
|
70a8fe30b7 | ||
|
|
30e538e5ed | ||
|
|
58dbc3c702 | ||
|
|
210c904604 | ||
|
|
27fdab7c8d | ||
|
|
ba3e1abb5e | ||
|
|
ce194e2162 | ||
|
|
595166db8e | ||
|
|
38d9e34a66 | ||
|
|
c1e0977db3 | ||
|
|
b4f32e7645 | ||
|
|
6bb0c95c95 | ||
|
|
4e958c9230 | ||
|
|
64cf1890f2 | ||
|
|
6a857b00db | ||
|
|
6d60a061bc | ||
|
|
6a09ddef18 | ||
|
|
d48e803b7b | ||
|
|
9061b3d8c3 | ||
|
|
2839539c6c | ||
|
|
f77a1798f3 | ||
|
|
664b558a36 | ||
|
|
c1865f127c | ||
|
|
3a69539192 | ||
|
|
cfcaf28ace | ||
|
|
d9e93f3944 | ||
|
|
60470211e5 | ||
|
|
c5851a4a0c | ||
|
|
0c0b2446b7 | ||
|
|
ce9352fd23 | ||
|
|
375ae5fe77 | ||
|
|
665d35196d | ||
|
|
9757f9ae53 | ||
|
|
e45d0c4dcf | ||
|
|
5c9f22bc18 | ||
|
|
d8287e9cdb | ||
|
|
c66e064f42 | ||
|
|
364fc84aaa | ||
|
|
fe4f86bc84 | ||
|
|
982b2e33ff | ||
|
|
8190098bb8 | ||
|
|
c99411311b | ||
|
|
da8a048dce | ||
|
|
b4de495154 | ||
|
|
aaa6af3f38 | ||
|
|
b11b322581 | ||
|
|
60b38215ce | ||
|
|
53e68515dd | ||
|
|
7676ae9184 | ||
|
|
b385feefa5 | ||
|
|
fc50b4abc0 | ||
|
|
0104a2eb3a | ||
|
|
23fdc9d1a9 | ||
|
|
ea4a678308 | ||
|
|
6566c4f15e | ||
|
|
6f39f1740f | ||
|
|
7b61bdbfd2 | ||
|
|
8e65db19b0 | ||
|
|
698fcdad36 | ||
|
|
c25d6e974f | ||
|
|
35aae48932 | ||
|
|
f8afa2703f | ||
|
|
cd903dceb9 | ||
|
|
5843c6f25e | ||
|
|
3005373760 | ||
|
|
7678540a93 | ||
|
|
463666aec5 | ||
|
|
5847f94ece | ||
|
|
09855b76ef | ||
|
|
f4d476d160 | ||
|
|
d88d4be63e | ||
|
|
154114e900 | ||
|
|
03f019dea2 | ||
|
|
a47524b762 | ||
|
|
fd2f5a5ba4 | ||
|
|
e66b2234f6 | ||
|
|
f35b15b09c | ||
|
|
99dac51b9d | ||
|
|
656faf4ce9 | ||
|
|
d9ab6986ad | ||
|
|
514d45c219 | ||
|
|
94b7fc76c1 | ||
|
|
e9923ac257 | ||
|
|
60ad1793e4 | ||
|
|
96a15bec3b | ||
|
|
fba676fc07 | ||
|
|
9ad14ad98b | ||
|
|
477c62082d | ||
|
|
82169d4115 | ||
|
|
362d5452d5 | ||
|
|
92e5a15399 | ||
|
|
114e0c4ada | ||
|
|
075ff26499 | ||
|
|
d65f2ede81 | ||
|
|
4a9248a451 | ||
|
|
1c6092c430 | ||
|
|
0e9ed1e82f | ||
|
|
02ce0558b9 | ||
|
|
63110f0134 | ||
|
|
d8db4449be | ||
|
|
fda98bbf58 | ||
|
|
aadba1f694 | ||
|
|
2c8d152885 | ||
|
|
37c598833c | ||
|
|
e80de4eba0 | ||
|
|
e382a181f7 | ||
|
|
85f69cb908 | ||
|
|
112a94e572 | ||
|
|
13307c502f | ||
|
|
8a1754efe8 | ||
|
|
8caa075bc6 | ||
|
|
d5deb49d20 | ||
|
|
575a15e135 | ||
|
|
dc7469c64b | ||
|
|
f54b18f733 | ||
|
|
db66e4dc00 | ||
|
|
47e614c7d6 | ||
|
|
03cb3c2145 | ||
|
|
a8d4b5479d | ||
|
|
de37e1bbab | ||
|
|
f0b8f10665 | ||
|
|
88b91de197 | ||
|
|
f22bb34c07 | ||
|
|
2d1cb7a43a | ||
|
|
dc169675e2 | ||
|
|
99f8253637 | ||
|
|
f3244caac1 | ||
|
|
6edaadf5d8 | ||
|
|
1f668046a0 | ||
|
|
cb2aa3b29f | ||
|
|
8ccd59a7d8 | ||
|
|
ddfdae64bf | ||
|
|
21a90a42e5 | ||
|
|
712d6e5c1e | ||
|
|
f02a2c0853 | ||
|
|
00d55c9daa | ||
|
|
a05e45f84b | ||
|
|
e650033f2c | ||
|
|
846fc14b4a | ||
|
|
a8a5e036f5 | ||
|
|
009f05b61d | ||
|
|
d8a6f82459 | ||
|
|
185fe8520a | ||
|
|
ce9bac34d6 | ||
|
|
e80673ed15 | ||
|
|
bdbaf9c655 | ||
|
|
7473a6c27a | ||
|
|
71a4cfefd5 | ||
|
|
4919129bbc | ||
|
|
a02175cec0 | ||
|
|
63affdd2e7 | ||
|
|
351687e5cd | ||
|
|
739f497bbd | ||
|
|
2d2ed591e9 | ||
|
|
871a85d688 | ||
|
|
a5f05019db | ||
|
|
e124d2094f | ||
|
|
5d874cd43b | ||
|
|
9f6cdadd3e | ||
|
|
6a3853ef35 | ||
|
|
9ea65c6793 | ||
|
|
8d14e97dfa | ||
|
|
1c63a70673 | ||
|
|
8022f3b920 | ||
|
|
420b7d48d9 | ||
|
|
5915669f6f | ||
|
|
52b01db306 | ||
|
|
a0d6ecb331 | ||
|
|
0271b02d50 | ||
|
|
9f61c78c0e | ||
|
|
4db176867b | ||
|
|
4b5cfaf9ba | ||
|
|
c014c1bafe | ||
|
|
96594516af | ||
|
|
bed20bf1fa | ||
|
|
4e5a445d8b | ||
|
|
99437d931e | ||
|
|
5166717298 | ||
|
|
49b5738f4f | ||
|
|
c753ea7cd1 | ||
|
|
5b1488ddf0 | ||
|
|
a34cfb0ee0 | ||
|
|
d8ff605d32 | ||
|
|
8031c47602 | ||
|
|
e522e47544 | ||
|
|
ed0f79b683 | ||
|
|
de1337d351 | ||
|
|
1b34a0c6d8 | ||
|
|
313380381b | ||
|
|
f56ff2ca20 | ||
|
|
da2ef0ac61 | ||
|
|
6a3033fa85 | ||
|
|
f3a1c5e679 | ||
|
|
a96c8fd4db | ||
|
|
da3ed9926b | ||
|
|
fd386d9d7f | ||
|
|
5d1614989e | ||
|
|
bae73a9526 | ||
|
|
f4b1678535 | ||
|
|
943517a1e4 | ||
|
|
03999e9d56 | ||
|
|
d5f177b1ee | ||
|
|
fdaed7e323 | ||
|
|
d39e775c95 | ||
|
|
829e0b6e26 | ||
|
|
1656c8d0cb | ||
|
|
2770cc7de3 | ||
|
|
48de631e04 | ||
|
|
66b11bcbd7 | ||
|
|
cda7487cbe | ||
|
|
e8f6504ec4 | ||
|
|
8f1b26bdda | ||
|
|
5bd3e4bcd0 | ||
|
|
fb3b62f8f0 | ||
|
|
e89fe2f7d9 | ||
|
|
16812c3ee4 | ||
|
|
c9cb293bf2 | ||
|
|
8e2e154cdd | ||
|
|
b7505ab575 | ||
|
|
cc47e29fac | ||
|
|
608f8349d9 | ||
|
|
3ecd93dcf6 | ||
|
|
dd0209b192 | ||
|
|
ae92567383 | ||
|
|
9f2646ba03 | ||
|
|
925e46da8c | ||
|
|
a6475ce848 | ||
|
|
9149912a2d | ||
|
|
2dadb4d7a2 | ||
|
|
1897d4703c | ||
|
|
a25cead7d7 | ||
|
|
3d919b21f6 | ||
|
|
d2de04d5b2 | ||
|
|
a753c942b9 | ||
|
|
9dd88281af | ||
|
|
e75561016b | ||
|
|
e2cbccb133 | ||
|
|
0271df0657 | ||
|
|
e05e324a7c | ||
|
|
71041e8674 | ||
|
|
c65b518432 | ||
|
|
6ba960ce47 | ||
|
|
8bf4919576 | ||
|
|
cca4867987 | ||
|
|
7aa47cf93b | ||
|
|
3089de79ee | ||
|
|
6b020149f3 | ||
|
|
34fae52e98 | ||
|
|
976bdad067 | ||
|
|
26d3ef529e | ||
|
|
53c3d9baa2 | ||
|
|
2a6858fa34 | ||
|
|
5440cbec6a | ||
|
|
19f5a5ef79 | ||
|
|
ef831a0b4d | ||
|
|
efc239533c | ||
|
|
ef1463a6a9 | ||
|
|
95e952b896 | ||
|
|
db72faca5e | ||
|
|
6961853ed7 | ||
|
|
5ec5248fe4 | ||
|
|
14fdd33972 | ||
|
|
140e29840a | ||
|
|
d1d318fad5 | ||
|
|
dfb6c0bb20 | ||
|
|
7339abbab5 | ||
|
|
27db0e27e8 | ||
|
|
a0b43b9a95 | ||
|
|
b6a202d68e | ||
|
|
125035d546 | ||
|
|
9f05ad2927 | ||
|
|
86ae69d360 | ||
|
|
c12fb69ca2 | ||
|
|
8b911aba7f | ||
|
|
2fa595523f | ||
|
|
190a3c2d6b | ||
|
|
1bf9d052fc | ||
|
|
e7b99b0d78 | ||
|
|
96313ee1c4 | ||
|
|
3e356e5866 | ||
|
|
1cc24de787 | ||
|
|
e6875d559c | ||
|
|
b73dd5b23b | ||
|
|
28d21ecdcc | ||
|
|
42298abfad | ||
|
|
c4a1fe0f36 | ||
|
|
0396f8f968 | ||
|
|
f1b840dede | ||
|
|
4da5d79e88 | ||
|
|
fc0c9bcfe3 | ||
|
|
32d0368f59 | ||
|
|
8bfe9fa8fc | ||
|
|
f10ad07f97 | ||
|
|
95df7dd8dc | ||
|
|
dcd1f7478a | ||
|
|
c2be6c4068 | ||
|
|
101eef5495 | ||
|
|
933d5424da | ||
|
|
ecf528f9b6 | ||
|
|
9b309fe0a0 | ||
|
|
29fd8dc7a5 | ||
|
|
624b95782d | ||
|
|
4fa25042c8 | ||
|
|
9f9cb030ad | ||
|
|
1d9290afc0 | ||
|
|
ad2f639195 | ||
|
|
07b4eea037 | ||
|
|
79c61cf0e0 | ||
|
|
80268ea56a | ||
|
|
bb9f595b8b | ||
|
|
2ad314f150 |
38
.github/ISSUE_TEMPLATE/bug-report-or-feature-proposal.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug-report-or-feature-proposal.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report or feature proposal
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Please - if you just have a question (i.e. not a bug report or a feature proposal), post in our [forum](https://meshtastic.discourse.group/) instead.
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Device info:**
|
||||||
|
- Device model: [e.g. TBEAM]
|
||||||
|
- Software Version [e.g. 0.7.8]
|
||||||
|
|
||||||
|
**Smartphone information (if relevant):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- App Version [e.g. 0.7.2]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
13
.github/pull_request_template.md
vendored
Normal file
13
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
## Thank you for sending in a pull request, here's some tips to get started!
|
||||||
|
|
||||||
|
(Please delete all these tips and replace with your text)
|
||||||
|
|
||||||
|
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
|
||||||
|
to say "hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||||
|
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
|
||||||
|
- Please do not check in files that don't have real changes
|
||||||
|
- Please do not reformat lines that you didn't have to change the code on
|
||||||
|
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor,
|
||||||
|
because automatically follows our indentation rules and it's auto reformatting will not cause spurious changes to lines.
|
||||||
|
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
|
||||||
|
- If your other co-developers have comments on your PR please tweak as needed.
|
||||||
7
.github/workflows/main.yml
vendored
7
.github/workflows/main.yml
vendored
@@ -9,6 +9,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
|
- name: Checkout submodules
|
||||||
|
uses: textbook/git-checkout-submodule-action@master
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@master
|
uses: actions/setup-python@master
|
||||||
with:
|
with:
|
||||||
@@ -17,5 +19,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio
|
||||||
|
- name: Install extra python tools
|
||||||
|
run: |
|
||||||
|
pip install -U adafruit-nrfutil
|
||||||
- name: Build
|
- name: Build
|
||||||
run: platformio run
|
run: platformio run -e tbeam -e heltec -e nrf52840dk -e rak815
|
||||||
|
|||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -7,4 +7,13 @@ main/credentials.h
|
|||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.autotools
|
||||||
|
.built
|
||||||
|
.context
|
||||||
|
.cproject
|
||||||
|
.idea/*
|
||||||
|
.vagrant
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "proto"]
|
[submodule "proto"]
|
||||||
path = proto
|
path = proto
|
||||||
url = https://github.com/meshtastic/Meshtastic-protobufs.git
|
url = https://github.com/meshtastic/Meshtastic-protobufs.git
|
||||||
|
[submodule "sdk-nrfxlib"]
|
||||||
|
path = sdk-nrfxlib
|
||||||
|
url = https://github.com/nrfconnect/sdk-nrfxlib.git
|
||||||
|
|||||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@@ -47,11 +47,21 @@
|
|||||||
"memory_resource": "cpp",
|
"memory_resource": "cpp",
|
||||||
"optional": "cpp",
|
"optional": "cpp",
|
||||||
"string_view": "cpp",
|
"string_view": "cpp",
|
||||||
"cassert": "cpp"
|
"cassert": "cpp",
|
||||||
|
"iterator": "cpp"
|
||||||
},
|
},
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"Blox",
|
||||||
|
"HFSR",
|
||||||
"Meshtastic",
|
"Meshtastic",
|
||||||
|
"NEMAGPS",
|
||||||
|
"Ublox",
|
||||||
|
"bkpt",
|
||||||
|
"cfsr",
|
||||||
"descs",
|
"descs",
|
||||||
"protobufs"
|
"ocrypto",
|
||||||
]
|
"protobufs",
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"C_Cpp.dimInactiveRegions": true
|
||||||
}
|
}
|
||||||
17
.vscode/tasks.json
vendored
Normal file
17
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "PlatformIO",
|
||||||
|
"task": "Build",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$platformio"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"label": "PlatformIO: Build"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
52
README.md
52
README.md
@@ -4,7 +4,7 @@ This is the device side code for the [meshtastic.org](https://www.meshtastic.org
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Meshtastic is a project that lets you use
|
Meshtastic™ is a project that lets you use
|
||||||
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
|
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
|
||||||
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
|
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
|
||||||
members and any text messages sent to your group chat.
|
members and any text messages sent to your group chat.
|
||||||
@@ -14,20 +14,47 @@ will optionally work with your phone, but no phone is required.
|
|||||||
|
|
||||||
Typical time between recharging the radios should be about eight days.
|
Typical time between recharging the radios should be about eight days.
|
||||||
|
|
||||||
This project is currently early-alpha, but if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
This project is is currently in beta-testing - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||||
|
|
||||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
|
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
|
||||||
|
|
||||||
## Supported hardware
|
## Supported hardware
|
||||||
|
|
||||||
We currently support three models of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4000119152086.html), [TTGO LORA32](https://www.banggood.com/LILYGO-TTGO-LORA32-868Mhz-SX1276-ESP32-Oled-Display-bluetooth-WIFI-Lora-Development-Module-Board-p-1248652.html?cur_warehouse=UK) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most users should buy the T-Beam and an 18650 battery (total cost less than \$35). Make sure to buy the frequency range which is legal for your country (915MHz for US/JP/AU/NZ, 470MHz for CN, 433MHz and 870MHz for EU). Getting a version that includes a screen is optional, but highly recommended.
|
We currently support three models of radios.
|
||||||
|
|
||||||
See (meshtastic.org) for 3D printable cases.
|
- TTGO T-Beam (usually the recommended choice)
|
||||||
|
- [T-Beam V1.1 w/ NEO-6M - special Meshtastic version](https://www.aliexpress.com/item/4001178678568.html) (Includes built-in OLED display and they have **preinstalled** the meshtastic software)
|
||||||
|
- [T-Beam V1.1 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (slightly better GPS)
|
||||||
|
- [T-Beam V0.7 w/ NEO-6M](https://www.aliexpress.com/item/4000574335430.html) (will work but **you must use the tbeam0.7 firmware ** - but the T-Beam V1.0 or later are better!)
|
||||||
|
- board labels "TTGO T22_V07 20180711"
|
||||||
|
- 3D printable cases
|
||||||
|
- [T-Beam V0](https://www.thingiverse.com/thing:3773717)
|
||||||
|
- [T-Beam V1](https://www.thingiverse.com/thing:3830711)
|
||||||
|
|
||||||
|
- [TTGO LORA32](https://www.aliexpress.com/item/4000211331316.html) - No GPS
|
||||||
|
- version 2.1
|
||||||
|
- board labels "TTGO T3_V1.6 20180606"
|
||||||
|
- 3D printable case
|
||||||
|
- [TTGO LORA32 v1](https://www.thingiverse.com/thing:3385109)
|
||||||
|
|
||||||
|
- [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/) - No GPS
|
||||||
|
- [3D Printable case](https://www.thingiverse.com/thing:3125854)
|
||||||
|
|
||||||
|
**Make sure to get the frequency for your country**
|
||||||
|
|
||||||
|
- US/JP/AU/NZ/CA - 915MHz
|
||||||
|
- CN - 470MHz
|
||||||
|
- EU - 868MHz, 433MHz
|
||||||
|
- full list of LoRa frequencies per region is available [here](https://www.thethingsnetwork.org/docs/lorawan/frequencies-by-country.html)
|
||||||
|
|
||||||
|
Getting a version that includes a screen is optional, but highly recommended.
|
||||||
|
|
||||||
## Firmware Installation
|
## Firmware Installation
|
||||||
|
|
||||||
Prebuilt binaries for the supported radios are available in our [releases](https://github.com/meshtastic/Meshtastic-esp32/releases). Your initial installation has to happen over USB from your Mac, Windows or Linux PC. Once our software is installed, all future software updates happen over bluetooth from your phone.
|
Prebuilt binaries for the supported radios are available in our [releases](https://github.com/meshtastic/Meshtastic-esp32/releases). Your initial installation has to happen over USB from your Mac, Windows or Linux PC. Once our software is installed, all future software updates happen over bluetooth from your phone.
|
||||||
|
|
||||||
|
Be **very careful** to install the correct load for your board. In particular the popular 'T-BEAM' radio from TTGO is not called 'TTGO-Lora' (that is a different board). So don't install the 'TTGO-Lora' build on a TBEAM, it won't work correctly.
|
||||||
|
|
||||||
Please post comments on our [group chat](https://meshtastic.discourse.group/) if you have problems or successes.
|
Please post comments on our [group chat](https://meshtastic.discourse.group/) if you have problems or successes.
|
||||||
|
|
||||||
### Installing from a GUI - Windows and Mac
|
### Installing from a GUI - Windows and Mac
|
||||||
@@ -40,7 +67,8 @@ Please post comments on our [group chat](https://meshtastic.discourse.group/) if
|
|||||||
6. In ESPHome Flasher, refresh the serial ports and select your board.
|
6. In ESPHome Flasher, refresh the serial ports and select your board.
|
||||||
7. Browse to the previously downloaded firmware and select the correct firmware based on the board type, country and frequency.
|
7. Browse to the previously downloaded firmware and select the correct firmware based on the board type, country and frequency.
|
||||||
8. Select Flash ESP.
|
8. Select Flash ESP.
|
||||||
9. Once finished, the terminal should start displaying debug messages including the Bluetooth passphrase when you try connect from your phone (handy if you don’t have a screen).
|
9. Once complete, “Done! Flashing is complete!” will be shown.
|
||||||
|
10. Debug messages sent from the Meshtastic device can be viewed with a terminal program such as [PuTTY](https://www.putty.org/) (Windows only). Within PuTTY, click “Serial”, enter the “Serial line” com port (can be found at step 4), enter “Speed” as 921600, then click “Open”.
|
||||||
|
|
||||||
### Installing from a commandline
|
### Installing from a commandline
|
||||||
|
|
||||||
@@ -70,9 +98,12 @@ Hard resetting via RTS pin...
|
|||||||
```
|
```
|
||||||
|
|
||||||
5. cd into the directory where the release zip file was expanded.
|
5. cd into the directory where the release zip file was expanded.
|
||||||
6. Install the correct firmware for your board with "device-install.sh firmware-_board_-_country_.bin". For instance "./device-install.sh firmware-HELTEC-US-0.0.3.bin".
|
6. Install the correct firmware for your board with `device-install.sh firmware-_board_-_country_.bin`.
|
||||||
|
- Example: `./device-install.sh firmware-HELTEC-US-0.0.3.bin`.
|
||||||
|
7. To update run `device-update.sh firmware-_board_-_country_.bin`
|
||||||
|
- Example: `./device-update.sh firmware-HELTEC-US-0.0.3.bin`.
|
||||||
|
|
||||||
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run "esptool.py --baud 921600 write*flash 0x10000 firmware-\_board*-_country_.bin". This will be faster, also all of your current preferences will be preserved.
|
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run `esptool.py --baud 921600 write_flash 0x10000 firmware-_board_-_country_-_version_.bin`. This will be faster, also all of your current preferences will be preserved.
|
||||||
|
|
||||||
You should see something like this:
|
You should see something like this:
|
||||||
|
|
||||||
@@ -145,12 +176,7 @@ Hard resetting via RTS pin...
|
|||||||
|
|
||||||
# Meshtastic Android app
|
# Meshtastic Android app
|
||||||
|
|
||||||
The source code for the (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android).
|
The companion (optional) Meshtastic Android app is [here](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-dev-readme). You can also download it on Google Play.
|
||||||
|
|
||||||
Alpha test builds available by opting into our alpha test group. See (www.meshtastic.org) for instructions.
|
|
||||||
|
|
||||||
If you don't want to live on the 'bleeding edge' you can opt-in to the beta-test or use the released version:
|
|
||||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub%26utm_medium%3Desp32-readme%26utm_campaign%3Dmeshtastic-esp32%2520readme%26anid%3Dadmob&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
|
|
||||||
|
|
||||||
# Python API
|
# Python API
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ COUNTRIES="US EU433 EU865 CN JP"
|
|||||||
#COUNTRIES=US
|
#COUNTRIES=US
|
||||||
#COUNTRIES=CN
|
#COUNTRIES=CN
|
||||||
|
|
||||||
BOARDS="ttgo-lora32-v2 ttgo-lora32-v1 tbeam heltec"
|
BOARDS="ttgo-lora32-v2 ttgo-lora32-v1 tbeam heltec tbeam0.7"
|
||||||
#BOARDS=tbeam
|
#BOARDS=tbeam
|
||||||
|
|
||||||
OUTDIR=release/latest
|
OUTDIR=release/latest
|
||||||
@@ -39,6 +39,9 @@ function do_build {
|
|||||||
cp $SRCELF $OUTDIR/elfs/firmware-$ENV_NAME-$COUNTRY-$VERSION.elf
|
cp $SRCELF $OUTDIR/elfs/firmware-$ENV_NAME-$COUNTRY-$VERSION.elf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Make sure our submodules are current
|
||||||
|
git submodule update
|
||||||
|
|
||||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
platformio lib update
|
platformio lib update
|
||||||
|
|
||||||
@@ -64,6 +67,6 @@ Generated by bin/buildall.sh -->
|
|||||||
XML
|
XML
|
||||||
|
|
||||||
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
||||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh
|
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh
|
||||||
|
|
||||||
echo BUILT ALL
|
echo BUILT ALL
|
||||||
|
|||||||
8
bin/device-update.sh
Executable file
8
bin/device-update.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FILENAME=$1
|
||||||
|
|
||||||
|
echo "Trying to update $FILENAME"
|
||||||
|
esptool.py --baud 921600 write_flash 0x10000 $FILENAME
|
||||||
3
bin/dump-ram-users.sh
Executable file
3
bin/dump-ram-users.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
arm-none-eabi-readelf -s -e .pio/build/nrf52dk/firmware.elf | head -80
|
||||||
|
|
||||||
|
nm -CSr --size-sort .pio/build/nrf52dk/firmware.elf | grep '^200'
|
||||||
@@ -1 +1,4 @@
|
|||||||
JLinkRTTViewer
|
|
||||||
|
|
||||||
|
# JLinkRTTViewer
|
||||||
|
JLinkRTTClient
|
||||||
3
bin/nrf52832-gdbserver.sh
Executable file
3
bin/nrf52832-gdbserver.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA
|
||||||
3
bin/nrf52840-gdbserver.sh
Executable file
3
bin/nrf52840-gdbserver.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52832_XXAA
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
export VERSION=0.6.1
|
export VERSION=0.7.11
|
||||||
47
boards/nrf52840_dk.json
Normal file
47
boards/nrf52840_dk.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [["0x239A", "0x4404"]],
|
||||||
|
"usb_product": "nrf52840dk",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "pca10056",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "jlink",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||||
|
},
|
||||||
|
"url": "https://meshtastic.org/",
|
||||||
|
"vendor": "Nordic Semi"
|
||||||
|
}
|
||||||
|
|
||||||
46
boards/nrf52840_dk_modified.json
Normal file
46
boards/nrf52840_dk_modified.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [["0x239A", "0x4404"]],
|
||||||
|
"usb_product": "nrf52840dk",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "pca10056-rc-clock",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "jlink",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||||
|
},
|
||||||
|
"url": "https://meshtastic.org/",
|
||||||
|
"vendor": "Nordic Semi"
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
"hwids": [["0x239A", "0x4403"]],
|
"hwids": [["0x239A", "0x4403"]],
|
||||||
"usb_product": "PPR",
|
"usb_product": "PPR",
|
||||||
"mcu": "nrf52840",
|
"mcu": "nrf52840",
|
||||||
"variant": "pca10056-rc-clock",
|
"variant": "ppr",
|
||||||
"variants_dir": "variants",
|
"variants_dir": "variants",
|
||||||
"bsp": {
|
"bsp": {
|
||||||
"name": "adafruit"
|
"name": "adafruit"
|
||||||
|
|||||||
55
boards/rak815.json
Normal file
55
boards/rak815.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"ldscript": "nrf52832_s132_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DNRF52832_XXAA -DNRF52",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x10c4",
|
||||||
|
"0xea60"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"usb_product": "RAK815",
|
||||||
|
"mcu": "nrf52832",
|
||||||
|
"variant": "rak815",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS132",
|
||||||
|
"sd_name": "s132",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"bluetooth"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52832_xxAA",
|
||||||
|
"svd_path": "nrf52.svd"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino"
|
||||||
|
],
|
||||||
|
"name": "RAK RAK815",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 65536,
|
||||||
|
"maximum_size": 524288,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": "https://store.rakwireless.com/products/rak815-hybrid-location-tracker",
|
||||||
|
"vendor": "RAK"
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# What is Meshtastic?
|
# What is Meshtastic?
|
||||||
|
|
||||||
Meshtastic is a project that lets you use
|
Meshtastic™ is a project that lets you use
|
||||||
inexpensive (\$30 ish) GPS radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding - essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other members and any text messages sent to your group chat.
|
inexpensive (\$30 ish) GPS radios as an extensible, long battery life, secure, mesh GPS communicator. These radios are great for hiking, skiing, paragliding - essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other members and any text messages sent to your group chat.
|
||||||
|
|
||||||
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios will optionally work with your phone, but no phone is required.
|
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios will optionally work with your phone, but no phone is required.
|
||||||
|
|
||||||
@@ -24,21 +24,27 @@ Not all of these features are fully implemented yet - see **important** disclaim
|
|||||||
- Very long battery life (should be about eight days with the beta software)
|
- Very long battery life (should be about eight days with the beta software)
|
||||||
- Built in GPS and [LoRa](https://en.wikipedia.org/wiki/LoRa) radio, but we manage the radio automatically for you
|
- Built in GPS and [LoRa](https://en.wikipedia.org/wiki/LoRa) radio, but we manage the radio automatically for you
|
||||||
- Long range - a few miles per node but each node will forward packets as needed
|
- Long range - a few miles per node but each node will forward packets as needed
|
||||||
|
- Secure - channels are encrypted by AES256 (But see important disclaimers below wrt this feature)
|
||||||
- Shows direction and distance to all members of your channel
|
- Shows direction and distance to all members of your channel
|
||||||
- Directed or broadcast text messages for channel members
|
- Directed or broadcast text messages for channel members
|
||||||
- Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor
|
- Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor
|
||||||
- Communication API for bluetooth devices (such as our Android app) to use the mesh. So if you have some application that needs long range low power networking, this might work for you.
|
- Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers.
|
||||||
- Eventually (within a couple of months) we should have a modified version of Signal that works with this project.
|
|
||||||
- Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
|
- Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
|
||||||
|
|
||||||
This project is currently in early alpha - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
This project is currently in beta testing but it is fairly stable and feature complete - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||||
|
|
||||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [forum](https://meshtastic.discourse.group/).
|
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [forum](https://meshtastic.discourse.group/).
|
||||||
|
|
||||||
|
### Beginner's Guide
|
||||||
|
|
||||||
|
For an detailed walk-through aimed at beginners, we recommend [meshtastic.letstalkthis.com](https://meshtastic.letstalkthis.com/).
|
||||||
|
|
||||||
# Updates
|
# Updates
|
||||||
|
|
||||||
Note: Updates are happening almost daily, only major updates are listed below. For more details see our forum.
|
Note: Updates are happening almost daily, only major updates are listed below. For more details see our forum.
|
||||||
|
|
||||||
|
- 06/24/2020 - 0.7.x Now with over 1000 android users, over 600 people using the radios and translated into 13 languages. Fairly stable and we are working through bugs to get to 1.0.
|
||||||
|
- 06/04/2020 - 0.6.7 Beta releases of both the application and the device code are released. Features are fairly solid now with a sizable number of users.
|
||||||
- 04/28/2020 - 0.6.0 [Python API](https://pypi.org/project/meshtastic/) released. Makes it easy to use meshtastic devices as "zero config / just works" mesh transport adapters for other projects.
|
- 04/28/2020 - 0.6.0 [Python API](https://pypi.org/project/meshtastic/) released. Makes it easy to use meshtastic devices as "zero config / just works" mesh transport adapters for other projects.
|
||||||
- 04/20/2020 - 0.4.3 Pretty solid now both for the android app and the device code. Many people have donated translations and code. Probably going to call it a beta soon.
|
- 04/20/2020 - 0.4.3 Pretty solid now both for the android app and the device code. Many people have donated translations and code. Probably going to call it a beta soon.
|
||||||
- 03/03/2020 - 0.0.9 of the Android app and device code is released. Still an alpha but fairly functional.
|
- 03/03/2020 - 0.0.9 of the Android app and device code is released. Still an alpha but fairly functional.
|
||||||
@@ -50,7 +56,7 @@ Note: Updates are happening almost daily, only major updates are listed below. F
|
|||||||
|
|
||||||
Our Android application is available here:
|
Our Android application is available here:
|
||||||
|
|
||||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dhomepage%26anid%3Dadmob)
|
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-homepage)
|
||||||
|
|
||||||
The link above will return older more stable releases. We would prefer if you join our alpha-test group, because the application is rapidly improving. Three steps to opt-in to the alpha- test:
|
The link above will return older more stable releases. We would prefer if you join our alpha-test group, because the application is rapidly improving. Three steps to opt-in to the alpha- test:
|
||||||
|
|
||||||
@@ -62,8 +68,9 @@ If you'd like to help with development, the source code is [on github](https://g
|
|||||||
|
|
||||||
## Supported hardware
|
## Supported hardware
|
||||||
|
|
||||||
We currently support two brands of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4000119152086.html) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most people should buy the T-Beam and a 18650 battery (total cost less than \$35). Make
|
We currently support two brands of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4001178678568.html) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most people should buy the T-Beam and a 18650 battery (total cost less than \$35). Also, the version of the T-Beam we link to is shipped with Meshtastic **preinstalled** by TTGO, so you don't have to install it yourself.
|
||||||
sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen is optional, but highly recommended.
|
|
||||||
|
Make sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen is optional, but highly recommended.
|
||||||
|
|
||||||
Instructions for installing prebuilt firmware can be found [here](https://github.com/meshtastic/Meshtastic-esp32/blob/master/README.md).
|
Instructions for installing prebuilt firmware can be found [here](https://github.com/meshtastic/Meshtastic-esp32/blob/master/README.md).
|
||||||
|
|
||||||
|
|||||||
8
docs/SupportedHardware.md
Normal file
8
docs/SupportedHardware.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
| Vendor | Product line | Version | Board labels | Notes | URL |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| TTGO | T-Beam | 0.7 | T22_V07 20180711 | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>GPS ublox NEO-6M , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4000574335430.html) |
|
||||||
|
| TTGO | T-Beam | 1.0 | | | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||||
|
| TTGO | T-Beam | 1.1 | T22_V11 20191212 | LoRa 433/470MHz *OR* LoRa 868/915MHz *OR* LoRa 923MHz , <br/>GPS ublox NEO-M8N , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||||
|
| TTGO | Lora32 | 2.0 | *missing* | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>OLED SSD1306 , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000211331316.html) |
|
||||||
|
| TTGO | Lora32 | 2.1 | T3_V1.6 20180606 | LoRa 32 (V2) , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000119208093.html) |
|
||||||
|
| Heltec | Lora 32 | V2 | V2 | LoRa 433/470MHz *OR* LoRa 868/915MHz | [buy](https://heltec.org/project/wifi-lora-32/) |
|
||||||
@@ -4,7 +4,7 @@ This project is still pretty young but moving at a pretty good pace. Not all fea
|
|||||||
Most of these problems should be solved by the beta release (within three months):
|
Most of these problems should be solved by the beta release (within three months):
|
||||||
|
|
||||||
- We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
|
- We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
|
||||||
- Encryption is turned off for now
|
- The encryption implementation is good but see this list of [caveats](software/crypto.md#summary-of-strengthsweaknesses-of-our-current-implementation) to determine risks you might face.
|
||||||
- A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
|
- A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
|
||||||
- The Android API needs to be documented better
|
- The Android API needs to be documented better
|
||||||
- No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-)
|
- No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-)
|
||||||
|
|||||||
6
docs/hardware/cubecell-TODO.md
Normal file
6
docs/hardware/cubecell-TODO.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
https://heltec-automation-docs.readthedocs.io/en/latest/cubecell/index.html
|
||||||
|
|
||||||
|
https://github.com/HelTecAutomation/ASR650x-Arduino?utm_source=platformio.org&utm_medium=docs
|
||||||
|
|
||||||
|
* Either portfreertos or make not theaded versions of Lock, WorkerThread, Queue (probably the latter).
|
||||||
BIN
docs/hardware/nrf52/nrf52-programming.png
Normal file
BIN
docs/hardware/nrf52/nrf52-programming.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
BIN
docs/hardware/rak815/PE4259.pdf
Normal file
BIN
docs/hardware/rak815/PE4259.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/rak815/RAK813 Module Datasheet V1.0.pdf
Normal file
BIN
docs/hardware/rak815/RAK813 Module Datasheet V1.0.pdf
Normal file
Binary file not shown.
3692
docs/hardware/rak815/RAK813_BLE_LoRa_Schematic_20180322.pdf
Normal file
3692
docs/hardware/rak815/RAK813_BLE_LoRa_Schematic_20180322.pdf
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
8249
docs/hardware/rak815/ublox max7 datasheet.pdf
Normal file
8249
docs/hardware/rak815/ublox max7 datasheet.pdf
Normal file
File diff suppressed because one or more lines are too long
@@ -1,207 +1,72 @@
|
|||||||
# High priority
|
# Geeksville's current work queue
|
||||||
|
|
||||||
Items to complete soon (next couple of alpha releases).
|
You probably don't care about this section - skip to the next one.
|
||||||
|
|
||||||
- lower wait_bluetooth_secs to 30 seconds once we have the GPS power on (but GPS in sleep mode) across light sleep. For the time
|
- brf52 ble
|
||||||
being I have it set at 2 minutes to ensure enough time for a GPS lock from scratch.
|
- update protocol description per cyclomies
|
||||||
|
- esp32 pairing
|
||||||
- remeasure wake time power draws now that we run CPU down at 80MHz
|
- update faq with antennas https://meshtastic.discourse.group/t/range-test-ideas-requested/738/2
|
||||||
|
- update faq on recommended android version and phones
|
||||||
# AXP192 tasks
|
- add help link inside the app, reference a page on the wiki
|
||||||
|
- turn on amazon reviews support
|
||||||
- figure out why this fixme is needed: "FIXME, disable wake due to PMU because it seems to fire all the time?"
|
- add a tablet layout (with map next to messages) in the android app
|
||||||
- "AXP192 interrupt is not firing, remove this temporary polling of battery state"
|
|
||||||
- make debug info screen show real data (including battery level & charging) - close corresponding github issue
|
|
||||||
|
|
||||||
# Medium priority
|
# Medium priority
|
||||||
|
|
||||||
Items to complete before the first beta release.
|
Items to complete before 1.0.
|
||||||
|
|
||||||
- Don't store position packets in the to phone fifo if we are disconnected. The phone will get that info for 'free' when it
|
# Post 1.0 ideas
|
||||||
fetches the fresh nodedb.
|
|
||||||
- Use the RFM95 sequencer to stay in idle mode most of the time, then automatically go to receive mode and automatically go from transmit to receive mode. See 4.2.8.2 of manual.
|
|
||||||
- possibly switch to https://github.com/SlashDevin/NeoGPS for gps comms
|
|
||||||
- good source of battery/signal/gps icons https://materialdesignicons.com/
|
|
||||||
- research and implement better mesh algorithm - investigate changing routing to https://github.com/sudomesh/LoRaLayer2 ?
|
|
||||||
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/
|
|
||||||
- use fuse bits to store the board type and region. So one load can be used on all boards
|
|
||||||
- the BLE stack is leaking about 200 bytes each time we go to light sleep
|
|
||||||
- rx signal measurements -3 marginal, -9 bad, 10 great, -10 means almost unusable. So scale this into % signal strength. preferably as a graph, with an X indicating loss of comms.
|
|
||||||
- assign every "channel" a random shared 8 bit sync word (per 4.2.13.6 of datasheet) - use that word to filter packets before even checking CRC. This will ensure our CPU will only wake for packets on our "channel"
|
|
||||||
- Note: we do not do address filtering at the chip level, because we might need to route for the mesh
|
|
||||||
- add basic crypto - https://github.com/chegewara/esp32-mbedtls-aes-test/blob/master/main/main.c https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation - use ECB at first (though it is shit) because it doesn't require us to send 16 bytes of IV with each packet. Then OFB per example. Possibly do this crypto at the data payload level only, so that all of the packet routing metadata
|
|
||||||
is in cleartext (so that nodes will route for other radios that are cryptoed with a key we don't know)
|
|
||||||
- add frequency hopping, dependent on the gps time, make the switch moment far from the time anyone is going to be transmitting
|
|
||||||
- share channel settings over Signal (or qr code) by embedding an an URL which is handled by the MeshUtil app.
|
|
||||||
- publish update articles on the web
|
|
||||||
|
|
||||||
# Pre-beta priority
|
- finish DSR for unicast
|
||||||
|
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though.
|
||||||
During the beta timeframe the following improvements 'would be nice' (and yeah - I guess some of these items count as features, but it is a hobby project ;-) )
|
|
||||||
|
|
||||||
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
|
|
||||||
for it (because it will redownload the nodedb when it comes back)
|
|
||||||
- Figure out why the RF95 ISR is never seeing RH_RF95_VALID_HEADER, so it is not protecting our rx packets from getting stomped on by sends
|
|
||||||
- fix the frequency error reading in the RF95 RX code (can't do floating point math in an ISR ;-)
|
|
||||||
- See CustomRF95::send and fix the problem of dropping partially received packets if we want to start sending
|
|
||||||
- make sure main cpu is not woken for packets with bad crc or not addressed to this node - do that in the radio hw
|
|
||||||
- triple check fcc compliance
|
|
||||||
- pick channel center frequency based on channel name? "dolphin" would hash to 900Mhz, "cat" to 905MHz etc? allows us to hide the concept of channel # from hte user.
|
|
||||||
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
|
|
||||||
- make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired
|
- make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired
|
||||||
- if radio params change fundamentally, discard the nodedb
|
- if radio params change fundamentally, discard the nodedb
|
||||||
- reneable the bluetooth battery level service on the T-BEAM, because we can read battery level there
|
- re-enable the bluetooth battery level service on the T-BEAM
|
||||||
|
- provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ]
|
||||||
|
|
||||||
|
# Low priority ideas
|
||||||
|
|
||||||
|
Items after the first final candidate release.
|
||||||
|
|
||||||
|
- dynamic frequency scaling could save a lot of power on ESP32, but it seems to corrupt uart (even with ref_tick set correctly)
|
||||||
|
- Change back to using a fixed sized MemoryPool rather than MemoryDynamic (see bug #149)
|
||||||
|
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
|
||||||
|
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
|
||||||
|
for it (because it will redownload the nodedb when it comes back)
|
||||||
|
- add frequency hopping, dependent on the gps time, make the switch moment far from the time anyone is going to be transmitting
|
||||||
|
- assign every "channel" a random shared 8 bit sync word (per 4.2.13.6 of datasheet) - use that word to filter packets before even checking CRC. This will ensure our CPU will only wake for packets on our "channel"
|
||||||
|
- the BLE stack is leaking about 200 bytes each time we go to light sleep
|
||||||
|
- use fuse bits to store the board type and region. So one load can be used on all boards
|
||||||
|
- Don't store position packets in the to phone fifo if we are disconnected. The phone will get that info for 'free' when it
|
||||||
|
fetches the fresh nodedb.
|
||||||
|
- Use the RFM95 sequencer to stay in idle mode most of the time, then automatically go to receive mode and automatically go from transmit to receive mode. See 4.2.8.2 of manual.
|
||||||
|
- Use fixed32 for node IDs, packetIDs, successid, failid, and lat/lon - will require all nodes to be updated, but make messages slightly smaller.
|
||||||
|
- add "store and forward" support for messages, or move to the DB sync model. This would allow messages to be eventually delivered even if nodes are out of contact at the moment.
|
||||||
|
- use variable length Strings in protobufs (instead of current fixed buffers). This would save lots of RAM
|
||||||
|
- use BLEDevice::setPower to lower our BLE transmit power - extra range doesn't help us, it costs amps and it increases snoopability
|
||||||
|
- make a HAM build: just a new frequency list, a bool to say 'never do encryption' and use hte callsign as that node's unique id. -from Girts
|
||||||
|
- don't forward redundant pings or ping responses to the phone, it just wastes phone battery
|
||||||
|
- don't send location packets if we haven't moved significantly
|
||||||
|
- scrub default radio config settings for bandwidth/range/speed
|
||||||
|
- show radio and gps signal strength as an image
|
||||||
|
- only BLE advertise for a short time after the screen is on and button pressed - to save power and prevent people for sniffing for our BT app.
|
||||||
|
- make mesh aware network timing state machine (sync wake windows to gps time) - this can save LOTS of battery
|
||||||
|
- split out the software update utility so other projects can use it. Have the appload specify the URL for downloads.
|
||||||
|
- read the PMU battery fault indicators and blink/led/warn user on screen
|
||||||
|
- discard very old nodedb records (> 1wk)
|
||||||
|
- handle millis() rollover in GPS.getTime - otherwise we will break after 50 days
|
||||||
|
- report esp32 device code bugs back to the mothership via android
|
||||||
|
- change BLE bonding to something more secure. see comment by pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND)
|
||||||
|
|
||||||
|
Changes related to wifi support on ESP32:
|
||||||
|
|
||||||
|
- iram space: https://esp32.com/viewtopic.php?t=8460
|
||||||
|
- set https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/external-ram.html spi ram bss
|
||||||
|
- figure out if iram or bluetooth classic caused ble problems
|
||||||
|
- post bug on esp32-arduino with BLE bug findings
|
||||||
|
|
||||||
# Spinoff project ideas
|
# Spinoff project ideas
|
||||||
|
|
||||||
- an open source version of https://www.burnair.ch/skynet/
|
- an open source version of https://www.burnair.ch/skynet/
|
||||||
- a paragliding app like http://airwhere.co.uk/
|
- a paragliding app like http://airwhere.co.uk/
|
||||||
- a version with a solar cell for power, just mounted high to permanently provide routing for nodes in a valley. Someone just pointed me at disaster.radio
|
|
||||||
- How do avalanche beacons work? Could this do that as well? possibly by using beacon mode feature of the RF95?
|
- How do avalanche beacons work? Could this do that as well? possibly by using beacon mode feature of the RF95?
|
||||||
- provide generalized (but slow) internet message forwarding servie if one of our nodes has internet connectivity
|
|
||||||
|
|
||||||
# Low priority
|
|
||||||
|
|
||||||
Items after the first final candidate release.
|
|
||||||
|
|
||||||
- use variable length arduino Strings in protobufs (instead of current fixed buffers)
|
|
||||||
- use BLEDevice::setPower to lower our BLE transmit power - extra range doesn't help us, it costs amps and it increases snoopability
|
|
||||||
- make an install script to let novices install software on their boards
|
|
||||||
- use std::map<NodeInfo\*, std::string> in node db
|
|
||||||
- make a HAM build: yep - that's a great idea. I'll add it to the TODO. should be pretty painless - just a new frequency list, a bool to say 'never do encryption' and use hte callsign as that node's unique id. -from Girts
|
|
||||||
- don't forward redundant pings or ping responses to the phone, it just wastes phone battery
|
|
||||||
- use https://platformio.org/lib/show/1260/OneButton if necessary
|
|
||||||
- don't send location packets if we haven't moved
|
|
||||||
- scrub default radio config settings for bandwidth/range/speed
|
|
||||||
- answer to pings (because some other user is looking at our nodeinfo) with our latest location (not a stale location)
|
|
||||||
- show radio and gps signal strength as an image
|
|
||||||
- only BLE advertise for a short time after the screen is on and button pressed - to save power and prevent people for sniffing for our BT app.
|
|
||||||
- make mesh aware network timing state machine (sync wake windows to gps time)
|
|
||||||
- split out the software update utility so other projects can use it. Have the appload specify the URL for downloads.
|
|
||||||
- read the PMU battery fault indicators and blink/led/warn user on screen
|
|
||||||
- the AXP debug output says it is trying to charge at 700mA, but the max I've seen is 180mA, so AXP registers probably need to be set to tell them the circuit can only provide 300mAish max. So that the low charge rate kicks in faster and we don't wear out batteries.
|
|
||||||
- increase the max charging rate a bit for 18650s, currently it limits to 180mA (at 4V). Work backwards from the 500mA USB limit (at 5V) and let the AXP charge at that rate.
|
|
||||||
- discard very old nodedb records (> 1wk)
|
|
||||||
- using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
|
|
||||||
- We let anyone BLE scan for us (FIXME, perhaps only allow that until we are paired with a phone and configured)
|
|
||||||
- use two different buildenv flags for ttgo vs lora32. https://docs.platformio.org/en/latest/ide/vscode.html#key-bindings
|
|
||||||
- sim gps data for testing nodes that don't have hardware
|
|
||||||
- do debug serial logging to android over bluetooth
|
|
||||||
- break out my bluetooth OTA software as a seperate library so others can use it
|
|
||||||
- Heltec LoRa32 has 8MB flash, use a bigger partition table if needed - TTGO is 4MB but has PSRAM
|
|
||||||
- add a watchdog timer
|
|
||||||
- handle millis() rollover in GPS.getTime - otherwise we will break after 50 days
|
|
||||||
- report esp32 device code bugs back to the mothership via android
|
|
||||||
|
|
||||||
# Done
|
|
||||||
|
|
||||||
- change the partition table to take advantage of the 4MB flash on the wroom: http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
|
||||||
- wrap in nice MeshRadio class
|
|
||||||
- add mesh send & rx
|
|
||||||
- make message send from android go to service, then to mesh radio
|
|
||||||
- make message receive from radio go through to android
|
|
||||||
- test loopback tx/rx path code without using radio
|
|
||||||
- notify phone when rx packets arrive, currently the phone polls at startup only
|
|
||||||
- figure out if we can use PA_BOOST - yes, it seems to be on both boards
|
|
||||||
- implement new ble characteristics
|
|
||||||
- have MeshService keep a node DB by sniffing user messages
|
|
||||||
- have a state machine return the correct FromRadio packet to the phone, it isn't always going to be a MeshPacket. Do a notify on fromnum to force the radio to read our state machine generated packets
|
|
||||||
- send my_node_num when phone sends WantsNodes
|
|
||||||
- have meshservice periodically send location data on mesh (if device has a GPS)
|
|
||||||
- implement getCurrentTime() - set based off gps but then updated locally
|
|
||||||
- make default owner record have valid usernames
|
|
||||||
- message loop between node 0x28 and 0x7c
|
|
||||||
- check in my radiolib fixes
|
|
||||||
- figure out what is busted with rx
|
|
||||||
- send our owner info at boot, reply if we see anyone send theirs
|
|
||||||
- add manager layers
|
|
||||||
- confirm second device receives that gps message and updates device db
|
|
||||||
- send correct hw vendor in the bluetooth info - needed so the android app can update different radio models
|
|
||||||
- correctly map nodeids to nodenums, currently we just do a proof of concept by always doing a broadcast
|
|
||||||
- add interrupt detach/sleep mode config to lora radio so we can enable deepsleep without panicing
|
|
||||||
- make jtag work on second board
|
|
||||||
- implement regen owner and radio prefs
|
|
||||||
- use a better font
|
|
||||||
- make nice screens (boot, about to sleep, debug info (gps signal, #people), latest text, person info - one frame per person on network)
|
|
||||||
- turn framerate from ui->state.frameState to 1 fps (or less) unless in transition
|
|
||||||
- switch to my gui layout manager
|
|
||||||
- make basic gui. different screens: debug, one page for each user in the user db, last received text message
|
|
||||||
- make button press cycle between screens
|
|
||||||
- save our node db on entry to sleep
|
|
||||||
- fix the logo
|
|
||||||
- sent/received packets (especially if a node was just reset) have variant of zero sometimes - I think there is a bug (race-condtion?) in the radio send/rx path.
|
|
||||||
- DONE dynamic nodenum assignment tasks
|
|
||||||
- make jtag debugger id stable: https://askubuntu.com/questions/49910/how-to-distinguish-between-identical-usb-to-serial-adapters
|
|
||||||
- reported altitude is crap
|
|
||||||
- good tips on which bands might be more free https://github.com/TheThingsNetwork/ttn/issues/119
|
|
||||||
- finish power measurements (GPS on during sleep vs LCD on during sleep vs LORA on during sleep) and est battery life
|
|
||||||
- make screen sleep behavior work
|
|
||||||
- make screen advance only when a new node update arrives, a new text arrives or the user presses a button, turn off screen after a while
|
|
||||||
- after reboot, channel number is getting reset to zero! fix!
|
|
||||||
- send user and location events much less often
|
|
||||||
- send location (or if not available user) when the user wakes the device from display sleep (both for testing and to improve user experience)
|
|
||||||
- make real implementation of getNumOnlineNodes
|
|
||||||
- very occasionally send our position and user packet based on the schedule in the radio info (if for nothing else so that other nodes update last_seen)
|
|
||||||
- show real text info on the text screen
|
|
||||||
- apply radio settings from android land
|
|
||||||
- cope with nodes that have 0xff or 0x00 as the last byte of their mac
|
|
||||||
- allow setting full radio params from android
|
|
||||||
- add receive timestamps to messages, inserted by esp32 when message is received but then shown on the phone
|
|
||||||
- update build to generate both board types
|
|
||||||
- have node info screen show real info (including distance and heading)
|
|
||||||
- blink the power led less often
|
|
||||||
- have radiohead ISR send messages to RX queue directly, to allow that thread to block until we have something to send
|
|
||||||
- move lora rx/tx to own thread and block on IO
|
|
||||||
- keep our pseudo time moving forward even if we enter deep sleep (use esp32 rtc)
|
|
||||||
- for non GPS equipped devices, set time from phone
|
|
||||||
- GUI on oled hangs for a few seconds occasionally, but comes back
|
|
||||||
- update local GPS position (but do not broadcast) at whatever rate the GPS is giving it
|
|
||||||
- don't send our times to other nodes
|
|
||||||
- don't trust times from other nodes
|
|
||||||
- draw compass rose based off local walking track
|
|
||||||
- add requestResponse optional bool - use for location broadcasts when sending tests
|
|
||||||
- post sample video to signal forum
|
|
||||||
- support non US frequencies
|
|
||||||
- send pr https://github.com/ThingPulse/esp8266-oled-ssd1306 to tell them about this project
|
|
||||||
- document rules for sleep wrt lora/bluetooth/screen/gps. also: if I have text messages (only) for the phone, then give a few seconds in the hopes BLE can get it across before we have to go back to sleep.
|
|
||||||
- wake from light sleep as needed for our next scheduled periodic task (needed for gps position broadcasts etc)
|
|
||||||
- turn bluetooth off based on our sleep policy
|
|
||||||
- blink LED while in LS sleep mode
|
|
||||||
- scrolling between screens based on press is busted
|
|
||||||
- Use Neo-M8M API to put it in sleep mode (on hold until my new boards arrive)
|
|
||||||
- update the prebuilt bins for different regulatory regions
|
|
||||||
- don't enter NB state if we've recently talked to the phone (to prevent breaking syncing or bluetooth sw update)
|
|
||||||
- have sw update prevent BLE sleep
|
|
||||||
- manually delete characteristics/descs
|
|
||||||
- leave lora receiver always on
|
|
||||||
- protobufs are sometimes corrupted after sleep!
|
|
||||||
- stay awake while charging
|
|
||||||
- check gps battery voltage
|
|
||||||
- if a position report includes ground truth time and we don't have time yet, set our clock from that. It is better than nothing.
|
|
||||||
- retest BLE software update for both board types
|
|
||||||
- report on wikifactory
|
|
||||||
- send note to the guy who designed the cases
|
|
||||||
- turn light sleep on aggressively (while lora is on but BLE off)
|
|
||||||
- Use the Periodic class for both position and user periodic broadcasts
|
|
||||||
- don't treat north as up, instead adjust shown bearings for our guess at the users heading (i.e. subtract one from the other)
|
|
||||||
- sendToMesh can currently block for a long time, instead have it just queue a packet for a radio freertos thread
|
|
||||||
- don't even power on bluetooth until we have some data to send to the android phone. Most of the time we should be sleeping in a lowpower "listening for lora" only mode. Once we have some packets for the phone, then power on bluetooth
|
|
||||||
until the phone pulls those packets. Ever so often power on bluetooth just so we can see if the phone wants to send some packets. Possibly might need ULP processor to help with this wake process.
|
|
||||||
- do hibernation mode to get power draw down to 2.5uA https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/
|
|
||||||
- fix GPS.zeroOffset calculation it is wrong
|
|
||||||
- (needs testing) fixed the following during a plane flight:
|
|
||||||
Have state machine properly enter deep sleep based on loss of mesh and phone comms.
|
|
||||||
Default to enter deep sleep if no LORA received for two hours (indicates user has probably left the mesh).
|
|
||||||
- (fixed I think) text messages are not showing on local screen if screen was on
|
|
||||||
- add links to todos
|
|
||||||
- link to the kanban page
|
|
||||||
- add a getting started page
|
|
||||||
- finish mesh alg reeval
|
|
||||||
- ublox gps parsing seems a little buggy (we shouldn't be sending out read solution commands, the device is already broadcasting them)
|
|
||||||
- turn on gps https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example18_PowerSaveMode/Example18_PowerSaveMode.ino
|
|
||||||
- switch gps to 38400 baud https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example11_ResetModule/Example2_FactoryDefaultsviaSerial/Example2_FactoryDefaultsviaSerial.ino
|
|
||||||
- Use Neo-M8M API to put it in sleep mode
|
|
||||||
- use gps sleep mode instead of killing its power (to allow fast position when we wake)
|
|
||||||
- enable fast lock and low power inside the gps chip
|
|
||||||
- Make a FAQ
|
|
||||||
- add a SF12 transmit option for _super_ long range
|
|
||||||
|
|||||||
14
docs/software/ant.md
Normal file
14
docs/software/ant.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# ANT protocol notes
|
||||||
|
|
||||||
|
SD340 terms are reasonable for NRF52
|
||||||
|
https://www.thisisant.com/developer/components/nrf52832#tab_protocol_stacks_tab
|
||||||
|
|
||||||
|
Profiles to implement:
|
||||||
|
|
||||||
|
tracker
|
||||||
|
https://www.thisisant.com/developer/ant-plus/device-profiles/#4365_tab
|
||||||
|
|
||||||
|
ebike
|
||||||
|
https://www.thisisant.com/developer/ant-plus/device-profiles/#527_tab
|
||||||
|
|
||||||
|
no profile for messaging?
|
||||||
@@ -6,10 +6,11 @@ in these instructions I describe use of their command line tool.
|
|||||||
1. Purchase a suitable radio (see above)
|
1. Purchase a suitable radio (see above)
|
||||||
2. Install [PlatformIO](https://platformio.org/platformio-ide)
|
2. Install [PlatformIO](https://platformio.org/platformio-ide)
|
||||||
3. Download this git repo and cd into it
|
3. Download this git repo and cd into it
|
||||||
4. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with "hw_version" and instructions are provided above that line. Options are provided for EU433, EU835, CN, JP and US. Pull-requests eagerly accepted for other countries.
|
4. Run `git submodule update --init --recursive` to pull in dependencies this project needs.
|
||||||
5. Plug the radio into your USB port
|
5. If you are outside the USA, run "export COUNTRY=EU865" (or whatever) to set the correct frequency range for your country. Options are provided for `EU433`, `EU865`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries.
|
||||||
6. Type "pio run --environment XXX -t upload" (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either tbeam, heltec, ttgo-lora32-v1, ttgo-lora32-v2).
|
6. Plug the radio into your USB port
|
||||||
7. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
|
7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tbeam`, `heltec`, `ttgo-lora32-v1`, `ttgo-lora32-v2`).
|
||||||
|
8. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
|
||||||
|
|
||||||
## Decoding stack traces
|
## Decoding stack traces
|
||||||
|
|
||||||
|
|||||||
51
docs/software/crypto.md
Normal file
51
docs/software/crypto.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Encryption in Meshtastic
|
||||||
|
|
||||||
|
Cryptography is tricky, so we've tried to 'simply' apply standard crypto solutions to our implementation. However,
|
||||||
|
the project developers are not cryptography experts. Therefore we ask two things:
|
||||||
|
|
||||||
|
- If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our
|
||||||
|
notes below and offering advice? We will happily give as much or as little credit as you wish ;-).
|
||||||
|
- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary
|
||||||
|
(but we can't yet make a more confident statement).
|
||||||
|
|
||||||
|
## Summary of strengths/weaknesses of our current implementation
|
||||||
|
|
||||||
|
Based on comments from reviewers (see below), here's some tips for usage of these radios. So you can know the level of protection offered:
|
||||||
|
|
||||||
|
* It is pretty likely that the AES256 security is implemented 'correctly' and an observer will not be able to decode your messages.
|
||||||
|
* Warning: If an attacker is able to get one of the radios in their position, they could either a) extract the channel key from that device or b) use that radio to listen to new communications.
|
||||||
|
* Warning: If an attacker is able to get the "Channel QR code/URL" that you share with others - that attacker could then be able to read any messages sent on the channel (either tomorrow or in the past - if they kept a raw copy of those broadcast packets)
|
||||||
|
|
||||||
|
Possible future areas of work (if there is enough interest - post in our [forum](https://meshtastic.discourse.group) if you want this):
|
||||||
|
|
||||||
|
1. Optionally requiring users to provide a PIN to regain access to the mesh. This could be based on: intentionally locking the device, time since last use, or any member could force all members to reauthenticate,
|
||||||
|
2. Until a device reauthenticates, any other access via BLE or USB would be blocked (this would protect against attackers who are not prepared to write custom software to extract and reverse engineer meshtastic flash memory)
|
||||||
|
3. Turning on read-back protection in the device fuse-bits (this would extend protection in #2 to block all but **extremely** advanced attacks involving chip disassembly)
|
||||||
|
4. Time limiting keys used for message transmission and automatically cycling them on a schedule. This would protect past messages from being decoded even if an attacker learns the current key.
|
||||||
|
|
||||||
|
### Notes for reviewers
|
||||||
|
|
||||||
|
If you are reviewing our implementation, this is a brief statement of our method.
|
||||||
|
|
||||||
|
- We do all crypto at the SubPacket (payload) level only, so that all meshtastic nodes will route for others - even those channels which are encrypted with a different key.
|
||||||
|
- Mostly based on reading [Wikipedia](<https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)>) and using the modes the ESP32 provides support for in hardware.
|
||||||
|
- We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration.
|
||||||
|
- Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
|
||||||
|
- The node number concatenated with the packet number is used as the NONCE. This nonce will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero.
|
||||||
|
- The packet number is sent in cleartext with each packet. The node number can be derived from the "from" field of each packet. (Cleartext is acceptable because it merely provides IV for each encryption run)
|
||||||
|
- Each 16 byte BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet.
|
||||||
|
- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Since our packets are small counter portion will really never be higher than 32 (five bits).
|
||||||
|
|
||||||
|
## Comments from reviewer #1
|
||||||
|
|
||||||
|
This reviewer is a cryptography professional, but would like to remain anonymous. We thank them for their comments ;-):
|
||||||
|
|
||||||
|
I'm assuming that meshtastic is being used to hike in places where someone capable is trying to break it - like you were going to walk around DefCon using these. I spent about an hour reviewing the encryption, and have the following notes:
|
||||||
|
|
||||||
|
* The write-up isn't quite as clear as the code.
|
||||||
|
* The code is using AES-CTR mode correctly to ensure confidentiality.
|
||||||
|
* The comment for initNonce really covers the necessary information.
|
||||||
|
* I think the bigger encryption question is "what does the encryption need to do"? As it stands, an attacker who has yet to capture any of the devices cannot reasonably capture text or location data. An attacker who captures any device in the channel/mesh can read everything going to that device, everything stored on that device, and any other communication within the channel that they captured in encrypted form. If that capability basically matches your expectations, it is suitable for whatever adventures this was intended for, then, based on information publicly available or widely disclosed, the encryption is good. If those properties are distressing (like, device history is deliberately limited and you don't want a device captured today to endanger the information sent over the channel yesterday) we could talk about ways to achieve that (most likely synchronizing time and replacing the key with its own SHA256 every X hours, and ensuring the old key is not retained unnecessarily).
|
||||||
|
* Two other things to keep in mind are that AES-CTR does not itself provide authenticity (e.g. an attacker can flip bits in replaying data and scramble the resulting plaintext), and that the current scheme gives some hints about transmission in the size. So, if you worry about an adversary deliberately messing-up messages or knowing the length of a text message, it looks like those might be possible.
|
||||||
|
|
||||||
|
I'm guessing that the network behaves somewhat like a store-and-forward network - or, at least, that the goal is to avoid establishing a two-way connection to transmit data. I'm afraid I haven't worked with mesh networks much, but remember studying them briefly in school about ten years ago.
|
||||||
@@ -1,28 +1,51 @@
|
|||||||
# Bluetooth API
|
# Device API
|
||||||
|
|
||||||
The Bluetooth API is design to have only a few characteristics and most polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
The Device API is design to have only a simple stream of ToRadio and FromRadio packets and all polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
||||||
|
|
||||||
## A note on MTU sizes
|
## Streaming version
|
||||||
|
|
||||||
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
This protocol is **almost** identical when it is deployed over BLE, Serial/USB or TCP (our three currently supported transports for connecting to phone/PC). Most of this document is in terms of the original BLE version, but this section describes the small changes when this API is exposed over a Streaming (non datagram) transport. The streaming version has the following changes:
|
||||||
|
|
||||||
## MeshBluetoothService
|
- We assume the stream is reliable (though the protocol will resynchronize if bytes are lost or corrupted). i.e. we do not include CRCs or error correction codes.
|
||||||
|
- Packets always have a four byte header (described below) prefixed before each packet. This header provides framing characters and length.
|
||||||
|
- The stream going towards the radio is only a series of ToRadio packets (with the extra 4 byte headers)
|
||||||
|
- The stream going towards the PC is a stream of FromRadio packets (with the 4 byte headers), or if the receiver state machine does not see valid header bytes it can (optionally) print those bytes as the debug console from the radio. This allows the device to emit regular serial debugging messages (which can be understood by a terminal program) but also switch to a more structured set of protobufs once it sees that the PC client has sent a protobuf towards it.
|
||||||
|
|
||||||
|
The 4 byte header is constructed to both provide framing and to not look line 'normal' 7 bit ASCII.
|
||||||
|
|
||||||
|
- Byte 0: START1 (0x94)
|
||||||
|
- Byte 1: START2 (0xc3)
|
||||||
|
- Byte 2: MSB of protobuf length
|
||||||
|
- Byte 3: LSB of protobuf length
|
||||||
|
|
||||||
|
The receiver will validate length and if >512 it will assume the packet is corrupted and return to looking for START1. While looking for START1 any other characters are printed as "debug output". For small example implementation of this reader see the meshtastic-python implementation.
|
||||||
|
|
||||||
|
## MeshBluetoothService (the BLE API)
|
||||||
|
|
||||||
This is the main bluetooth service for the device and provides the API your app should use to get information about the mesh, send packets or provision the radio.
|
This is the main bluetooth service for the device and provides the API your app should use to get information about the mesh, send packets or provision the radio.
|
||||||
|
|
||||||
For a reference implementation of a client that uses this service see [RadioInterfaceService](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt). Typical flow when
|
For a reference implementation of a client that uses this service see [RadioInterfaceService](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt).
|
||||||
a phone connects to the device should be the following:
|
|
||||||
|
|
||||||
|
Typical flow when a phone connects to the device should be the following (if you want to watch this flow from the python app just run "meshtastic --debug --info" - the flow over BLE is identical):
|
||||||
|
|
||||||
|
- There are only three relevant endpoints (and they have built in BLE documentation - so use a BLE tool of your choice to watch them): FromRadio, FromNum (sends notifies when new data is available in FromRadio) and ToRadio
|
||||||
- SetMTU size to 512
|
- SetMTU size to 512
|
||||||
|
- Write a ToRadio.startConfig protobuf to the "ToRadio" endpoint" - this tells the radio you are a new connection and you need the entire NodeDB sent down.
|
||||||
|
- Read repeatedly from the "FromRadio" endpoint. Each time you read you will get back a FromRadio protobuf (see Meshtatastic-protobuf). Keep reading from this endpoint until you get back and empty buffer.
|
||||||
|
- See below for the expected sequence for your initial download.
|
||||||
|
- After the initial download, you should subscribe for BLE "notify" on the "FromNum" endpoint. If a notification arrives, that means there are now one or more FromRadio packets waiting inside FromRadio. Read from FromRadio until you get back an empty packet.
|
||||||
|
- Any time you want to send packets to the radio, you should write a ToRadio packet into ToRadio.
|
||||||
|
|
||||||
|
Expected sequence for initial download:
|
||||||
|
|
||||||
|
- After your send startConfig, you will receive a series of FromRadio packets. The sequence of these packets will be as follows (but you are best not counting on this, instead just update your model for whatever packet you receive - based on looking at the type)
|
||||||
- Read a RadioConfig from "radio" - used to get the channel and radio settings
|
- Read a RadioConfig from "radio" - used to get the channel and radio settings
|
||||||
- Read (and write if incorrect) a User from "user" - to get the username for this node
|
- Read a User from "user" - to get the username for this node
|
||||||
- Read a MyNodeInfo from "mynode" to get information about this local device
|
- Read a MyNodeInfo from "mynode" to get information about this local device
|
||||||
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
|
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
|
||||||
- Read from "nodeinfo" until it returns empty to build the phone's copy of the current NodeDB for the mesh
|
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
|
||||||
- Read from "fromradio" until it returns empty to get any messages that arrived for this node while the phone was away
|
- Read a endConfig packet that indicates that the entire state you need has been sent.
|
||||||
- Subscribe to notify on "fromnum" to get notified whenever the device has a new received packet
|
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away
|
||||||
- Read that new packet from "fromradio"
|
|
||||||
- Whenever the phone has a packet to send write to "toradio"
|
|
||||||
|
|
||||||
For definitions (and documentation) on FromRadio, ToRadio, MyNodeInfo, NodeInfo and User protocol buffers see [mesh.proto](https://github.com/meshtastic/Meshtastic-protobufs/blob/master/mesh.proto)
|
For definitions (and documentation) on FromRadio, ToRadio, MyNodeInfo, NodeInfo and User protocol buffers see [mesh.proto](https://github.com/meshtastic/Meshtastic-protobufs/blob/master/mesh.proto)
|
||||||
|
|
||||||
@@ -62,16 +85,20 @@ Not all messages are kept in the fromradio queue (filtered based on SubPacket):
|
|||||||
- No WantNodeNum / DenyNodeNum messages are kept
|
- No WantNodeNum / DenyNodeNum messages are kept
|
||||||
A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging)
|
A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging)
|
||||||
|
|
||||||
## Protobuf API
|
### A note on MTU sizes
|
||||||
|
|
||||||
|
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
||||||
|
|
||||||
|
### Protobuf API
|
||||||
|
|
||||||
On connect, you should send a want_config_id protobuf to the device. This will cause the device to send its node DB and radio config via the fromradio endpoint. After sending the full DB, the radio will send a want_config_id to indicate it is done sending the configuration.
|
On connect, you should send a want_config_id protobuf to the device. This will cause the device to send its node DB and radio config via the fromradio endpoint. After sending the full DB, the radio will send a want_config_id to indicate it is done sending the configuration.
|
||||||
|
|
||||||
## Other bluetooth services
|
### Other bluetooth services
|
||||||
|
|
||||||
This document focuses on the core mesh service, but it is worth noting that the following other Bluetooth services are also
|
This document focuses on the core device protocol, but it is worth noting that the following other Bluetooth services are also
|
||||||
provided by the device.
|
provided by the device.
|
||||||
|
|
||||||
### BluetoothSoftwareUpdate
|
#### BluetoothSoftwareUpdate
|
||||||
|
|
||||||
The software update service. For a sample function that performs a software update using this API see [startUpdate](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt).
|
The software update service. For a sample function that performs a software update using this API see [startUpdate](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt).
|
||||||
|
|
||||||
@@ -89,10 +116,10 @@ Characteristics
|
|||||||
| GATT_UUID_MANU_NAME/0x2a29 | read | |
|
| GATT_UUID_MANU_NAME/0x2a29 | read | |
|
||||||
| GATT_UUID_HW_VERSION_STR/0x2a27 | read | |
|
| GATT_UUID_HW_VERSION_STR/0x2a27 | read | |
|
||||||
|
|
||||||
### DeviceInformationService
|
#### DeviceInformationService
|
||||||
|
|
||||||
Implements the standard BLE contract for this service (has software version, hardware model, serial number, etc...)
|
Implements the standard BLE contract for this service (has software version, hardware model, serial number, etc...)
|
||||||
|
|
||||||
### BatteryLevelService
|
#### BatteryLevelService
|
||||||
|
|
||||||
Implements the standard BLE contract service, provides battery level in a way that most client devices should automatically understand (i.e. it should show in the bluetooth devices screen automatically)
|
Implements the standard BLE contract service, provides battery level in a way that most client devices should automatically understand (i.e. it should show in the bluetooth devices screen automatically)
|
||||||
16
docs/software/esp32-arduino-build-notes.md
Normal file
16
docs/software/esp32-arduino-build-notes.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# esp32-arduino build instructions
|
||||||
|
|
||||||
|
We build our own custom version of esp32-arduino, in order to get some fixes we've made but haven't yet been merged in master.
|
||||||
|
|
||||||
|
These are a set of currently unformatted notes on how to build and install them. Most developers should not care about this, because
|
||||||
|
you'll automatically get our fixed libraries.
|
||||||
|
|
||||||
|
```
|
||||||
|
last EDF release in arduino is: https://github.com/espressif/arduino-esp32/commit/1977370e6fc069e93ffd8818798fbfda27ae7d99
|
||||||
|
IDF release/v3.3 46b12a560
|
||||||
|
IDF release/v3.3 367c3c09c
|
||||||
|
https://docs.espressif.com/projects/esp-idf/en/release-v3.3/get-started/linux-setup.html
|
||||||
|
kevinh@kevin-server:~/development/meshtastic/esp32-arduino-lib-builder\$ python /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/esp-idf/components/esptool*py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/build/bootloader/bootloader.bin
|
||||||
|
cp -a out/tools/sdk/* components/arduino/tools/sdk
|
||||||
|
cp -ar components/arduino/* ~/.platformio/packages/framework-arduinoespressif32@src-fba9d33740f719f712e9f8b07da6ea13/
|
||||||
|
```
|
||||||
@@ -1,19 +1,93 @@
|
|||||||
# Mesh broadcast algorithm
|
# Mesh broadcast algorithm
|
||||||
|
|
||||||
FIXME - instead look for standard solutions. this approach seems really suboptimal, because too many nodes will try to rebroast. If
|
|
||||||
all else fails could always use the stock Radiohead solution - though super inefficient.
|
|
||||||
|
|
||||||
great source of papers and class notes: http://www.cs.jhu.edu/~cs647/
|
great source of papers and class notes: http://www.cs.jhu.edu/~cs647/
|
||||||
|
|
||||||
|
flood routing improvements
|
||||||
|
|
||||||
|
- DONE if we don't see anyone rebroadcast our want_ack=true broadcasts, retry as needed.
|
||||||
|
|
||||||
|
reliable messaging tasks (stage one for DSR):
|
||||||
|
|
||||||
|
- DONE generalize naive flooding
|
||||||
|
- DONE add a max hops parameter, use it for broadcast as well (0 means adjacent only, 1 is one forward etc...). Store as three bits in the header.
|
||||||
|
- DONE add a 'snoopReceived' hook for all messages that pass through our node.
|
||||||
|
- DONE use the same 'recentmessages' array used for broadcast msgs to detect duplicate retransmitted messages.
|
||||||
|
- DONE in the router receive path?, send an ack packet if want_ack was set and we are the final destination. FIXME, for now don't handle multihop or merging of data replies with these acks.
|
||||||
|
- DONE keep a list of packets waiting for acks
|
||||||
|
- DONE for each message keep a count of # retries (max of three). Local to the node, only for the most immediate hop, ignorant of multihop routing.
|
||||||
|
- DONE delay some random time for each retry (large enough to allow for acks to come in)
|
||||||
|
- DONE once an ack comes in, remove the packet from the retry list and deliver the ack to the original sender
|
||||||
|
- DONE after three retries, deliver a no-ack packet to the original sender (i.e. the phone app or mesh router service)
|
||||||
|
- DONE test one hop ack/nak with the python framework
|
||||||
|
- DONE Do stress test with acks
|
||||||
|
|
||||||
|
dsr tasks
|
||||||
|
|
||||||
|
- DONE oops I might have broken message reception
|
||||||
|
- DONE Don't use broadcasts for the network pings (close open github issue)
|
||||||
|
- DONE add ignoreSenders to radioconfig to allow testing different mesh topologies by refusing to see certain senders
|
||||||
|
- DONE test multihop delivery with the python framework
|
||||||
|
|
||||||
|
optimizations / low priority:
|
||||||
|
|
||||||
|
- read this [this](http://pages.cs.wisc.edu/~suman/pubs/nadv-mobihoc05.pdf) paper and others and make our naive flood routing less naive
|
||||||
|
- read @cyclomies long email with good ideas on optimizations and reply
|
||||||
|
- DONE Remove NodeNum assignment algorithm (now that we use 4 byte node nums)
|
||||||
|
- DONE make android app warn if firmware is too old or too new to talk to
|
||||||
|
- change nodenums and packetids in protobuf to be fixed32
|
||||||
|
- low priority: think more careful about reliable retransmit intervals
|
||||||
|
- make ReliableRouter.pending threadsafe
|
||||||
|
- bump up PacketPool size for all the new ack/nak/routing packets
|
||||||
|
- handle 51 day rollover in doRetransmissions
|
||||||
|
- use a priority queue for the messages waiting to send. Send acks first, then routing messages, then data messages, then broadcasts?
|
||||||
|
|
||||||
|
when we send a packet
|
||||||
|
|
||||||
|
- do "hop by hop" routing
|
||||||
|
- when sending, if destnodeinfo.next_hop is zero (and no message is already waiting for an arp for that node), startRouteDiscovery() for that node. Queue the message in the 'waiting for arp queue' so we can send it later when then the arp completes.
|
||||||
|
- otherwise, use next_hop and start sending a message (with ack request) towards that node (starting with next_hop).
|
||||||
|
|
||||||
|
when we receive any packet
|
||||||
|
|
||||||
|
- sniff and update tables (especially useful to find adjacent nodes). Update user, network and position info.
|
||||||
|
- if we need to route() that packet, resend it to the next_hop based on our nodedb.
|
||||||
|
- if it is broadcast or destined for our node, deliver locally
|
||||||
|
- handle routereply/routeerror/routediscovery messages as described below
|
||||||
|
- then free it
|
||||||
|
|
||||||
|
routeDiscovery
|
||||||
|
|
||||||
|
- if we've already passed through us (or is from us), then it ignore it
|
||||||
|
- use the nodes already mentioned in the request to update our routing table
|
||||||
|
- if they were looking for us, send back a routereply
|
||||||
|
- NOT DOING FOR NOW -if max_hops is zero and they weren't looking for us, drop (FIXME, send back error - I think not though?)
|
||||||
|
- if we receive a discovery packet, and we don't have next_hop set in our nodedb, we use it to populate next_hop (if needed) towards the requester (after decrementing max_hops)
|
||||||
|
- if we receive a discovery packet, and we have a next_hop in our nodedb for that destination we send a (reliable) we send a route reply towards the requester
|
||||||
|
|
||||||
|
when sending any reliable packet
|
||||||
|
|
||||||
|
- if timeout doing retries, send a routeError (nak) message back towards the original requester. all nodes eavesdrop on that packet and update their route caches.
|
||||||
|
|
||||||
|
when we receive a routereply packet
|
||||||
|
|
||||||
|
- update next_hop on the node, if the new reply needs fewer hops than the existing one (we prefer shorter paths). fixme, someday use a better heuristic
|
||||||
|
|
||||||
|
when we receive a routeError packet
|
||||||
|
|
||||||
|
- delete the route for that failed recipient, restartRouteDiscovery()
|
||||||
|
- if we receive routeerror in response to a discovery,
|
||||||
|
- fixme, eventually keep caches of possible other routes.
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- DONE reread the radiohead mesh implementation - hop to hop acknoledgement seems VERY expensive but otherwise it seems like DSR
|
- optimize our generalized flooding with heuristics, possibly have particular nodes self mark as 'router' nodes.
|
||||||
|
|
||||||
|
- DONE reread the radiohead mesh implementation - hop to hop acknowledgement seems VERY expensive but otherwise it seems like DSR
|
||||||
- DONE read about mesh routing solutions (DSR and AODV)
|
- DONE read about mesh routing solutions (DSR and AODV)
|
||||||
- DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
- DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
||||||
- DONE reread the disaster radio protocol docs - seems based on Babel (which is AODVish)
|
- DONE reread the disaster radio protocol docs - seems based on Babel (which is AODVish)
|
||||||
- possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack - does the opensource stack implement multihop routing? flooding? their discussion mailing list looks dead-dead
|
- REJECTED - seems dying - possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack - does the opensource stack implement multihop routing? flooding? their discussion mailing list looks dead-dead
|
||||||
- update duty cycle spreadsheet for our typical usecase
|
- update duty cycle spreadsheet for our typical usecase
|
||||||
- generalize naive flooding on top of radiohead or disaster.radio? (and fix radiohead to use my new driver)
|
|
||||||
|
|
||||||
a description of DSR: https://tools.ietf.org/html/rfc4728 good slides here: https://www.slideshare.net/ashrafmath/dynamic-source-routing
|
a description of DSR: https://tools.ietf.org/html/rfc4728 good slides here: https://www.slideshare.net/ashrafmath/dynamic-source-routing
|
||||||
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
||||||
@@ -77,7 +151,6 @@ look into the literature for this idea specifically.
|
|||||||
|
|
||||||
FIXME, merge into the above:
|
FIXME, merge into the above:
|
||||||
|
|
||||||
|
|
||||||
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
||||||
|
|
||||||
interesting paper on lora mesh: https://portal.research.lu.se/portal/files/45735775/paper.pdf
|
interesting paper on lora mesh: https://portal.research.lu.se/portal/files/45735775/paper.pdf
|
||||||
|
|||||||
@@ -1,51 +1,130 @@
|
|||||||
# NRF52 TODO
|
# NRF52 TODO
|
||||||
|
|
||||||
|
## RAK815
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- i2c gps comms not quite right
|
||||||
|
- ble: AdafruitBluefruit::begin - adafruit_ble_task was assigned an invalid stack pointer. out of memory?
|
||||||
|
- measure power draw
|
||||||
|
|
||||||
|
### Bootloader
|
||||||
|
|
||||||
|
Install our (temporarily hacked up) adafruit bootloader
|
||||||
|
|
||||||
|
```
|
||||||
|
kevinh@kevin-server:~/development/meshtastic/Adafruit_nRF52_Bootloader$ make BOARD=rak815 sd flash
|
||||||
|
LD rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||||
|
text data bss dec hex filename
|
||||||
|
20888 1124 15006 37018 909a _build/build-rak815/rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||||
|
Create rak815_bootloader-0.3.2-111-g9478eb7-dirty.hex
|
||||||
|
Create rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex
|
||||||
|
Flashing: rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex
|
||||||
|
nrfjprog --program _build/build-rak815/rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex --sectoranduicrerase -f nrf52 --reset
|
||||||
|
Parsing hex file.
|
||||||
|
Erasing page at address 0x0.
|
||||||
|
Erasing page at address 0x74000.
|
||||||
|
Erasing page at address 0x75000.
|
||||||
|
Erasing page at address 0x76000.
|
||||||
|
Erasing page at address 0x77000.
|
||||||
|
Erasing page at address 0x78000.
|
||||||
|
Erasing page at address 0x79000.
|
||||||
|
Erasing UICR flash area.
|
||||||
|
Applying system reset.
|
||||||
|
Checking that the area to write is not protected.
|
||||||
|
Programming device.
|
||||||
|
Applying system reset.
|
||||||
|
Run.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Appload
|
||||||
|
|
||||||
|
tips on installing https://github.com/platformio/platform-nordicnrf52/issues/8#issuecomment-374017768
|
||||||
|
|
||||||
|
to see console output over jlink:
|
||||||
|
|
||||||
|
```
|
||||||
|
12:17
|
||||||
|
in one tab run "bin/nrf52832-gdbserver.sh" - leave this running the whole time while developing/debugging
|
||||||
|
12:17
|
||||||
|
~/development/meshtastic/meshtastic-esp32$ bin/nrf52-console.sh
|
||||||
|
###RTT Client: ************************************************************
|
||||||
|
###RTT Client: * SEGGER Microcontroller GmbH *
|
||||||
|
###RTT Client: * Solutions for real time microcontroller applications *
|
||||||
|
###RTT Client: ************************************************************
|
||||||
|
###RTT Client: * *
|
||||||
|
###RTT Client: * (c) 2012 - 2016 SEGGER Microcontroller GmbH *
|
||||||
|
###RTT Client: * *
|
||||||
|
###RTT Client: * www.segger.com Support: support@segger.com *
|
||||||
|
###RTT Client: * *
|
||||||
|
###RTT Client: ************************************************************
|
||||||
|
###RTT Client: * *
|
||||||
|
###RTT Client: * SEGGER J-Link RTT Client Compiled Apr 7 2020 15:01:22 *
|
||||||
|
###RTT Client: * *
|
||||||
|
###RTT Client: ************************************************************
|
||||||
|
###RTT Client: -----------------------------------------------
|
||||||
|
###RTT Client: Connecting to J-Link RTT Server via localhost:19021 ..............
|
||||||
|
###RTT Client: Connected.
|
||||||
|
SEGGER J-Link V6.70c - Real time terminal output
|
||||||
|
SEGGER J-Link ARM V9.6, SN=69663845
|
||||||
|
Process: JLinkGDBServerCLExein another tab run:
|
||||||
|
12:18
|
||||||
|
On NRF52 I've been using the jlink fake serial console. But since the rak815 has the serial port hooked up we can switch back to that once the basics are working.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Misc work items
|
||||||
|
|
||||||
|
RAM investigation.
|
||||||
|
nRF52832-QFAA 64KB ram, 512KB flash vs
|
||||||
|
nrf52832-QFAB 32KB ram, 512kb flash
|
||||||
|
nrf52833 128KB RAM
|
||||||
|
nrf52840 256KB RAM, 1MB flash
|
||||||
|
|
||||||
|
Manual hacks needed to build (for now):
|
||||||
|
|
||||||
|
kevinh@kevin-server:~/.platformio/packages/framework-arduinoadafruitnrf52/variants\$ ln -s ~/development/meshtastic/meshtastic-esp32/variants/\* .
|
||||||
|
|
||||||
## Initial work items
|
## Initial work items
|
||||||
|
|
||||||
Minimum items needed to make sure hardware is good.
|
Minimum items needed to make sure hardware is good.
|
||||||
|
|
||||||
- add a hard fault handler
|
- DONE set power UICR per https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration
|
||||||
- use "variants" to get all gpio bindings
|
- switch charge controller into / out of performance mode (see 8.3.1 in datasheet)
|
||||||
- plug in correct variants for the real board
|
- write UC1701 wrapper
|
||||||
|
- Test hardfault handler for null ptrs (if one isn't already installed)
|
||||||
|
- test my hackedup bootloader on the real hardware
|
||||||
- Use the PMU driver on real hardware
|
- Use the PMU driver on real hardware
|
||||||
- add a NEMA based GPS driver to test GPS
|
- Use new radio driver on real hardware
|
||||||
- Use new radio driver on real hardware - possibly start with https://os.mbed.com/teams/Semtech/code/SX126xLib/
|
- Use UC1701 LCD driver on real hardware. Still need to create at startup and probe on SPI. Make sure SPI is atomic.
|
||||||
- Use UC1701 LCD driver on real hardware. Still need to create at startup and probe on SPI
|
- set vbus voltage per https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html?cp=4_0_0_4_2
|
||||||
- test the LEDs
|
- test the LEDs
|
||||||
- test the buttons
|
- test the buttons
|
||||||
- make a new boarddef with a variant.h file. Fix pins in that file. In particular (at least):
|
|
||||||
#define PIN_SPI_MISO (46)
|
|
||||||
#define PIN_SPI_MOSI (45)
|
|
||||||
#define PIN_SPI_SCK (47)
|
|
||||||
#define PIN_WIRE_SDA (26)
|
|
||||||
#define PIN_WIRE_SCL (27)
|
|
||||||
|
|
||||||
## Secondary work items
|
## Secondary work items
|
||||||
|
|
||||||
Needed to be fully functional at least at the same level of the ESP32 boards. At this point users would probably want them.
|
Needed to be fully functional at least at the same level of the ESP32 boards. At this point users would probably want them.
|
||||||
|
|
||||||
- increase preamble length? - will break other clients? so all devices must update
|
- DONE get serial API working
|
||||||
- enable BLE DFU somehow
|
|
||||||
- set appversion/hwversion
|
|
||||||
- report appversion/hwversion in BLE
|
|
||||||
- use new LCD driver from screen.cpp. Still need to hook it to a subclass of (poorly named) OLEDDisplay, and override display() to stream bytes out to the screen.
|
|
||||||
- get full BLE api working
|
- get full BLE api working
|
||||||
- we need to enable the external xtal for the sx1262 (on dio3)
|
|
||||||
- figure out which regulator mode the sx1262 is operating in
|
|
||||||
- turn on security for BLE, make pairing work
|
|
||||||
- make power management/sleep work properly
|
- make power management/sleep work properly
|
||||||
- make a settimeofday implementation
|
- make a settimeofday implementation
|
||||||
- make a file system implementation (preferably one that can see the files the bootloader also sees) - use https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/lib_fds_usage.html?cp=7_5_0_3_55_3
|
- DONE increase preamble length? - will break other clients? so all devices must update
|
||||||
|
- DONE enable BLE DFU somehow
|
||||||
|
- report appversion/hwversion in BLE
|
||||||
|
- use new LCD driver from screen.cpp. Still need to hook it to a subclass of (poorly named) OLEDDisplay, and override display() to stream bytes out to the screen.
|
||||||
|
- we need to enable the external tcxo for the sx1262 (on dio3)?
|
||||||
|
- figure out which regulator mode the sx1262 is operating in
|
||||||
|
- turn on security for BLE, make pairing work
|
||||||
- make ble endpoints not require "start config", just have them start in config mode
|
- make ble endpoints not require "start config", just have them start in config mode
|
||||||
- measure power management and confirm battery life
|
|
||||||
- use new PMU to provide battery voltage/% full to app (both bluetooth and screen)
|
- use new PMU to provide battery voltage/% full to app (both bluetooth and screen)
|
||||||
- do initial power measurements
|
- do initial power measurements, measure effects of more preamble bits, measure power management and confirm battery life
|
||||||
|
- set UICR.CUSTOMER to indicate board model & version
|
||||||
|
|
||||||
## Items to be 'feature complete'
|
## Items to be 'feature complete'
|
||||||
|
|
||||||
- use SX126x::startReceiveDutyCycleAuto to save power by sleeping and briefly waking to check for preamble bits. Change xmit rules to have more preamble bits.
|
- check datasheet about sx1262 temperature compensation
|
||||||
- turn back on in-radio destaddr checking for RF95
|
- enable brownout detection and watchdog
|
||||||
- remove the MeshRadio wrapper - we don't need it anymore, just do everythin in RadioInterface subclasses.
|
- stop polling for GPS characters, instead stay blocked on read in a thread
|
||||||
- figure out what the correct current limit should be for the sx1262, currently we just use the default 100
|
- figure out what the correct current limit should be for the sx1262, currently we just use the default 100
|
||||||
- put sx1262 in sleepmode when processor gets shutdown (or rebooted), ideally even for critical faults (to keep power draw low). repurpose deepsleep state for this.
|
- put sx1262 in sleepmode when processor gets shutdown (or rebooted), ideally even for critical faults (to keep power draw low). repurpose deepsleep state for this.
|
||||||
- good power management tips: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-power-on-nrf52-designs
|
- good power management tips: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-power-on-nrf52-designs
|
||||||
@@ -55,13 +134,19 @@ Needed to be fully functional at least at the same level of the ESP32 boards. At
|
|||||||
- use the new buttons in the UX
|
- use the new buttons in the UX
|
||||||
- currently using soft device SD140, is that ideal?
|
- currently using soft device SD140, is that ideal?
|
||||||
- turn on the watchdog timer, require servicing from key application threads
|
- turn on the watchdog timer, require servicing from key application threads
|
||||||
- install a hardfault handler for null ptrs (if one isn't already installed)
|
|
||||||
- nrf52setup should call randomSeed(tbd)
|
- nrf52setup should call randomSeed(tbd)
|
||||||
|
- implement SYSTEMOFF behavior per https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html?cp=4_0_0_4_2
|
||||||
|
|
||||||
## Things to do 'someday'
|
## Things to do 'someday'
|
||||||
|
|
||||||
Nice ideas worth considering someday...
|
Nice ideas worth considering someday...
|
||||||
|
|
||||||
|
- enable monitor mode debugging (need to use real jlink): https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
|
||||||
|
- Improve efficiency of PeriodicTimer by only checking the next queued timer event, and carefully sorting based on schedule
|
||||||
|
- make a Mfg Controller and device under test classes as examples of custom app code for third party devs. Make a post about this. Use a custom payload type code. Have device under test send a broadcast with max hopcount of 0 for the 'mfgcontroller' payload type. mfg controller will read SNR and reply. DOT will declare failure/success and switch to the regular app screen.
|
||||||
|
- Hook Segger RTT to the nordic logging framework. https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/debugging-with-real-time-terminal
|
||||||
|
- Use nordic logging for DEBUG_MSG
|
||||||
|
- use the Jumper simulator to run meshes of simulated hardware: https://docs.jumper.io/docs/install.html
|
||||||
- make/find a multithread safe debug logging class (include remote logging and timestamps and levels). make each log event atomic.
|
- make/find a multithread safe debug logging class (include remote logging and timestamps and levels). make each log event atomic.
|
||||||
- turn on freertos stack size checking
|
- turn on freertos stack size checking
|
||||||
- Currently we use Nordic's vendor ID, which is apparently okay: https://devzone.nordicsemi.com/f/nordic-q-a/44014/using-nordic-vid-and-pid-for-nrf52840 and I just picked a PID of 0x4403
|
- Currently we use Nordic's vendor ID, which is apparently okay: https://devzone.nordicsemi.com/f/nordic-q-a/44014/using-nordic-vid-and-pid-for-nrf52840 and I just picked a PID of 0x4403
|
||||||
@@ -71,11 +156,15 @@ Nice ideas worth considering someday...
|
|||||||
- in addition to the main CPU watchdog, use the PMU watchdog as a really big emergency hammer
|
- in addition to the main CPU watchdog, use the PMU watchdog as a really big emergency hammer
|
||||||
- turn on 'shipping mode' in the PMU when device is 'off' - to cut battery draw to essentially zero
|
- turn on 'shipping mode' in the PMU when device is 'off' - to cut battery draw to essentially zero
|
||||||
- make Lorro_BQ25703A read/write operations atomic, current version could let other threads sneak in (once we start using threads)
|
- make Lorro_BQ25703A read/write operations atomic, current version could let other threads sneak in (once we start using threads)
|
||||||
- turn on DFU assistance in the appload using the nordic DFU helper lib call
|
|
||||||
- make the segger logbuffer larger, move it to RAM that is preserved across reboots and support reading it out at runtime (to allow full log messages to be included in crash reports). Share this code with ESP32 (use gcc noinit attribute)
|
- make the segger logbuffer larger, move it to RAM that is preserved across reboots and support reading it out at runtime (to allow full log messages to be included in crash reports). Share this code with ESP32 (use gcc noinit attribute)
|
||||||
- convert hardfaults/panics/asserts/wd exceptions into fault codes sent to phone
|
- convert hardfaults/panics/asserts/wd exceptions into fault codes sent to phone
|
||||||
- stop enumerating all i2c devices at boot, it wastes power & time
|
- stop enumerating all i2c devices at boot, it wastes power & time
|
||||||
- consider using "SYSTEMOFF" deep sleep mode, without RAM retension. Only useful for 'truly off - wake only by button press' only saves 1.5uA vs SYSTEMON. (SYSTEMON only costs 1.5uA). Possibly put PMU into shipping mode?
|
- consider using "SYSTEMOFF" deep sleep mode, without RAM retension. Only useful for 'truly off - wake only by button press' only saves 1.5uA vs SYSTEMON. (SYSTEMON only costs 1.5uA). Possibly put PMU into shipping mode?
|
||||||
|
- change the BLE protocol to be more symmetric. Have the phone _also_ host a GATT service which receives writes to
|
||||||
|
'fromradio'. This would allow removing the 'fromnum' mailbox/notify scheme of the current approach and decrease the number of packet handoffs when a packet is received.
|
||||||
|
- Using the preceeding, make a generalized 'nrf52/esp32 ble to internet' bridge service. To let nrf52 apps do MQTT/UDP/HTTP POST/HTTP GET operations to web services.
|
||||||
|
- lower advertise interval to save power, lower ble transmit power to save power
|
||||||
|
- the SX126x class does SPI transfers on a byte by byte basis, which is very ineffecient. Much better to do block writes/reads.
|
||||||
|
|
||||||
## Old unorganized notes
|
## Old unorganized notes
|
||||||
|
|
||||||
@@ -86,6 +175,8 @@ Nice ideas worth considering someday...
|
|||||||
- Currently using Nordic PCA10059 Dongle hardware
|
- Currently using Nordic PCA10059 Dongle hardware
|
||||||
- https://community.platformio.org/t/same-bootloader-same-softdevice-different-board-different-pins/11411/9
|
- https://community.platformio.org/t/same-bootloader-same-softdevice-different-board-different-pins/11411/9
|
||||||
|
|
||||||
|
- To make Segger JLink more reliable, turn off its fake filesystem. "JLinkExe MSDDisable" per https://learn.adafruit.com/circuitpython-on-the-nrf52/nrf52840-bootloader
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
- DONE add "DFU trigger library" to application load
|
- DONE add "DFU trigger library" to application load
|
||||||
@@ -100,6 +191,23 @@ Nice ideas worth considering someday...
|
|||||||
- DONE neg 7 error code from receive
|
- DONE neg 7 error code from receive
|
||||||
- DONE remove unused sx1262 lib from github
|
- DONE remove unused sx1262 lib from github
|
||||||
- at boot we are starting our message IDs at 1, rather we should start them at a random number. also, seed random based on timer. this could be the cause of our first message not seen bug.
|
- at boot we are starting our message IDs at 1, rather we should start them at a random number. also, seed random based on timer. this could be the cause of our first message not seen bug.
|
||||||
|
- add a NEMA based GPS driver to test GPS
|
||||||
|
- DONE use "variants" to get all gpio bindings
|
||||||
|
- DONE plug in correct variants for the real board
|
||||||
|
- turn on DFU assistance in the appload using the nordic DFU helper lib call
|
||||||
|
- make a new boarddef with a variant.h file. Fix pins in that file. In particular (at least):
|
||||||
|
#define PIN_SPI_MISO (46)
|
||||||
|
#define PIN_SPI_MOSI (45)
|
||||||
|
#define PIN_SPI_SCK (47)
|
||||||
|
#define PIN_WIRE_SDA (26)
|
||||||
|
#define PIN_WIRE_SCL (27)
|
||||||
|
- customize the bootloader to use proper button bindings
|
||||||
|
- remove the MeshRadio wrapper - we don't need it anymore, just do everything in RadioInterface subclasses.
|
||||||
|
- DONE use SX126x::startReceiveDutyCycleAuto to save power by sleeping and briefly waking to check for preamble bits. Change xmit rules to have more preamble bits.
|
||||||
|
- scheduleOSCallback doesn't work yet - it is way too fast (causes rapid polling of busyTx, high power draw etc...)
|
||||||
|
- find out why we reboot while debugging - it was bluetooth/softdevice
|
||||||
|
- make a file system implementation (preferably one that can see the files the bootloader also sees) - preferably https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/libraries/InternalFileSytem/examples/Internal_ReadWrite/Internal_ReadWrite.ino else use https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/lib_fds_usage.html?cp=7_5_0_3_55_3
|
||||||
|
- change packet numbers to be 32 bits
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
27
docs/software/pinetab.md
Normal file
27
docs/software/pinetab.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Pinetab
|
||||||
|
|
||||||
|
These are **preliminary** notes on support for Meshtastic in the Pinetab.
|
||||||
|
|
||||||
|
A RF95 is connected via a CS341 USB-SPI chip.
|
||||||
|
|
||||||
|
Pin assignments:
|
||||||
|
CS0 from RF95 goes to CS0 on CS341
|
||||||
|
DIO0 from RF95 goes to INT on CS341
|
||||||
|
RST from RF95 goes to RST on CS341
|
||||||
|
|
||||||
|
This linux driver claims to provide USB-SPI support: https://github.com/gschorcht/spi-ch341-usb
|
||||||
|
Notes here on using that driver: https://www.linuxquestions.org/questions/linux-hardware-18/ch341-usb-to-spi-adaptor-driver-doesn%27t-work-4175622736/
|
||||||
|
|
||||||
|
Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/02/16/wch-ch341-usb-to-serial-chip-gets-linux-driver-to-control-gpios-over-usb/
|
||||||
|
|
||||||
|
## Task list
|
||||||
|
|
||||||
|
* Port meshtastic to build (under platformio) for a poxix target. spec: no screen, no gpios, sim network interface, posix threads, posix semaphores & queues, IO to the console only
|
||||||
|
Use ARM linux: https://platformio.org/platforms/linux_arm
|
||||||
|
And linux native: https://platformio.org/platforms/native
|
||||||
|
|
||||||
|
* Test cs341 driver - just test reading/writing a register and detecting interrupts, confirm can see rf95
|
||||||
|
* Make a radiolib spi module that targets the cs341 (and builds on linux)
|
||||||
|
* use new radiolib module to hook pinebook lora to meshtastic, confirm mesh discovery works
|
||||||
|
* Make a subclass of StreamAPI that works as a posix TCP server
|
||||||
|
* Use new TCP endpoint from meshtastic-python
|
||||||
@@ -36,6 +36,10 @@ From lower to higher power consumption.
|
|||||||
onEntry: setBluetoothOn(true), screen.setOn(true)
|
onEntry: setBluetoothOn(true), screen.setOn(true)
|
||||||
onExit: screen.setOn(false)
|
onExit: screen.setOn(false)
|
||||||
|
|
||||||
|
- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off
|
||||||
|
onEntry: setBluetooth off, screen on
|
||||||
|
onExit:
|
||||||
|
|
||||||
## Behavior
|
## Behavior
|
||||||
|
|
||||||
### events that increase CPU activity
|
### events that increase CPU activity
|
||||||
@@ -51,9 +55,11 @@ From lower to higher power consumption.
|
|||||||
- While in DARK/ON: If we receive EVENT_BLUETOOTH_PAIR we transition to ON and start our screen_on_secs timeout
|
- While in DARK/ON: If we receive EVENT_BLUETOOTH_PAIR we transition to ON and start our screen_on_secs timeout
|
||||||
- While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown)
|
- While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown)
|
||||||
- While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts)
|
- While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts)
|
||||||
|
- while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial
|
||||||
|
|
||||||
### events that decrease cpu activity
|
### events that decrease cpu activity
|
||||||
|
|
||||||
|
- While in SERIAL: if SERIAL_DISCONNECTED, go to NB
|
||||||
- While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess
|
- While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess
|
||||||
- While in ON: If it has been more than screen_on_secs since a press, lower to DARK
|
- While in ON: If it has been more than screen_on_secs since a press, lower to DARK
|
||||||
- While in DARK: If time since last contact by our phone exceeds phone_timeout_secs (15 minutes), we transition down into NB mode
|
- While in DARK: If time since last contact by our phone exceeds phone_timeout_secs (15 minutes), we transition down into NB mode
|
||||||
|
|||||||
6
docs/software/rak815.md
Normal file
6
docs/software/rak815.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# RAK815
|
||||||
|
|
||||||
|
Notes on trying to get the RAK815 working with meshtastic.
|
||||||
|
|
||||||
|
good tutorial: https://www.hackster.io/naresh-krish/getting-started-with-rak815-tracker-module-and-arduino-1c7bc9
|
||||||
|
(includes software serial link - possibly useful for GPS)
|
||||||
202
docs/software/ramusage-nrf52.txt
Normal file
202
docs/software/ramusage-nrf52.txt
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
23K + messages
|
||||||
|
+ heap of 70ish packets, 300ish bytes per packet: 20KB
|
||||||
|
+ 14KB soft device RAM
|
||||||
|
|
||||||
|
With max length Data inside the packet
|
||||||
|
Size of NodeInfo 104
|
||||||
|
Size of SubPacket 272
|
||||||
|
Size of MeshPacket 304
|
||||||
|
|
||||||
|
If Data was smaller: for 70 data packets we would save 7KB. We would need to make SubPacket.data and MeshPacket.encrypted into "type:FT_POINTER" - variably sized mallocs
|
||||||
|
Size of NodeInfo 104
|
||||||
|
Size of SubPacket 96
|
||||||
|
Size of MeshPacket 292 (could have been much smaller but I forgot to shrink MeshPacket.encrypted)
|
||||||
|
|
||||||
|
therefore:
|
||||||
|
a) we should store all ToPhone message queued messages compressed as protobufs (since they will become that anyways)
|
||||||
|
b) shrink packet pool size because none of that storage will be used for ToPhone packets
|
||||||
|
c) don't allocate any storage in RAM for the tophone messages we save inside device state, instead just use nanopb callbacks to save/load those
|
||||||
|
d) a smarter MeshPacket in memory representation would save about 7KB of RAM. call pb_release before freeing each freshly malloced MeshPacket
|
||||||
|
|
||||||
|
- nrf52 free memory https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/hathach-memory-map
|
||||||
|
|
||||||
|
2000790c 00003558 B devicestate // 16KB
|
||||||
|
2000b53c 00001000 b _cache_buffer // 4KB flash filesystem support
|
||||||
|
20003b1c 000006b0 B console
|
||||||
|
2000d5f4 00000400 b vApplicationGetTimerTaskMemory::uxTimerTaskStack
|
||||||
|
2000da04 00000400 b _acUpBuffer
|
||||||
|
2000c558 0000036c B Bluefruit
|
||||||
|
2000c8d8 00000358 b _cdcd_itf
|
||||||
|
2000e54c 00000258 B _midid_itf
|
||||||
|
2000d0dc 00000200 b ucStaticTimerQueueStorage.9390
|
||||||
|
2000e044 00000200 b _mscd_buf
|
||||||
|
2000e284 000001cc b _vendord_itf
|
||||||
|
2000d410 00000190 b vApplicationGetIdleTaskMemory::uxIdleTaskStack
|
||||||
|
2000374c 0000016c D __global_locale
|
||||||
|
2000de48 0000012c B USBDevice
|
||||||
|
2000afa4 00000100 b Router::send(_MeshPacket*)::bytes
|
||||||
|
2000aea4 00000100 b Router::perhapsDecode(_MeshPacket*)::bytes
|
||||||
|
200039b0 000000f4 B powerFSM
|
||||||
|
20004258 000000f0 B screen
|
||||||
|
2000cd7c 000000c4 b _dcd
|
||||||
|
2000cc68 000000c0 b _usbd_qdef_buf
|
||||||
|
2000b3c4 000000bc B Wire
|
||||||
|
2000cef4 000000a8 B Serial2
|
||||||
|
2000ce4c 000000a8 B Serial1
|
||||||
|
2000e498 000000a8 B _SEGGER_RTT
|
||||||
|
2000b498 000000a4 B InternalFS
|
||||||
|
2000dfb8 0000008c b _hidd_itf
|
||||||
|
2000b260 00000088 b meshtastic::normalFrames
|
||||||
|
2000cfdc 00000064 b pxReadyTasksLists
|
||||||
|
2000b340 00000060 b meshtastic::drawTextMessageFrame(OLEDDisplay*, OLEDDisplayUiState*, short, short)::tempBuf
|
||||||
|
200036ec 00000060 d impure_data
|
||||||
|
2000b104 00000060 B bledfu
|
||||||
|
2000b0a4 00000060 B blebas
|
||||||
|
20003684 00000058 D _usbd_qdef
|
||||||
|
200038c0 00000058 d tzinfo
|
||||||
|
2000d5a0 00000054 b vApplicationGetTimerTaskMemory::xTimerTaskTCB
|
||||||
|
2000d3bc 00000054 b vApplicationGetIdleTaskMemory::xIdleTaskTCB
|
||||||
|
2000d308 00000050 b xStaticTimerQueue.9389
|
||||||
|
2000b1f4 00000050 B hrmc
|
||||||
|
2000b1a4 00000050 B bslc
|
||||||
|
20004360 0000004c B service
|
||||||
|
2000d374 00000048 b m_cb
|
||||||
|
2000df74 00000042 b _desc_str
|
||||||
|
2000cd3c 00000040 b _usbd_ctrl_buf
|
||||||
|
20004214 00000040 B realRouter
|
||||||
|
2000e244 00000040 b _mscd_itf
|
||||||
|
2000b164 00000040 B bledis
|
||||||
|
20003634 00000038 d _InternalFSConfig
|
||||||
|
2000cc30 00000031 b _usbd_dev
|
||||||
|
2000398c 00000020 B periodicScheduler
|
||||||
|
2000cfa4 00000020 b callbacksInt
|
||||||
|
2000de10 0000001f b fw_str.13525
|
||||||
|
20003974 00000018 b object.9934
|
||||||
|
2000ae68 00000018 B nodeDB
|
||||||
|
2000366c 00000018 d _cache
|
||||||
|
2000b314 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::signalStr
|
||||||
|
2000b300 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::lastStr
|
||||||
|
2000b2ec 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::distStr
|
||||||
|
200041e0 00000014 b getDeviceName()::name
|
||||||
|
2000d0b8 00000014 b xTasksWaitingTermination
|
||||||
|
2000d0a4 00000014 b xSuspendedTaskList
|
||||||
|
2000d08c 00000014 b xPendingReadyList
|
||||||
|
2000d06c 00000014 b xDelayedTaskList2
|
||||||
|
2000d058 00000014 b xDelayedTaskList1
|
||||||
|
2000d2f0 00000014 b xActiveTimerList2
|
||||||
|
2000d2dc 00000014 b xActiveTimerList1
|
||||||
|
2000b480 00000014 B SPI
|
||||||
|
2000c8c4 00000014 B Serial
|
||||||
|
2000cd28 00000014 b _ctrl_xfer
|
||||||
|
2000de30 00000011 b serial_str.13534
|
||||||
|
2000c544 00000010 b BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
|
||||||
|
20003614 00000010 d meshtastic::btPIN
|
||||||
|
2000434c 00000010 b sendOwnerPeriod
|
||||||
|
2000ae8c 00000010 b staticPool
|
||||||
|
2000e484 00000010 B xQueueRegistry
|
||||||
|
20003b04 00000010 B stateSERIAL
|
||||||
|
20003af4 00000010 B stateSDS
|
||||||
|
20003ae4 00000010 B stateON
|
||||||
|
20003ad4 00000010 B stateNB
|
||||||
|
20003ac4 00000010 B stateLS
|
||||||
|
20003ab4 00000010 B stateDARK
|
||||||
|
20003aa4 00000010 B stateBOOT
|
||||||
|
200041f8 00000010 B ledPeriodic
|
||||||
|
2000b244 00000010 B hrms
|
||||||
|
2000d9f4 00000010 b _acDownBuffer
|
||||||
|
2000b3b8 0000000c B preflightSleep
|
||||||
|
20004208 0000000c B powerStatus
|
||||||
|
2000e540 0000000c B nrf_nvic_state
|
||||||
|
2000b3ac 0000000c B notifySleep
|
||||||
|
2000b3a0 0000000c B notifyDeepSleep
|
||||||
|
2000e463 0000000b b __tzname_std
|
||||||
|
2000e458 0000000b b __tzname_dst
|
||||||
|
2000b338 00000008 b meshtastic::estimatedHeading(double, double)::oldLon
|
||||||
|
2000b330 00000008 b meshtastic::estimatedHeading(double, double)::oldLat
|
||||||
|
200041d0 00000008 b zeroOffsetSecs
|
||||||
|
2000ae80 00000008 b spiSettings
|
||||||
|
200038b8 00000008 D _tzname
|
||||||
|
20003b14 00000008 B noopPrint
|
||||||
|
2000cfc4 00000008 b channelMap
|
||||||
|
2000cf9c 00000008 b callbackDeferred
|
||||||
|
200043ac 00000006 b ourMacAddr
|
||||||
|
2000435c 00000004 b MeshService::onGPSChanged(void*)::lastGpsSend
|
||||||
|
2000b32c 00000004 b meshtastic::estimatedHeading(double, double)::b
|
||||||
|
2000b328 00000004 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::simRadian
|
||||||
|
2000362c 00000004 d meshtastic::Screen::setup()::bootFrames
|
||||||
|
20003628 00000004 d meshtastic::Screen::handleStartBluetoothPinScreen(unsigned long)::btFrames
|
||||||
|
200039ac 00000004 b onEnter()::lastPingMs
|
||||||
|
2000ae9c 00000004 b generatePacketId()::i
|
||||||
|
2000ae88 00000004 B RadioLibInterface::instance
|
||||||
|
2000b2e8 00000004 b meshtastic::nodeIndex
|
||||||
|
20003610 00000004 d meshtastic::targetFramerate
|
||||||
|
2000c554 00000004 B BLEService::lastService
|
||||||
|
200041cc 00000004 b timeStartMsec
|
||||||
|
200036dc 00000004 d sbrk_heap_top
|
||||||
|
2000d364 00000004 b _loopHandle
|
||||||
|
2000c540 00000004 b guard variable for BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
|
||||||
|
2000d0d0 00000004 b xYieldPending
|
||||||
|
2000d35c 00000004 b xTimerTaskHandle
|
||||||
|
2000d358 00000004 b xTimerQueue
|
||||||
|
2000d0cc 00000004 b xTickCount
|
||||||
|
2000d0a0 00000004 b xSchedulerRunning
|
||||||
|
2000d088 00000004 b xNumOfOverflows
|
||||||
|
2000d084 00000004 b xNextTaskUnblockTime
|
||||||
|
2000d304 00000004 b xLastTime.9343
|
||||||
|
2000d080 00000004 b xIdleTaskHandle
|
||||||
|
2000d054 00000004 b uxTopReadyPriority
|
||||||
|
2000d050 00000004 b uxTaskNumber
|
||||||
|
2000d04c 00000004 b uxSchedulerSuspended
|
||||||
|
2000d048 00000004 b uxPendedTicks
|
||||||
|
2000d044 00000004 b uxDeletedTasksWaitingCleanUp
|
||||||
|
2000d040 00000004 b uxCurrentNumberOfTasks
|
||||||
|
2000d360 00000004 b uxCriticalNesting
|
||||||
|
2000cc64 00000004 b _usbd_q
|
||||||
|
2000e478 00000004 B _timezone
|
||||||
|
200036e0 00000004 D SystemCoreClock
|
||||||
|
2000c53c 00000004 b _sem
|
||||||
|
2000d0d8 00000004 b pxOverflowTimerList
|
||||||
|
2000cfd8 00000004 b pxOverflowDelayedTaskList
|
||||||
|
2000cfd4 00000004 b pxDelayedTaskList
|
||||||
|
2000d0d4 00000004 b pxCurrentTimerList
|
||||||
|
2000cfd0 00000004 B pxCurrentTCB
|
||||||
|
2000e470 00000004 b prev_tzenv
|
||||||
|
2000360c 00000004 D preftmp
|
||||||
|
20003608 00000004 D preffile
|
||||||
|
2000b25c 00000004 B nrf52Bluetooth
|
||||||
|
2000d370 00000004 b m_usbevt_handler
|
||||||
|
2000d36c 00000004 b m_sleepevt_handler
|
||||||
|
2000d368 00000004 b m_pofwarn_handler
|
||||||
|
2000e454 00000004 B __malloc_sbrk_start
|
||||||
|
2000e450 00000004 B __malloc_free_list
|
||||||
|
2000e480 00000004 B MAIN_MonCnt
|
||||||
|
2000e47c 00000004 b initial_env
|
||||||
|
200036e8 00000004 D _impure_ptr
|
||||||
|
200041d8 00000004 B gps
|
||||||
|
2000e7a4 00000004 B errno
|
||||||
|
20003918 00000004 D environ
|
||||||
|
2000cfcc 00000004 b enabled
|
||||||
|
2000ae64 00000004 B displayedNodeNum
|
||||||
|
2000e474 00000004 B _daylight
|
||||||
|
2000b254 00000004 B crypto
|
||||||
|
2000ce44 00000004 B count_duration
|
||||||
|
2000de0c 00000004 b _cb_task
|
||||||
|
2000de08 00000004 b _cb_queue
|
||||||
|
2000de04 00000004 b _cb_qdepth
|
||||||
|
2000de44 00000004 B bootloaderVersion
|
||||||
|
200041f5 00000001 b ledBlinker()::ledOn
|
||||||
|
20003604 00000001 d loop::showingBootScreen
|
||||||
|
200041f4 00000001 b loop::wasPressed
|
||||||
|
2000b494 00000001 b DefaultFontTableLookup(unsigned char)::LASTCHAR
|
||||||
|
2000aea0 00000001 b generatePacketId()::didInit
|
||||||
|
20003624 00000001 d meshtastic::prevFrame
|
||||||
|
2000b258 00000001 b bleOn
|
||||||
|
200041dc 00000001 B timeSetFromGPS
|
||||||
|
20004348 00000001 B ssd1306_found
|
||||||
|
2000ce49 00000001 B pin_sound
|
||||||
|
2000e494 00000001 B nrfx_power_irq_enabled
|
||||||
|
2000ce48 00000001 B no_stop
|
||||||
|
20003630 00000001 D neo6M
|
||||||
|
2000ce40 00000001 b _initialized
|
||||||
|
200036e4 00000001 D __fdlib_version
|
||||||
|
20003970 00000001 b completed.9929
|
||||||
13
gdbinit
13
gdbinit
@@ -1,6 +1,19 @@
|
|||||||
|
|
||||||
|
# Setup Monitor Mode Debugging
|
||||||
|
# Per .platformio/packages/framework-arduinoadafruitnrf52-old/cores/nRF5/linker/nrf52840_s140_v6.ld
|
||||||
|
# our appload starts at 0x26000
|
||||||
|
# Disable for now because our version on board doesn't support monitor mode debugging
|
||||||
|
# mon exec SetMonModeDebug=1
|
||||||
|
# mon exec SetMonModeVTableAddr=0x26000
|
||||||
|
|
||||||
|
# echo setting RTTAddr
|
||||||
|
# eval "monitor exec SetRTTAddr %p", &_SEGGER_RTT
|
||||||
|
|
||||||
# the jlink debugger seems to want a pause after reset before we tell it to start running
|
# the jlink debugger seems to want a pause after reset before we tell it to start running
|
||||||
define restart
|
define restart
|
||||||
|
echo Restarting
|
||||||
monitor reset
|
monitor reset
|
||||||
shell sleep 1
|
shell sleep 1
|
||||||
cont
|
cont
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
|
|
||||||
#include "BLECharacteristic.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This mixin just lets the power management state machine know the phone is still talking to us
|
|
||||||
*/
|
|
||||||
class BLEKeepAliveCallbacks : public BLECharacteristicCallbacks
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void onRead(BLECharacteristic *c)
|
|
||||||
{
|
|
||||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onWrite(BLECharacteristic *c)
|
|
||||||
{
|
|
||||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A characterstic with a set of overridable callbacks
|
|
||||||
*/
|
|
||||||
class CallbackCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CallbackCharacteristic(const char *uuid, uint32_t btprops)
|
|
||||||
: BLECharacteristic(uuid, btprops)
|
|
||||||
{
|
|
||||||
setCallbacks(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
/* Enable support for dynamically allocated fields */
|
/* Enable support for dynamically allocated fields */
|
||||||
/* #define PB_ENABLE_MALLOC 1 */
|
#define PB_ENABLE_MALLOC 1
|
||||||
|
|
||||||
/* Define this if your CPU / compiler combination does not support
|
/* Define this if your CPU / compiler combination does not support
|
||||||
* unaligned memory access to packed structures. */
|
* unaligned memory access to packed structures. */
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
Important - Read carefully:
|
|
||||||
|
|
||||||
SEGGER RTT - Real Time Transfer for embedded targets
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
SEGGER strongly recommends to not make any changes
|
|
||||||
to or modify the source code of this software in order to stay
|
|
||||||
compatible with the RTT protocol and J-Link.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or
|
|
||||||
without modification, are permitted provided that the following
|
|
||||||
condition is met:
|
|
||||||
|
|
||||||
o Redistributions of source code must retain the above copyright
|
|
||||||
notice, this condition and the following disclaimer.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
||||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
||||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
DAMAGE.
|
|
||||||
|
|
||||||
|
|
||||||
(c) 2014 - 2016 SEGGER Microcontroller GmbH
|
|
||||||
www.segger.com
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
README.txt for the SEGGER RTT Implementation Pack.
|
|
||||||
|
|
||||||
Included files:
|
|
||||||
===============
|
|
||||||
Root Directory
|
|
||||||
- Examples
|
|
||||||
- Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0.
|
|
||||||
- Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality.
|
|
||||||
- Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation.
|
|
||||||
- Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed.
|
|
||||||
- RTT
|
|
||||||
- SEGGER_RTT.c - The RTT implementation.
|
|
||||||
- SEGGER_RTT.h - Header for RTT implementation.
|
|
||||||
- SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation.
|
|
||||||
- SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT.
|
|
||||||
- Syscalls
|
|
||||||
- RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib.
|
|
||||||
- RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler.
|
|
||||||
- RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler.
|
|
||||||
- RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio.
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT_Syscalls_GCC.c
|
|
||||||
Purpose : Low-level functions for using printf() via RTT in GCC.
|
|
||||||
To use RTT for printf output, include this file in your
|
|
||||||
application.
|
|
||||||
Revision: $Rev: 17697 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM)
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
#include <reent.h> // required for _write_r
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Types
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
// If necessary define the _reent struct
|
|
||||||
// to match the one passed by the used standard library.
|
|
||||||
//
|
|
||||||
struct _reent;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Function prototypes
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
int _write(int file, char *ptr, int len);
|
|
||||||
// _ssize_t _write_r(struct _reent *r, int file, const void *ptr, int len);
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _write()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Low-level write function.
|
|
||||||
* libc subroutines will use this system routine for output to all files,
|
|
||||||
* including stdout.
|
|
||||||
* Write data via RTT.
|
|
||||||
*/
|
|
||||||
int _write(int file, char *ptr, int len)
|
|
||||||
{
|
|
||||||
(void)file; /* Not used, avoid warning */
|
|
||||||
SEGGER_RTT_Write(0, ptr, len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _write_r()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Low-level reentrant write function.
|
|
||||||
* libc subroutines will use this system routine for output to all files,
|
|
||||||
* including stdout.
|
|
||||||
* Write data via RTT.
|
|
||||||
*/
|
|
||||||
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, int len)
|
|
||||||
{
|
|
||||||
(void)file; /* Not used, avoid warning */
|
|
||||||
(void)r; /* Not used, avoid warning */
|
|
||||||
SEGGER_RTT_Write(0, ptr, len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/****** End Of File *************************************************/
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT_Syscalls_IAR.c
|
|
||||||
Purpose : Low-level functions for using printf() via RTT in IAR.
|
|
||||||
To use RTT for printf output, include this file in your
|
|
||||||
application and set the Library Configuration to Normal.
|
|
||||||
Revision: $Rev: 17697 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifdef __IAR_SYSTEMS_ICC__
|
|
||||||
|
|
||||||
//
|
|
||||||
// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h
|
|
||||||
// shall be used instead. To not break any compatibility with older compiler versions, we have a
|
|
||||||
// version check in here.
|
|
||||||
//
|
|
||||||
#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400))
|
|
||||||
#include <LowLevelIOInterface.h>
|
|
||||||
#else
|
|
||||||
#include <yfuns.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
#pragma module_name = "?__write"
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Function prototypes
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
size_t __write(int handle, const unsigned char * buffer, size_t size);
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* __write()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Low-level write function.
|
|
||||||
* Standard library subroutines will use this system routine
|
|
||||||
* for output to all files, including stdout.
|
|
||||||
* Write data via RTT.
|
|
||||||
*/
|
|
||||||
size_t __write(int handle, const unsigned char * buffer, size_t size) {
|
|
||||||
(void) handle; /* Not used, avoid warning */
|
|
||||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* __write_buffered()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Low-level write function.
|
|
||||||
* Standard library subroutines will use this system routine
|
|
||||||
* for output to all files, including stdout.
|
|
||||||
* Write data via RTT.
|
|
||||||
*/
|
|
||||||
size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
|
|
||||||
(void) handle; /* Not used, avoid warning */
|
|
||||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/****** End Of File *************************************************/
|
|
||||||
@@ -1,386 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : RTT_Syscalls_KEIL.c
|
|
||||||
Purpose : Retargeting module for KEIL MDK-CM3.
|
|
||||||
Low-level functions for using printf() via RTT
|
|
||||||
Revision: $Rev: 17697 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifdef __CC_ARM
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <rt_sys.h>
|
|
||||||
#include <rt_misc.h>
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* #pragmas
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#pragma import(__use_no_semihosting)
|
|
||||||
|
|
||||||
#ifdef _MICROLIB
|
|
||||||
#pragma import(__use_full_stdio)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines non-configurable
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Standard IO device handles - arbitrary, but any real file system handles must be
|
|
||||||
less than 0x8000. */
|
|
||||||
#define STDIN 0x8001 // Standard Input Stream
|
|
||||||
#define STDOUT 0x8002 // Standard Output Stream
|
|
||||||
#define STDERR 0x8003 // Standard Error Stream
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Public const
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#if __ARMCC_VERSION < 5000000
|
|
||||||
//const char __stdin_name[] = "STDIN";
|
|
||||||
const char __stdout_name[] = "STDOUT";
|
|
||||||
const char __stderr_name[] = "STDERR";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Public code
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _ttywrch
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Outputs a character to the console
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* c - character to output
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void _ttywrch(int c) {
|
|
||||||
fputc(c, stdout); // stdout
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_open
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Opens the device/file in order to do read/write operations
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* sName - sName of the device/file to open
|
|
||||||
* OpenMode - This parameter is currently ignored
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* != 0 - Handle to the object to open, otherwise
|
|
||||||
* == 0 -"device" is not handled by this module
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
FILEHANDLE _sys_open(const char * sName, int OpenMode) {
|
|
||||||
(void)OpenMode;
|
|
||||||
// Register standard Input Output devices.
|
|
||||||
if (strcmp(sName, __stdout_name) == 0) {
|
|
||||||
return (STDOUT);
|
|
||||||
} else if (strcmp(sName, __stderr_name) == 0) {
|
|
||||||
return (STDERR);
|
|
||||||
} else
|
|
||||||
return (0); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_close
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Closes the handle to the open device/file
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* 0 - device/file closed
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_close(FILEHANDLE hFile) {
|
|
||||||
(void)hFile;
|
|
||||||
return 0; // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_write
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Writes the data to an open handle.
|
|
||||||
* Currently this function only outputs data to the console
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
* pBuffer - Pointer to the data that shall be written
|
|
||||||
* NumBytes - Number of bytes to write
|
|
||||||
* Mode - The Mode that shall be used
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* Number of bytes *not* written to the file/device
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
(void)Mode;
|
|
||||||
if (hFile == STDOUT) {
|
|
||||||
SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_read
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Reads data from an open handle.
|
|
||||||
* Currently this modules does nothing.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
* pBuffer - Pointer to buffer to store the read data
|
|
||||||
* NumBytes - Number of bytes to read
|
|
||||||
* Mode - The Mode that shall be used
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* Number of bytes read from the file/device
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
|
||||||
(void)hFile;
|
|
||||||
(void)pBuffer;
|
|
||||||
(void)NumBytes;
|
|
||||||
(void)Mode;
|
|
||||||
return (0); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_istty
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* This function shall return whether the opened file
|
|
||||||
* is a console device or not.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* 1 - Device is a console
|
|
||||||
* 0 - Device is not a console
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_istty(FILEHANDLE hFile) {
|
|
||||||
if (hFile > 0x8000) {
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
return (0); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_seek
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Seeks via the file to a specific position
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
* Pos -
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* int -
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_seek(FILEHANDLE hFile, long Pos) {
|
|
||||||
(void)hFile;
|
|
||||||
(void)Pos;
|
|
||||||
return (0); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_ensure
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* int -
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_ensure(FILEHANDLE hFile) {
|
|
||||||
(void)hFile;
|
|
||||||
return (-1); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_flen
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Returns the length of the opened file handle
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* hFile - Handle to a file opened via _sys_open
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* Length of the file
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
long _sys_flen(FILEHANDLE hFile) {
|
|
||||||
(void)hFile;
|
|
||||||
return (0); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_tmpnam
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* This function converts the file number fileno for a temporary
|
|
||||||
* file to a unique filename, for example, tmp0001.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* pBuffer - Pointer to a buffer to store the name
|
|
||||||
* FileNum - file number to convert
|
|
||||||
* MaxLen - Size of the buffer
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* 1 - Error
|
|
||||||
* 0 - Success
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
|
|
||||||
(void)pBuffer;
|
|
||||||
(void)FileNum;
|
|
||||||
(void)MaxLen;
|
|
||||||
return (1); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_command_string
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* This function shall execute a system command.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* cmd - Pointer to the command string
|
|
||||||
* len - Length of the string
|
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
* == NULL - Command was not successfully executed
|
|
||||||
* == sCmd - Command was passed successfully
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
char * _sys_command_string(char * cmd, int len) {
|
|
||||||
(void)len;
|
|
||||||
return cmd; // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _sys_exit
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* This function is called when the application returns from main
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* ReturnCode - Return code from the main function
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void _sys_exit(int ReturnCode) {
|
|
||||||
(void)ReturnCode;
|
|
||||||
while (1); // Not implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __ARMCC_VERSION >= 5000000
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* stdout_putchar
|
|
||||||
*
|
|
||||||
* Function description:
|
|
||||||
* Put a character to the stdout
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* ch - Character to output
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int stdout_putchar(int ch) {
|
|
||||||
(void)ch;
|
|
||||||
return ch; // Not implemented
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT_Syscalls_SES.c
|
|
||||||
Purpose : Reimplementation of printf, puts and __getchar using RTT
|
|
||||||
in SEGGER Embedded Studio.
|
|
||||||
To use RTT for printf output, include this file in your
|
|
||||||
application.
|
|
||||||
Revision: $Rev: 18539 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM)
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "limits.h"
|
|
||||||
#include "__libc.h"
|
|
||||||
#include "__vfprintf.h"
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, configurable
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
// Select string formatting implementation.
|
|
||||||
//
|
|
||||||
// RTT printf formatting
|
|
||||||
// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
|
|
||||||
// - No maximum string length.
|
|
||||||
// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
|
|
||||||
// Standard library printf formatting
|
|
||||||
// - Configurable formatting capabilities.
|
|
||||||
// - Full conversion specifier and flag support.
|
|
||||||
// - Maximum string length has to be known or (slightly) slower character-wise output.
|
|
||||||
//
|
|
||||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting
|
|
||||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting
|
|
||||||
//
|
|
||||||
#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING
|
|
||||||
#define PRINTF_USE_SEGGER_RTT_FORMATTING 0
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// If using standard library formatting,
|
|
||||||
// select maximum output string buffer size or character-wise output.
|
|
||||||
//
|
|
||||||
// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output
|
|
||||||
// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length
|
|
||||||
//
|
|
||||||
#ifndef PRINTF_BUFFER_SIZE
|
|
||||||
#define PRINTF_BUFFER_SIZE 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Function prototypes
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions, printf
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* printf()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* print a formatted string using RTT and SEGGER RTT formatting.
|
|
||||||
*/
|
|
||||||
int printf(const char *fmt,...) {
|
|
||||||
int n;
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start (args, fmt);
|
|
||||||
n = SEGGER_RTT_vprintf(0, fmt, &args);
|
|
||||||
va_end(args);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Static functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
static int _putchar(int x, __printf_tag_ptr ctx) {
|
|
||||||
(void)ctx;
|
|
||||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions, printf
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* printf()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* print a formatted string character-wise, using RTT and standard
|
|
||||||
* library formatting.
|
|
||||||
*/
|
|
||||||
int printf(const char *fmt, ...) {
|
|
||||||
int n;
|
|
||||||
va_list args;
|
|
||||||
__printf_t iod;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
iod.string = 0;
|
|
||||||
iod.maxchars = INT_MAX;
|
|
||||||
iod.output_fn = _putchar;
|
|
||||||
SEGGER_RTT_LOCK();
|
|
||||||
n = __vfprintf(&iod, fmt, args);
|
|
||||||
SEGGER_RTT_UNLOCK();
|
|
||||||
va_end(args);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // Use standard library formatting with static buffer
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions, printf
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* printf()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* print a formatted string using RTT and standard library formatting.
|
|
||||||
*/
|
|
||||||
int printf(const char *fmt,...) {
|
|
||||||
int n;
|
|
||||||
char aBuffer[PRINTF_BUFFER_SIZE];
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start (args, fmt);
|
|
||||||
n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
|
|
||||||
if (n > (int)sizeof(aBuffer)) {
|
|
||||||
SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
|
|
||||||
} else if (n > 0) {
|
|
||||||
SEGGER_RTT_Write(0, aBuffer, n);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* puts()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* print a string using RTT.
|
|
||||||
*/
|
|
||||||
int puts(const char *s) {
|
|
||||||
return SEGGER_RTT_WriteString(0, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* __putchar()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Write one character via RTT.
|
|
||||||
*/
|
|
||||||
int __putchar(int x, __printf_tag_ptr ctx) {
|
|
||||||
(void)ctx;
|
|
||||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* __getchar()
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Wait for and get a character via RTT.
|
|
||||||
*/
|
|
||||||
int __getchar() {
|
|
||||||
return SEGGER_RTT_WaitKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/****** End Of File *************************************************/
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* Solutions for real time microcontroller applications *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2018 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
--------- END-OF-HEADER --------------------------------------------
|
|
||||||
File : Main_RTT_MenuApp.c
|
|
||||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAIN_C
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
|
|
||||||
volatile int _Cnt;
|
|
||||||
volatile int _Delay;
|
|
||||||
|
|
||||||
static char r;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* main
|
|
||||||
*/
|
|
||||||
void main(void) {
|
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
|
||||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
|
||||||
do {
|
|
||||||
r = SEGGER_RTT_WaitKey();
|
|
||||||
SEGGER_RTT_Write(0, &r, 1);
|
|
||||||
r++;
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* Solutions for real time microcontroller applications *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2018 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
--------- END-OF-HEADER --------------------------------------------
|
|
||||||
File : Main_RTT_MenuApp.c
|
|
||||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAIN_C
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
|
|
||||||
volatile int _Cnt;
|
|
||||||
volatile int _Delay;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* main
|
|
||||||
*/
|
|
||||||
void main(void) {
|
|
||||||
int r;
|
|
||||||
int CancelOp;
|
|
||||||
|
|
||||||
do {
|
|
||||||
_Cnt = 0;
|
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
|
||||||
SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n");
|
|
||||||
SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n");
|
|
||||||
do {
|
|
||||||
r = SEGGER_RTT_WaitKey();
|
|
||||||
} while ((r != '1') && (r != '2'));
|
|
||||||
if (r == '1') {
|
|
||||||
SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n");
|
|
||||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
|
||||||
} else {
|
|
||||||
SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n");
|
|
||||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
|
||||||
}
|
|
||||||
CancelOp = 0;
|
|
||||||
do {
|
|
||||||
//for (_Delay = 0; _Delay < 10000; _Delay++);
|
|
||||||
SEGGER_RTT_printf(0, "Count: %d. Press <Space> to get back to menu.\r\n", _Cnt++);
|
|
||||||
r = SEGGER_RTT_HasKey();
|
|
||||||
if (r) {
|
|
||||||
CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Check if user selected to cancel the current operation
|
|
||||||
//
|
|
||||||
if (CancelOp) {
|
|
||||||
SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (1);
|
|
||||||
SEGGER_RTT_GetKey();
|
|
||||||
SEGGER_RTT_WriteString(0, "\r\n");
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* Solutions for real time microcontroller applications *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2018 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
--------- END-OF-HEADER --------------------------------------------
|
|
||||||
File : Main_RTT_MenuApp.c
|
|
||||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAIN_C
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
|
|
||||||
volatile int _Cnt;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* main
|
|
||||||
*/
|
|
||||||
void main(void) {
|
|
||||||
|
|
||||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n");
|
|
||||||
SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n");
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S');
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E');
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G');
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G');
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E');
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R');
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT");
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks.");
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345);
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345);
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345);
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC);
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC);
|
|
||||||
|
|
||||||
SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt);
|
|
||||||
|
|
||||||
SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n");
|
|
||||||
do {
|
|
||||||
_Cnt++;
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* Solutions for real time microcontroller applications *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2018 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
--------- END-OF-HEADER --------------------------------------------
|
|
||||||
File : Main_RTT_SpeedTestApp.c
|
|
||||||
Purpose : Sample program for measuring RTT performance.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "RTOS.h"
|
|
||||||
#include "BSP.h"
|
|
||||||
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */
|
|
||||||
OS_TASK TCBHP, TCBLP; /* Task-control-blocks */
|
|
||||||
|
|
||||||
static void HPTask(void) {
|
|
||||||
while (1) {
|
|
||||||
//
|
|
||||||
// Measure time needed for RTT output
|
|
||||||
// Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general
|
|
||||||
//
|
|
||||||
// Set BP here. Then start sampling on scope
|
|
||||||
BSP_ClrLED(0);
|
|
||||||
SEGGER_RTT_Write(0, 0, 0);
|
|
||||||
BSP_SetLED(0);
|
|
||||||
BSP_ClrLED(0);
|
|
||||||
SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82);
|
|
||||||
BSP_SetLED(0);
|
|
||||||
// Set BP here. Then stop sampling on scope
|
|
||||||
OS_Delay(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LPTask(void) {
|
|
||||||
while (1) {
|
|
||||||
BSP_ToggleLED(1);
|
|
||||||
OS_Delay (500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* main
|
|
||||||
*
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
OS_IncDI(); /* Initially disable interrupts */
|
|
||||||
OS_InitKern(); /* Initialize OS */
|
|
||||||
OS_InitHW(); /* Initialize Hardware for OS */
|
|
||||||
BSP_Init(); /* Initialize LED ports */
|
|
||||||
BSP_SetLED(0);
|
|
||||||
/* You need to create at least one task before calling OS_Start() */
|
|
||||||
OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
|
|
||||||
OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP);
|
|
||||||
OS_Start(); /* Start multitasking */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,321 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT.h
|
|
||||||
Purpose : Implementation of SEGGER real-time transfer which allows
|
|
||||||
real-time communication on targets which support debugger
|
|
||||||
memory accesses while the CPU is running.
|
|
||||||
Revision: $Rev: 17697 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_H
|
|
||||||
#define SEGGER_RTT_H
|
|
||||||
|
|
||||||
#include "SEGGER_RTT_Conf.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, defaults
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#ifndef RTT_USE_ASM
|
|
||||||
#if (defined __SES_ARM) // SEGGER Embedded Studio
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __GNUC__) // GCC
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __clang__) // Clang compiler
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __IASMARM__) // IAR assembler
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __ICCARM__) // IAR compiler
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#else
|
|
||||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
|
||||||
#endif
|
|
||||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3/4
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M7
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#elif (defined __ARM7M__) // IAR Cortex-M3/4
|
|
||||||
#if (__CORE__ == __ARM7M__)
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#else
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
|
||||||
#endif
|
|
||||||
#elif (defined __ARM7EM__) // IAR Cortex-M7
|
|
||||||
#if (__CORE__ == __ARM7EM__)
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
|
||||||
#else
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// If IDE and core support the ASM version, enable ASM version by default
|
|
||||||
//
|
|
||||||
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
|
|
||||||
#define RTT_USE_ASM (1)
|
|
||||||
#else
|
|
||||||
#define RTT_USE_ASM (0)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, fixed
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Types
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Description for a circular buffer (also called "ring buffer")
|
|
||||||
// which is used as up-buffer (T->H)
|
|
||||||
//
|
|
||||||
typedef struct {
|
|
||||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
|
||||||
char* pBuffer; // Pointer to start of buffer
|
|
||||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
|
||||||
unsigned WrOff; // Position of next item to be written by either target.
|
|
||||||
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
|
|
||||||
unsigned Flags; // Contains configuration flags
|
|
||||||
} SEGGER_RTT_BUFFER_UP;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Description for a circular buffer (also called "ring buffer")
|
|
||||||
// which is used as down-buffer (H->T)
|
|
||||||
//
|
|
||||||
typedef struct {
|
|
||||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
|
||||||
char* pBuffer; // Pointer to start of buffer
|
|
||||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
|
||||||
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
|
|
||||||
unsigned RdOff; // Position of next item to be read by target (down-buffer).
|
|
||||||
unsigned Flags; // Contains configuration flags
|
|
||||||
} SEGGER_RTT_BUFFER_DOWN;
|
|
||||||
|
|
||||||
//
|
|
||||||
// RTT control block which describes the number of buffers available
|
|
||||||
// as well as the configuration for each buffer
|
|
||||||
//
|
|
||||||
//
|
|
||||||
typedef struct {
|
|
||||||
char acID[16]; // Initialized to "SEGGER RTT"
|
|
||||||
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
|
||||||
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
|
||||||
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
|
|
||||||
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
|
|
||||||
} SEGGER_RTT_CB;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Global data
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
extern SEGGER_RTT_CB _SEGGER_RTT;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT API functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
|
||||||
int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
|
||||||
int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
|
||||||
int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
|
||||||
int SEGGER_RTT_GetKey (void);
|
|
||||||
unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
|
|
||||||
int SEGGER_RTT_HasKey (void);
|
|
||||||
unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
|
|
||||||
void SEGGER_RTT_Init (void);
|
|
||||||
unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
|
||||||
unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
|
||||||
int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
|
|
||||||
int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
|
|
||||||
int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
|
|
||||||
int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
|
|
||||||
int SEGGER_RTT_WaitKey (void);
|
|
||||||
unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
|
||||||
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
|
|
||||||
unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
|
|
||||||
unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
|
|
||||||
unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
|
|
||||||
unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
|
|
||||||
//
|
|
||||||
// Function macro for performance optimization
|
|
||||||
//
|
|
||||||
#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff)
|
|
||||||
|
|
||||||
#if RTT_USE_ASM
|
|
||||||
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT transfer functions to send RTT data via other channels.
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
|
||||||
unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
|
||||||
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff)
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT "Terminal" API functions
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
|
|
||||||
int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT printf functions (require SEGGER_RTT_printf.c)
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
|
|
||||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ifndef(SEGGER_RTT_ASM)
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
|
|
||||||
//
|
|
||||||
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
|
|
||||||
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
|
|
||||||
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
|
|
||||||
#define SEGGER_RTT_MODE_MASK (3)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Control sequences, based on ANSI.
|
|
||||||
// Can be used to control color, and clear the screen
|
|
||||||
//
|
|
||||||
#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
|
|
||||||
#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
|
|
||||||
|
|
||||||
#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
|
|
||||||
#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
|
|
||||||
#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
|
|
||||||
#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
|
|
||||||
#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
|
|
||||||
#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
|
|
||||||
#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
|
|
||||||
#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
|
|
||||||
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
|
|
||||||
#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
|
|
||||||
|
|
||||||
#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
|
|
||||||
#define RTT_CTRL_BG_RED "\x1B[24;41m"
|
|
||||||
#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
|
|
||||||
#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
|
|
||||||
#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
|
|
||||||
#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
|
|
||||||
#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
|
|
||||||
#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
|
|
||||||
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
|
|
||||||
#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,384 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT_Conf.h
|
|
||||||
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
|
||||||
allows real-time communication on targets which support
|
|
||||||
debugger memory accesses while the CPU is running.
|
|
||||||
Revision: $Rev: 18601 $
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_CONF_H
|
|
||||||
#define SEGGER_RTT_CONF_H
|
|
||||||
|
|
||||||
#ifdef __IAR_SYSTEMS_ICC__
|
|
||||||
#include <intrinsics.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, configurable
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
|
||||||
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
|
||||||
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BUFFER_SIZE_UP
|
|
||||||
#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BUFFER_SIZE_DOWN
|
|
||||||
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
|
||||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_MODE_DEFAULT
|
|
||||||
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT memcpy configuration
|
|
||||||
*
|
|
||||||
* memcpy() is good for large amounts of data,
|
|
||||||
* but the overhead is big for small amounts, which are usually stored via RTT.
|
|
||||||
* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
|
|
||||||
*
|
|
||||||
* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
|
|
||||||
* This is may be required with memory access restrictions,
|
|
||||||
* such as on Cortex-A devices with MMU.
|
|
||||||
*/
|
|
||||||
#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
|
||||||
#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
|
|
||||||
//
|
|
||||||
//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
|
|
||||||
// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
|
|
||||||
// Otherwise we would probably end up with a mixed string in the buffer.
|
|
||||||
// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
|
|
||||||
//
|
|
||||||
// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
|
|
||||||
// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
|
|
||||||
// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
|
|
||||||
// (Higher priority = lower priority number)
|
|
||||||
// Default value for embOS: 128u
|
|
||||||
// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
|
||||||
// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
|
|
||||||
// or define SEGGER_RTT_LOCK() to completely disable interrupts.
|
|
||||||
//
|
|
||||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
|
||||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for SEGGER Embedded Studio,
|
|
||||||
* Rowley CrossStudio and GCC
|
|
||||||
*/
|
|
||||||
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
|
|
||||||
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
__asm volatile ("mrs %0, primask \n\t" \
|
|
||||||
"movs r1, $1 \n\t" \
|
|
||||||
"msr primask, r1 \n\t" \
|
|
||||||
: "=r" (LockState) \
|
|
||||||
: \
|
|
||||||
: "r1" \
|
|
||||||
);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
|
|
||||||
: \
|
|
||||||
: "r" (LockState) \
|
|
||||||
: \
|
|
||||||
); \
|
|
||||||
}
|
|
||||||
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))
|
|
||||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
|
||||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
|
||||||
#endif
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
__asm volatile ("mrs %0, basepri \n\t" \
|
|
||||||
"mov r1, %1 \n\t" \
|
|
||||||
"msr basepri, r1 \n\t" \
|
|
||||||
: "=r" (LockState) \
|
|
||||||
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
|
|
||||||
: "r1" \
|
|
||||||
);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
|
|
||||||
: \
|
|
||||||
: "r" (LockState) \
|
|
||||||
: \
|
|
||||||
); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__ARM_ARCH_7A__)
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
|
||||||
"mov %0, r1 \n\t" \
|
|
||||||
"orr r1, r1, #0xC0 \n\t" \
|
|
||||||
"msr CPSR_c, r1 \n\t" \
|
|
||||||
: "=r" (LockState) \
|
|
||||||
: \
|
|
||||||
: "r1" \
|
|
||||||
);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
|
||||||
"mrs r1, CPSR \n\t" \
|
|
||||||
"bic r1, r1, #0xC0 \n\t" \
|
|
||||||
"and r0, r0, #0xC0 \n\t" \
|
|
||||||
"orr r1, r1, r0 \n\t" \
|
|
||||||
"msr CPSR_c, r1 \n\t" \
|
|
||||||
: \
|
|
||||||
: "r" (LockState) \
|
|
||||||
: "r0", "r1" \
|
|
||||||
); \
|
|
||||||
}
|
|
||||||
#elif defined(__riscv) || defined(__riscv_xlen)
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
__asm volatile ("csrr %0, mstatus \n\t" \
|
|
||||||
"csrci mstatus, 8 \n\t" \
|
|
||||||
"andi %0, %0, 8 \n\t" \
|
|
||||||
: "=r" (LockState) \
|
|
||||||
: \
|
|
||||||
: \
|
|
||||||
);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
|
|
||||||
"or %0, %0, a1 \n\t" \
|
|
||||||
"csrs mstatus, %0 \n\t" \
|
|
||||||
: \
|
|
||||||
: "r" (LockState) \
|
|
||||||
: "a1" \
|
|
||||||
); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define SEGGER_RTT_LOCK()
|
|
||||||
#define SEGGER_RTT_UNLOCK()
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for IAR EWARM
|
|
||||||
*/
|
|
||||||
#ifdef __ICCARM__
|
|
||||||
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
|
|
||||||
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
LockState = __get_PRIMASK(); \
|
|
||||||
__set_PRIMASK(1);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
|
|
||||||
}
|
|
||||||
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
|
|
||||||
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
|
|
||||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
|
|
||||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
|
|
||||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
|
||||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
|
||||||
#endif
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
LockState = __get_BASEPRI(); \
|
|
||||||
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for IAR RX
|
|
||||||
*/
|
|
||||||
#ifdef __ICCRX__
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned long LockState; \
|
|
||||||
LockState = __get_interrupt_state(); \
|
|
||||||
__disable_interrupt();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for IAR RL78
|
|
||||||
*/
|
|
||||||
#ifdef __ICCRL78__
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
__istate_t LockState; \
|
|
||||||
LockState = __get_interrupt_state(); \
|
|
||||||
__disable_interrupt();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for KEIL ARM
|
|
||||||
*/
|
|
||||||
#ifdef __CC_ARM
|
|
||||||
#if (defined __TARGET_ARCH_6S_M)
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
register unsigned char PRIMASK __asm( "primask"); \
|
|
||||||
LockState = PRIMASK; \
|
|
||||||
PRIMASK = 1u; \
|
|
||||||
__schedule_barrier();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \
|
|
||||||
__schedule_barrier(); \
|
|
||||||
}
|
|
||||||
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
|
||||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
|
||||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
|
||||||
#endif
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
register unsigned char BASEPRI __asm( "basepri"); \
|
|
||||||
LockState = BASEPRI; \
|
|
||||||
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
|
|
||||||
__schedule_barrier();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \
|
|
||||||
__schedule_barrier(); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for TI ARM
|
|
||||||
*/
|
|
||||||
#ifdef __TI_ARM__
|
|
||||||
#if defined (__TI_ARM_V6M0__)
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
LockState = __get_PRIMASK(); \
|
|
||||||
__set_PRIMASK(1);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
|
|
||||||
}
|
|
||||||
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
|
|
||||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
|
||||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
|
||||||
#endif
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned int LockState; \
|
|
||||||
LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for CCRX
|
|
||||||
*/
|
|
||||||
#ifdef __RX
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
unsigned long LockState; \
|
|
||||||
LockState = get_psw() & 0x010000; \
|
|
||||||
clrpsw_i();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration for embOS Simulation on Windows
|
|
||||||
* (Can also be used for generic RTT locking with embOS)
|
|
||||||
*/
|
|
||||||
#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
|
|
||||||
|
|
||||||
void OS_SIM_EnterCriticalSection(void);
|
|
||||||
void OS_SIM_LeaveCriticalSection(void);
|
|
||||||
|
|
||||||
#define SEGGER_RTT_LOCK() { \
|
|
||||||
OS_SIM_EnterCriticalSection();
|
|
||||||
|
|
||||||
#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* RTT lock configuration fallback
|
|
||||||
*/
|
|
||||||
#ifndef SEGGER_RTT_LOCK
|
|
||||||
#define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_UNLOCK
|
|
||||||
#define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,235 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* (c) SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
* www.segger.com *
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
-------------------------- END-OF-HEADER -----------------------------
|
|
||||||
|
|
||||||
File : SEGGER_RTT_ASM_ARMv7M.S
|
|
||||||
Purpose : Assembler implementation of RTT functions for ARMv7M
|
|
||||||
|
|
||||||
Additional information:
|
|
||||||
This module is written to be assembler-independent and works with
|
|
||||||
GCC and clang (Embedded Studio) and IAR.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SEGGER_RTT_ASM // Used to control processed input from header file
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, fixed
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
#define _CCIAR 0
|
|
||||||
#define _CCCLANG 1
|
|
||||||
|
|
||||||
#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__)
|
|
||||||
#define _CC_TYPE _CCCLANG
|
|
||||||
#define _PUB_SYM .global
|
|
||||||
#define _EXT_SYM .extern
|
|
||||||
#define _END .end
|
|
||||||
#define _WEAK .weak
|
|
||||||
#define _THUMB_FUNC .thumb_func
|
|
||||||
#define _THUMB_CODE .code 16
|
|
||||||
#define _WORD .word
|
|
||||||
#define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax"
|
|
||||||
#define _ALIGN(Exp) .align Exp
|
|
||||||
#define _PLACE_LITS .ltorg
|
|
||||||
#define _DATA_SECT_START
|
|
||||||
#define _C_STARTUP _start
|
|
||||||
#define _STACK_END __stack_end__
|
|
||||||
#define _RAMFUNC
|
|
||||||
//
|
|
||||||
// .text => Link to flash
|
|
||||||
// .fast => Link to RAM
|
|
||||||
// OtherSect => Usually link to RAM
|
|
||||||
// Alignment is 2^x
|
|
||||||
//
|
|
||||||
#elif defined (__IASMARM__)
|
|
||||||
#define _CC_TYPE _CCIAR
|
|
||||||
#define _PUB_SYM PUBLIC
|
|
||||||
#define _EXT_SYM EXTERN
|
|
||||||
#define _END END
|
|
||||||
#define _WEAK _WEAK
|
|
||||||
#define _THUMB_FUNC
|
|
||||||
#define _THUMB_CODE THUMB
|
|
||||||
#define _WORD DCD
|
|
||||||
#define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp)
|
|
||||||
#define _ALIGN(Exp) alignrom Exp
|
|
||||||
#define _PLACE_LITS
|
|
||||||
#define _DATA_SECT_START DATA
|
|
||||||
#define _C_STARTUP __iar_program_start
|
|
||||||
#define _STACK_END sfe(CSTACK)
|
|
||||||
#define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
|
||||||
//
|
|
||||||
// .text => Link to flash
|
|
||||||
// .textrw => Link to RAM
|
|
||||||
// OtherSect => Usually link to RAM
|
|
||||||
// NOROOT => Allows linker to throw away the function, if not referenced
|
|
||||||
// Alignment is 2^x
|
|
||||||
//
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (_CC_TYPE == _CCIAR)
|
|
||||||
NAME SEGGER_RTT_ASM_ARMv7M
|
|
||||||
#else
|
|
||||||
.syntax unified
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
|
||||||
#define SHT_PROGBITS 0x1
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Public / external symbols
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
_EXT_SYM __aeabi_memcpy
|
|
||||||
_EXT_SYM __aeabi_memcpy4
|
|
||||||
_EXT_SYM _SEGGER_RTT
|
|
||||||
|
|
||||||
_PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* SEGGER_RTT_WriteSkipNoLock
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Stores a specified number of characters in SEGGER RTT
|
|
||||||
* control block which is then read by the host.
|
|
||||||
* SEGGER_RTT_WriteSkipNoLock does not lock the application and
|
|
||||||
* skips all data, if the data does not fit into the buffer.
|
|
||||||
*
|
|
||||||
* Parameters
|
|
||||||
* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
|
||||||
* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
|
|
||||||
* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
|
|
||||||
* MUST be > 0!!!
|
|
||||||
* This is done for performance reasons, so no initial check has do be done.
|
|
||||||
*
|
|
||||||
* Return value
|
|
||||||
* 1: Data has been copied
|
|
||||||
* 0: No space, data has not been copied
|
|
||||||
*
|
|
||||||
* Notes
|
|
||||||
* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
|
|
||||||
* (2) For performance reasons this function does not call Init()
|
|
||||||
* and may only be called after RTT has been initialized.
|
|
||||||
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
|
||||||
*/
|
|
||||||
_SECTION(.text, CODE, 2)
|
|
||||||
_ALIGN(2)
|
|
||||||
_THUMB_FUNC
|
|
||||||
SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) {
|
|
||||||
//
|
|
||||||
// Cases:
|
|
||||||
// 1) RdOff <= WrOff => Space until wrap-around is sufficient
|
|
||||||
// 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
|
|
||||||
// 3) RdOff < WrOff => No space in buf
|
|
||||||
// 4) RdOff > WrOff => Space is sufficient
|
|
||||||
// 5) RdOff > WrOff => No space in buf
|
|
||||||
//
|
|
||||||
// 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
|
|
||||||
//
|
|
||||||
// Register usage:
|
|
||||||
// R0 Temporary needed as RdOff, <Tmp> register later on
|
|
||||||
// R1 pData
|
|
||||||
// R2 <NumBytes>
|
|
||||||
// R3 <Tmp> register. Hold free for subroutine calls
|
|
||||||
// R4 <Rem>
|
|
||||||
// R5 pRing->pBuffer
|
|
||||||
// R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN)
|
|
||||||
// R7 WrOff
|
|
||||||
//
|
|
||||||
PUSH {R4-R7}
|
|
||||||
ADD R3,R0,R0, LSL #+1
|
|
||||||
LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
|
||||||
ADD R0,R0,R3, LSL #+3
|
|
||||||
ADD R6,R0,#+24
|
|
||||||
LDR R0,[R6, #+16] // RdOff = pRing->RdOff;
|
|
||||||
LDR R7,[R6, #+12] // WrOff = pRing->WrOff;
|
|
||||||
LDR R5,[R6, #+4] // pRing->pBuffer
|
|
||||||
CMP R7,R0
|
|
||||||
BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3)
|
|
||||||
//
|
|
||||||
// Handling for case 1, later on identical to case 4
|
|
||||||
//
|
|
||||||
LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
|
|
||||||
SUBS R4,R3,R7 // <Rem> (Used in case we jump into case 2 afterwards)
|
|
||||||
SUBS R3,R4,#+1 // <Avail>
|
|
||||||
CMP R3,R2
|
|
||||||
BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)?
|
|
||||||
_Case4:
|
|
||||||
ADDS R5,R7,R5 // pBuffer += WrOff
|
|
||||||
ADDS R0,R2,R7 // v = WrOff + NumBytes
|
|
||||||
//
|
|
||||||
// 2x unrolling for the copy loop that is used most of the time
|
|
||||||
// This is a special optimization for small SystemView packets and makes them even faster
|
|
||||||
//
|
|
||||||
_ALIGN(2)
|
|
||||||
_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
|
||||||
LDRB R3,[R1], #+1
|
|
||||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
|
||||||
SUBS R2,R2,#+1
|
|
||||||
BEQ _CSDone
|
|
||||||
LDRB R3,[R1], #+1
|
|
||||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
|
||||||
SUBS R2,R2,#+1
|
|
||||||
BNE _LoopCopyStraight
|
|
||||||
_CSDone:
|
|
||||||
STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes;
|
|
||||||
MOVS R0,#+1
|
|
||||||
POP {R4-R7}
|
|
||||||
BX LR // Return 1
|
|
||||||
_CheckCase2:
|
|
||||||
ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around
|
|
||||||
CMP R0,R2
|
|
||||||
BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit)
|
|
||||||
//
|
|
||||||
// Handling for case 2
|
|
||||||
//
|
|
||||||
ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value
|
|
||||||
SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer)
|
|
||||||
_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk
|
|
||||||
LDRB R3,[R1], #+1
|
|
||||||
STRB R3,[R0], #+1 // *pDest++ = *pSrc++
|
|
||||||
SUBS R4,R4,#+1
|
|
||||||
BNE _LoopCopyBeforeWrapAround
|
|
||||||
//
|
|
||||||
// Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
|
|
||||||
// But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
|
|
||||||
// In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
|
|
||||||
// Therefore, check if 2nd memcpy is necessary at all
|
|
||||||
//
|
|
||||||
ADDS R4,R2,#+0 // Save <NumBytes> (needed as counter in loop but must be written to <WrOff> after the loop). Also use this inst to update the flags to skip 2nd loop if possible
|
|
||||||
BEQ.N _No2ChunkNeeded // if (NumBytes) {
|
|
||||||
_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes);
|
|
||||||
LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop
|
|
||||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
|
||||||
SUBS R2,R2,#+1
|
|
||||||
BNE _LoopCopyAfterWrapAround
|
|
||||||
_No2ChunkNeeded:
|
|
||||||
STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer
|
|
||||||
MOVS R0,#+1
|
|
||||||
POP {R4-R7}
|
|
||||||
BX LR // Return 1
|
|
||||||
_CheckCase4:
|
|
||||||
SUBS R0,R0,R7
|
|
||||||
SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u;
|
|
||||||
CMP R0,R2
|
|
||||||
BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit)
|
|
||||||
_Case3:
|
|
||||||
MOVS R0,#+0
|
|
||||||
POP {R4-R7}
|
|
||||||
BX LR // Return 0
|
|
||||||
_PLACE_LITS
|
|
||||||
|
|
||||||
#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
|
||||||
_END
|
|
||||||
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
@@ -1,500 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* SEGGER Microcontroller GmbH *
|
|
||||||
* The Embedded Experts *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
|
|
||||||
* *
|
|
||||||
* www.segger.com Support: support@segger.com *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
* *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* SEGGER strongly recommends to not make any changes *
|
|
||||||
* to or modify the source code of this software in order to stay *
|
|
||||||
* compatible with the RTT protocol and J-Link. *
|
|
||||||
* *
|
|
||||||
* Redistribution and use in source and binary forms, with or *
|
|
||||||
* without modification, are permitted provided that the following *
|
|
||||||
* condition is met: *
|
|
||||||
* *
|
|
||||||
* o Redistributions of source code must retain the above copyright *
|
|
||||||
* notice, this condition and the following disclaimer. *
|
|
||||||
* *
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
|
||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
|
||||||
* DAMAGE. *
|
|
||||||
* *
|
|
||||||
**********************************************************************
|
|
||||||
---------------------------END-OF-HEADER------------------------------
|
|
||||||
File : SEGGER_RTT_printf.c
|
|
||||||
Purpose : Replacement for printf to write formatted data via RTT
|
|
||||||
Revision: $Rev: 17697 $
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
#include "SEGGER_RTT_Conf.h"
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Defines, configurable
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
|
||||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
|
|
||||||
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
|
|
||||||
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
|
|
||||||
#define FORMAT_FLAG_ALTERNATE (1u << 3)
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Types
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* pBuffer;
|
|
||||||
unsigned BufferSize;
|
|
||||||
unsigned Cnt;
|
|
||||||
|
|
||||||
int ReturnValue;
|
|
||||||
|
|
||||||
unsigned RTTBufferIndex;
|
|
||||||
} SEGGER_RTT_PRINTF_DESC;
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Function prototypes
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Static code
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _StoreChar
|
|
||||||
*/
|
|
||||||
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
|
|
||||||
unsigned Cnt;
|
|
||||||
|
|
||||||
Cnt = p->Cnt;
|
|
||||||
if ((Cnt + 1u) <= p->BufferSize) {
|
|
||||||
*(p->pBuffer + Cnt) = c;
|
|
||||||
p->Cnt = Cnt + 1u;
|
|
||||||
p->ReturnValue++;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Write part of string, when the buffer is full
|
|
||||||
//
|
|
||||||
if (p->Cnt == p->BufferSize) {
|
|
||||||
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
|
|
||||||
p->ReturnValue = -1;
|
|
||||||
} else {
|
|
||||||
p->Cnt = 0u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _PrintUnsigned
|
|
||||||
*/
|
|
||||||
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
|
||||||
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
||||||
unsigned Div;
|
|
||||||
unsigned Digit;
|
|
||||||
unsigned Number;
|
|
||||||
unsigned Width;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
Number = v;
|
|
||||||
Digit = 1u;
|
|
||||||
//
|
|
||||||
// Get actual field width
|
|
||||||
//
|
|
||||||
Width = 1u;
|
|
||||||
while (Number >= Base) {
|
|
||||||
Number = (Number / Base);
|
|
||||||
Width++;
|
|
||||||
}
|
|
||||||
if (NumDigits > Width) {
|
|
||||||
Width = NumDigits;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Print leading chars if necessary
|
|
||||||
//
|
|
||||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
|
|
||||||
if (FieldWidth != 0u) {
|
|
||||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
|
|
||||||
c = '0';
|
|
||||||
} else {
|
|
||||||
c = ' ';
|
|
||||||
}
|
|
||||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
|
||||||
FieldWidth--;
|
|
||||||
_StoreChar(pBufferDesc, c);
|
|
||||||
if (pBufferDesc->ReturnValue < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pBufferDesc->ReturnValue >= 0) {
|
|
||||||
//
|
|
||||||
// Compute Digit.
|
|
||||||
// Loop until Digit has the value of the highest digit required.
|
|
||||||
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
|
|
||||||
//
|
|
||||||
while (1) {
|
|
||||||
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
|
|
||||||
NumDigits--;
|
|
||||||
} else {
|
|
||||||
Div = v / Digit;
|
|
||||||
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Digit *= Base;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Output digits
|
|
||||||
//
|
|
||||||
do {
|
|
||||||
Div = v / Digit;
|
|
||||||
v -= Div * Digit;
|
|
||||||
_StoreChar(pBufferDesc, _aV2C[Div]);
|
|
||||||
if (pBufferDesc->ReturnValue < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Digit /= Base;
|
|
||||||
} while (Digit);
|
|
||||||
//
|
|
||||||
// Print trailing spaces if necessary
|
|
||||||
//
|
|
||||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
|
|
||||||
if (FieldWidth != 0u) {
|
|
||||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
|
||||||
FieldWidth--;
|
|
||||||
_StoreChar(pBufferDesc, ' ');
|
|
||||||
if (pBufferDesc->ReturnValue < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* _PrintInt
|
|
||||||
*/
|
|
||||||
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
|
||||||
unsigned Width;
|
|
||||||
int Number;
|
|
||||||
|
|
||||||
Number = (v < 0) ? -v : v;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get actual field width
|
|
||||||
//
|
|
||||||
Width = 1u;
|
|
||||||
while (Number >= (int)Base) {
|
|
||||||
Number = (Number / (int)Base);
|
|
||||||
Width++;
|
|
||||||
}
|
|
||||||
if (NumDigits > Width) {
|
|
||||||
Width = NumDigits;
|
|
||||||
}
|
|
||||||
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
|
|
||||||
FieldWidth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Print leading spaces if necessary
|
|
||||||
//
|
|
||||||
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
|
|
||||||
if (FieldWidth != 0u) {
|
|
||||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
|
||||||
FieldWidth--;
|
|
||||||
_StoreChar(pBufferDesc, ' ');
|
|
||||||
if (pBufferDesc->ReturnValue < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Print sign if necessary
|
|
||||||
//
|
|
||||||
if (pBufferDesc->ReturnValue >= 0) {
|
|
||||||
if (v < 0) {
|
|
||||||
v = -v;
|
|
||||||
_StoreChar(pBufferDesc, '-');
|
|
||||||
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
|
|
||||||
_StoreChar(pBufferDesc, '+');
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
if (pBufferDesc->ReturnValue >= 0) {
|
|
||||||
//
|
|
||||||
// Print leading zeros if necessary
|
|
||||||
//
|
|
||||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
|
|
||||||
if (FieldWidth != 0u) {
|
|
||||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
|
||||||
FieldWidth--;
|
|
||||||
_StoreChar(pBufferDesc, '0');
|
|
||||||
if (pBufferDesc->ReturnValue < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pBufferDesc->ReturnValue >= 0) {
|
|
||||||
//
|
|
||||||
// Print number without sign
|
|
||||||
//
|
|
||||||
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* Public code
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* SEGGER_RTT_vprintf
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Stores a formatted string in SEGGER RTT control block.
|
|
||||||
* This data is read by the host.
|
|
||||||
*
|
|
||||||
* Parameters
|
|
||||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
|
||||||
* sFormat Pointer to format string
|
|
||||||
* pParamList Pointer to the list of arguments for the format string
|
|
||||||
*
|
|
||||||
* Return values
|
|
||||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
|
||||||
* < 0: Error
|
|
||||||
*/
|
|
||||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
|
|
||||||
char c;
|
|
||||||
SEGGER_RTT_PRINTF_DESC BufferDesc;
|
|
||||||
int v;
|
|
||||||
unsigned NumDigits;
|
|
||||||
unsigned FormatFlags;
|
|
||||||
unsigned FieldWidth;
|
|
||||||
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
|
|
||||||
|
|
||||||
BufferDesc.pBuffer = acBuffer;
|
|
||||||
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
|
|
||||||
BufferDesc.Cnt = 0u;
|
|
||||||
BufferDesc.RTTBufferIndex = BufferIndex;
|
|
||||||
BufferDesc.ReturnValue = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
c = *sFormat;
|
|
||||||
sFormat++;
|
|
||||||
if (c == 0u) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c == '%') {
|
|
||||||
//
|
|
||||||
// Filter out flags
|
|
||||||
//
|
|
||||||
FormatFlags = 0u;
|
|
||||||
v = 1;
|
|
||||||
do {
|
|
||||||
c = *sFormat;
|
|
||||||
switch (c) {
|
|
||||||
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
|
|
||||||
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
|
|
||||||
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
|
|
||||||
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
|
|
||||||
default: v = 0; break;
|
|
||||||
}
|
|
||||||
} while (v);
|
|
||||||
//
|
|
||||||
// filter out field with
|
|
||||||
//
|
|
||||||
FieldWidth = 0u;
|
|
||||||
do {
|
|
||||||
c = *sFormat;
|
|
||||||
if ((c < '0') || (c > '9')) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sFormat++;
|
|
||||||
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Filter out precision (number of digits to display)
|
|
||||||
//
|
|
||||||
NumDigits = 0u;
|
|
||||||
c = *sFormat;
|
|
||||||
if (c == '.') {
|
|
||||||
sFormat++;
|
|
||||||
do {
|
|
||||||
c = *sFormat;
|
|
||||||
if ((c < '0') || (c > '9')) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sFormat++;
|
|
||||||
NumDigits = NumDigits * 10u + ((unsigned)c - '0');
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Filter out length modifier
|
|
||||||
//
|
|
||||||
c = *sFormat;
|
|
||||||
do {
|
|
||||||
if ((c == 'l') || (c == 'h')) {
|
|
||||||
sFormat++;
|
|
||||||
c = *sFormat;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (1);
|
|
||||||
//
|
|
||||||
// Handle specifiers
|
|
||||||
//
|
|
||||||
switch (c) {
|
|
||||||
case 'c': {
|
|
||||||
char c0;
|
|
||||||
v = va_arg(*pParamList, int);
|
|
||||||
c0 = (char)v;
|
|
||||||
_StoreChar(&BufferDesc, c0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd':
|
|
||||||
v = va_arg(*pParamList, int);
|
|
||||||
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
v = va_arg(*pParamList, int);
|
|
||||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
case 'X':
|
|
||||||
v = va_arg(*pParamList, int);
|
|
||||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
{
|
|
||||||
const char * s = va_arg(*pParamList, const char *);
|
|
||||||
do {
|
|
||||||
c = *s;
|
|
||||||
s++;
|
|
||||||
if (c == '\0') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_StoreChar(&BufferDesc, c);
|
|
||||||
} while (BufferDesc.ReturnValue >= 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
v = va_arg(*pParamList, int);
|
|
||||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
_StoreChar(&BufferDesc, '%');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sFormat++;
|
|
||||||
} else {
|
|
||||||
_StoreChar(&BufferDesc, c);
|
|
||||||
}
|
|
||||||
} while (BufferDesc.ReturnValue >= 0);
|
|
||||||
|
|
||||||
if (BufferDesc.ReturnValue > 0) {
|
|
||||||
//
|
|
||||||
// Write remaining data, if any
|
|
||||||
//
|
|
||||||
if (BufferDesc.Cnt != 0u) {
|
|
||||||
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
|
|
||||||
}
|
|
||||||
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
|
|
||||||
}
|
|
||||||
return BufferDesc.ReturnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*
|
|
||||||
* SEGGER_RTT_printf
|
|
||||||
*
|
|
||||||
* Function description
|
|
||||||
* Stores a formatted string in SEGGER RTT control block.
|
|
||||||
* This data is read by the host.
|
|
||||||
*
|
|
||||||
* Parameters
|
|
||||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
|
||||||
* sFormat Pointer to format string, followed by the arguments for conversion
|
|
||||||
*
|
|
||||||
* Return values
|
|
||||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
|
||||||
* < 0: Error
|
|
||||||
*
|
|
||||||
* Notes
|
|
||||||
* (1) Conversion specifications have following syntax:
|
|
||||||
* %[flags][FieldWidth][.Precision]ConversionSpecifier
|
|
||||||
* (2) Supported flags:
|
|
||||||
* -: Left justify within the field width
|
|
||||||
* +: Always print sign extension for signed conversions
|
|
||||||
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
|
|
||||||
* Supported conversion specifiers:
|
|
||||||
* c: Print the argument as one char
|
|
||||||
* d: Print the argument as a signed integer
|
|
||||||
* u: Print the argument as an unsigned integer
|
|
||||||
* x: Print the argument as an hexadecimal integer
|
|
||||||
* s: Print the string pointed to by the argument
|
|
||||||
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
|
|
||||||
*/
|
|
||||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
|
|
||||||
int r;
|
|
||||||
va_list ParamList;
|
|
||||||
|
|
||||||
va_start(ParamList, sFormat);
|
|
||||||
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
|
|
||||||
va_end(ParamList);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
/*************************** End of file ****************************/
|
|
||||||
18
linker/esp32.extram.bss.ld
Normal file
18
linker/esp32.extram.bss.ld
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* This section is only included if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
|
is set, to link some sections to BSS in PSRAM */
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/
|
||||||
|
.ext_ram.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
_ext_ram_bss_start = ABSOLUTE(.);
|
||||||
|
*(.ext_ram.bss*)
|
||||||
|
*libnet80211.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||||
|
*libpp.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||||
|
*liblwip.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||||
|
*libbt.a:(EXCLUDE_FILE (libbtdm_app.a) .dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ext_ram_bss_end = ABSOLUTE(.);
|
||||||
|
} > extern_ram_seg
|
||||||
|
}
|
||||||
46
linker/nrf52840_s140_sim832.ld
Normal file
46
linker/nrf52840_s140_sim832.ld
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* Linker script to configure memory regions.
|
||||||
|
|
||||||
|
geeksville: modified this to simulate a nrf52832 but with a sd140 soft device. So I can
|
||||||
|
see how the memory footprint works on this lower end CPU. Note: to work with sd140 in my bootloader
|
||||||
|
I need to start ram at 0x6000 (instead of the correct 0x3600 for sd132) - so I have less
|
||||||
|
RAM available than on a real 832.
|
||||||
|
*/
|
||||||
|
|
||||||
|
SEARCH_DIR(.)
|
||||||
|
GROUP(-lgcc -lc -lnosys)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x6D000 - 0x26000
|
||||||
|
/* FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 */
|
||||||
|
|
||||||
|
/* SRAM required by S132 depend on
|
||||||
|
* - Attribute Table Size
|
||||||
|
* - Vendor UUID count
|
||||||
|
* - Max ATT MTU
|
||||||
|
* - Concurrent connection peripheral + central + secure links
|
||||||
|
* - Event Len, HVN queue, Write CMD queue
|
||||||
|
*/
|
||||||
|
/* RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 */
|
||||||
|
RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20010000 - 0x20006000
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
.svc_data :
|
||||||
|
{
|
||||||
|
PROVIDE(__start_svc_data = .);
|
||||||
|
KEEP(*(.svc_data))
|
||||||
|
PROVIDE(__stop_svc_data = .);
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.fs_data :
|
||||||
|
{
|
||||||
|
PROVIDE(__start_fs_data = .);
|
||||||
|
KEEP(*(.fs_data))
|
||||||
|
PROVIDE(__stop_fs_data = .);
|
||||||
|
} > RAM
|
||||||
|
} INSERT AFTER .data;
|
||||||
|
|
||||||
|
INCLUDE "nrf52_common.ld"
|
||||||
117
platformio.ini
117
platformio.ini
@@ -17,12 +17,12 @@ default_envs = tbeam ; Note: the github actions CI test build can't yet build NR
|
|||||||
; REQUIRED environment variables - if not set the specified default will be sued
|
; REQUIRED environment variables - if not set the specified default will be sued
|
||||||
; The following environment variables must be set in the shell if you'd like to override them.
|
; The following environment variables must be set in the shell if you'd like to override them.
|
||||||
; They are used in this ini file as systenv.VARNAME, so in your shell do export "VARNAME=fish"
|
; They are used in this ini file as systenv.VARNAME, so in your shell do export "VARNAME=fish"
|
||||||
; HW_VERSION (default US)
|
; COUNTRY (default US), i.e. "export COUNTRY=EU865"
|
||||||
; APP_VERSION (default emptystring)
|
; APP_VERSION (default emptystring)
|
||||||
; HW_VERSION (default emptystring)
|
; HW_VERSION (default emptystring)
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
platform = espressif32
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
; customize the partition table
|
; customize the partition table
|
||||||
@@ -31,7 +31,7 @@ board_build.partitions = partition-table.csv
|
|||||||
|
|
||||||
; note: we add src to our include search path so that lmic_project_config can override
|
; note: we add src to our include search path so that lmic_project_config can override
|
||||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||||
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Ilib/nanopb/include -Os -Wl,-Map,.pio/build/output.map
|
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Os -Wl,-Map,.pio/build/output.map
|
||||||
-DAXP_DEBUG_PORT=Serial
|
-DAXP_DEBUG_PORT=Serial
|
||||||
-DHW_VERSION_${sysenv.COUNTRY}
|
-DHW_VERSION_${sysenv.COUNTRY}
|
||||||
-DAPP_VERSION=${sysenv.APP_VERSION}
|
-DAPP_VERSION=${sysenv.APP_VERSION}
|
||||||
@@ -51,6 +51,7 @@ build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Ilib/nanopb/incl
|
|||||||
; the default is esptool
|
; the default is esptool
|
||||||
; upload_protocol = esp-prog
|
; upload_protocol = esp-prog
|
||||||
|
|
||||||
|
; monitor_speed = 115200
|
||||||
monitor_speed = 921600
|
monitor_speed = 921600
|
||||||
|
|
||||||
# debug_tool = esp-prog
|
# debug_tool = esp-prog
|
||||||
@@ -68,22 +69,28 @@ debug_tool = jlink
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||||
SPI
|
SPI
|
||||||
; 1260 ; OneButton - not used yet
|
1260 ; OneButton library for non-blocking button debounce
|
||||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||||
https://github.com/meshtastic/arduino-fsm.git
|
https://github.com/meshtastic/arduino-fsm.git
|
||||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||||
https://github.com/meshtastic/RadioLib.git
|
https://github.com/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f
|
||||||
|
https://github.com/meshtastic/TinyGPSPlus.git
|
||||||
|
|
||||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||||
[esp32_base]
|
[esp32_base]
|
||||||
|
platform = espressif32
|
||||||
src_filter =
|
src_filter =
|
||||||
${env.src_filter} -<nrf52/>
|
${env.src_filter} -<nrf52/>
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
debug_init_break = tbreak setup
|
debug_init_break = tbreak setup
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags} -Wall -Wextra
|
${env.build_flags} -Wall -Wextra -Isrc/esp32 -mfix-esp32-psram-cache-issue
|
||||||
|
# Hmm - this doesn't work yet
|
||||||
|
# board_build.ldscript = linker/esp32.extram.bss.ld
|
||||||
lib_ignore = segger_rtt
|
lib_ignore = segger_rtt
|
||||||
|
platform_packages =
|
||||||
|
framework-arduinoespressif32 @ https://github.com/meshtastic/arduino-esp32.git#71ed4002c953d8c87f44ed27e34fe0735f99013e
|
||||||
|
|
||||||
; The 1.0 release of the TBEAM board
|
; The 1.0 release of the TBEAM board
|
||||||
[env:tbeam]
|
[env:tbeam]
|
||||||
@@ -91,61 +98,117 @@ extends = esp32_base
|
|||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
AXP202X_Library
|
https://github.com/meshtastic/AXP202X_Library.git
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags} -D TBEAM_V10
|
${esp32_base.build_flags} -D TBEAM_V10
|
||||||
|
|
||||||
; The original TBEAM board without the AXP power chip and a few other changes
|
; The original TBEAM board without the AXP power chip and a few other changes
|
||||||
; Note: I've heard reports this didn't work. Disabled until someone with a 0.7 can test and debug.
|
; Note: I've heard reports this didn't work. Disabled until someone with a 0.7 can test and debug.
|
||||||
;[env:tbeam0.7]
|
[env:tbeam0.7]
|
||||||
;extends = esp32_base
|
extends = esp32_base
|
||||||
;board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
;build_flags =
|
build_flags =
|
||||||
; ${esp32_base.build_flags} -D TBEAM_V07
|
${esp32_base.build_flags} -D TBEAM_V07
|
||||||
|
|
||||||
[env:heltec]
|
[env:heltec]
|
||||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = heltec_wifi_lora_32_V2
|
board = heltec_wifi_lora_32_V2
|
||||||
|
|
||||||
[env:ttgo-lora32-v1]
|
[env:tlora-v1]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags} -D TTGO_LORA_V1
|
${esp32_base.build_flags} -D TLORA_V1
|
||||||
|
|
||||||
; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works
|
; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works
|
||||||
[env:ttgo-lora32-v2]
|
[env:tlora-v2]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags} -D TTGO_LORA_V2
|
${esp32_base.build_flags} -D TLORA_V2
|
||||||
|
|
||||||
|
[env:tlora-v2-1-1.6]
|
||||||
|
extends = esp32_base
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags} -D TLORA_V2_1_16
|
||||||
|
|
||||||
; The NRF52840-dk development board
|
; The Heltec Cubecell plus
|
||||||
[env:nrf52dk]
|
; IMPORTANT NOTE: This target doesn't yet work and probably won't ever work. I'm keeping it around for now.
|
||||||
platform = nordicnrf52
|
; For more details see my post in the forum.
|
||||||
board = ppr
|
[env:cubecellplus]
|
||||||
framework = arduino
|
platform = https://github.com/HelTecAutomation/platform-asrmicro650x.git ; we use top-of-tree because stable version has too many bugs - asrmicro650x
|
||||||
|
board = cubecell_board_plus
|
||||||
|
; FIXME, bug in cubecell arduino - they are supposed to set ARDUINO
|
||||||
|
build_flags = ${env.build_flags} -DARDUINO=100 -Isrc/cubecell
|
||||||
|
src_filter =
|
||||||
|
${env.src_filter} -<esp32/> -<nrf52/>
|
||||||
|
|
||||||
|
; Common settings for NRF52 based targets
|
||||||
|
[nrf52_base]
|
||||||
|
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||||
|
; platform = nordicnrf52
|
||||||
|
platform = https://github.com/meshtastic/platform-nordicnrf52.git#62d185fe61b6c84c554046106529b4fd8f155e2c
|
||||||
debug_tool = jlink
|
debug_tool = jlink
|
||||||
build_type = debug ; I'm debugging with ICE a lot now
|
build_type = debug ; I'm debugging with ICE a lot now
|
||||||
|
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags} -Wno-unused-variable -Isrc/nrf52
|
${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
|
||||||
|
;-DCFG_DEBUG=3
|
||||||
src_filter =
|
src_filter =
|
||||||
${env.src_filter} -<esp32/>
|
${env.src_filter} -<esp32/>
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
||||||
lib_deps =
|
|
||||||
${env.lib_deps}
|
|
||||||
UC1701
|
|
||||||
https://github.com/meshtastic/BQ25703A.git
|
|
||||||
monitor_port = /dev/ttyACM1
|
monitor_port = /dev/ttyACM1
|
||||||
|
|
||||||
debug_extra_cmds =
|
debug_extra_cmds =
|
||||||
source gdbinit
|
source gdbinit
|
||||||
|
|
||||||
|
; after programming the flash, reset the initial PC
|
||||||
|
; debug_load_cmds = load
|
||||||
|
|
||||||
; Set initial breakpoint (defaults to main)
|
; Set initial breakpoint (defaults to main)
|
||||||
debug_init_break =
|
debug_init_break =
|
||||||
;debug_init_break = tbreak loop
|
;debug_init_break = tbreak loop
|
||||||
;debug_init_break = tbreak Reset_Handler
|
;debug_init_break = tbreak Reset_Handler
|
||||||
|
|
||||||
|
; The NRF52840-dk development board
|
||||||
|
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||||
|
[env:nrf52840dk]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = nrf52840_dk
|
||||||
|
|
||||||
|
; The NRF52840-dk development board, but @geeksville's board - which has a busted oscilliator
|
||||||
|
[env:nrf52840dk-geeksville]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = nrf52840_dk_modified
|
||||||
|
|
||||||
|
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||||
|
[env:feather_nrf52832]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = adafruit_feather_nrf52832
|
||||||
|
|
||||||
|
[env:rak815]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = rak815
|
||||||
|
debug_tool = jlink
|
||||||
|
upload_protocol = jlink
|
||||||
|
monitor_port = /dev/ttyUSB0
|
||||||
|
; this board's serial chip can only run at 115200, not faster
|
||||||
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
# For experimenting with RAM sizes
|
||||||
|
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
|
||||||
|
|
||||||
|
; The PPR board
|
||||||
|
[env:ppr]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = ppr
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
UC1701
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
proto
2
proto
Submodule proto updated: bd002e5a14...ab281311c4
1
sdk-nrfxlib
Submodule
1
sdk-nrfxlib
Submodule
Submodule sdk-nrfxlib added at 17e8453553
16
src/BluetoothCommon.h
Normal file
16
src/BluetoothCommon.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common lib functions for all platforms that have bluetooth
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
||||||
|
|
||||||
|
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||||
|
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
|
||||||
|
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||||
|
|
||||||
|
/// Given a level between 0-100, update the BLE attribute
|
||||||
|
void updateBatteryLevel(uint8_t level);
|
||||||
218
src/GPS.cpp
218
src/GPS.cpp
@@ -1,218 +0,0 @@
|
|||||||
|
|
||||||
#include "GPS.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "time.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#ifdef GPS_RX_PIN
|
|
||||||
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
|
||||||
#else
|
|
||||||
// Assume NRF52
|
|
||||||
HardwareSerial &_serial_gps = Serial1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
|
|
||||||
|
|
||||||
GPS gps;
|
|
||||||
|
|
||||||
// stuff that really should be in in the instance instead...
|
|
||||||
static uint32_t
|
|
||||||
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
|
||||||
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
|
||||||
|
|
||||||
static bool wantNewLocation = true;
|
|
||||||
|
|
||||||
GPS::GPS() : PeriodicTask() {}
|
|
||||||
|
|
||||||
void GPS::setup()
|
|
||||||
{
|
|
||||||
PeriodicTask::setup();
|
|
||||||
|
|
||||||
readFromRTC(); // read the main CPU RTC at first
|
|
||||||
|
|
||||||
#ifdef GPS_RX_PIN
|
|
||||||
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
|
||||||
#else
|
|
||||||
_serial_gps.begin(GPS_BAUDRATE);
|
|
||||||
#endif
|
|
||||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
|
||||||
// ublox.enableDebugging(Serial);
|
|
||||||
|
|
||||||
// note: the lib's implementation has the wrong docs for what the return val is
|
|
||||||
// it is not a bool, it returns zero for success
|
|
||||||
isConnected = ublox.begin(_serial_gps);
|
|
||||||
|
|
||||||
// try a second time, the ublox lib serial parsing is buggy?
|
|
||||||
if (!isConnected)
|
|
||||||
isConnected = ublox.begin(_serial_gps);
|
|
||||||
|
|
||||||
if (isConnected) {
|
|
||||||
DEBUG_MSG("Connected to GPS successfully\n");
|
|
||||||
|
|
||||||
bool factoryReset = false;
|
|
||||||
bool ok;
|
|
||||||
if (factoryReset) {
|
|
||||||
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
|
|
||||||
// GPS_TX connected)
|
|
||||||
ublox.factoryReset();
|
|
||||||
delay(2000);
|
|
||||||
isConnected = ublox.begin(_serial_gps);
|
|
||||||
DEBUG_MSG("Factory reset success=%d\n", isConnected);
|
|
||||||
if (isConnected) {
|
|
||||||
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
|
||||||
assert(ok);
|
|
||||||
ok = ublox.setNavigationFrequency(1, 500); // Produce 4x/sec to keep the amount of time we stall in getPVT low
|
|
||||||
assert(ok);
|
|
||||||
// ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
|
||||||
// assert(ok);
|
|
||||||
// ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
|
|
||||||
// assert(ok);
|
|
||||||
ok = ublox.powerSaveMode(); // use power save mode
|
|
||||||
assert(ok);
|
|
||||||
}
|
|
||||||
ok = ublox.saveConfiguration(3000);
|
|
||||||
assert(ok);
|
|
||||||
} else {
|
|
||||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
|
||||||
// assume NEMA at 9600 baud.
|
|
||||||
DEBUG_MSG("ERROR: No bidirectional GPS found, hoping that it still might work\n");
|
|
||||||
|
|
||||||
// tell lib, we are expecting the module to send PVT messages by itself to our Rx pin
|
|
||||||
// you can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call
|
|
||||||
// checkUblox cyclically)
|
|
||||||
ublox.assumeAutoPVT(true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPS::readFromRTC()
|
|
||||||
{
|
|
||||||
struct timeval tv; /* btw settimeofday() is helpfull here too*/
|
|
||||||
|
|
||||||
if (!gettimeofday(&tv, NULL)) {
|
|
||||||
uint32_t now = millis();
|
|
||||||
|
|
||||||
DEBUG_MSG("Read RTC time as %ld (cur millis %u) valid=%d\n", tv.tv_sec, now, timeSetFromGPS);
|
|
||||||
timeStartMsec = now;
|
|
||||||
zeroOffsetSecs = tv.tv_sec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
|
||||||
void GPS::perhapsSetRTC(const struct timeval *tv)
|
|
||||||
{
|
|
||||||
if (!timeSetFromGPS) {
|
|
||||||
timeSetFromGPS = true;
|
|
||||||
DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec);
|
|
||||||
#ifndef NO_ESP32
|
|
||||||
settimeofday(tv, NULL);
|
|
||||||
#else
|
|
||||||
DEBUG_MSG("ERROR TIME SETTING NOT IMPLEMENTED!\n");
|
|
||||||
#endif
|
|
||||||
readFromRTC();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
uint32_t GPS::getTime()
|
|
||||||
{
|
|
||||||
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GPS::getValidTime()
|
|
||||||
{
|
|
||||||
return timeSetFromGPS ? getTime() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if we think the board can enter deep or light sleep now (we might be trying to get a GPS lock)
|
|
||||||
bool GPS::canSleep()
|
|
||||||
{
|
|
||||||
return true; // we leave GPS on during sleep now, so sleep is okay !wantNewLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
|
||||||
void GPS::prepareSleep()
|
|
||||||
{
|
|
||||||
if (isConnected)
|
|
||||||
ublox.powerOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPS::doTask()
|
|
||||||
{
|
|
||||||
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix
|
|
||||||
|
|
||||||
if (isConnected) {
|
|
||||||
// Consume all characters that have arrived
|
|
||||||
|
|
||||||
// getPVT automatically calls checkUblox
|
|
||||||
ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
|
|
||||||
|
|
||||||
// If we don't have a fix (a quick check), don't try waiting for a solution)
|
|
||||||
// Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions
|
|
||||||
// turn off for now
|
|
||||||
// fixtype = ublox.getFixType();
|
|
||||||
DEBUG_MSG("fix type %d\n", fixtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG_MSG("sec %d\n", ublox.getSecond());
|
|
||||||
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
|
|
||||||
|
|
||||||
// any fix that has time
|
|
||||||
if (!timeSetFromGPS && ublox.getT()) {
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
/* Convert to unix time
|
|
||||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
|
|
||||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
|
||||||
*/
|
|
||||||
struct tm t;
|
|
||||||
t.tm_sec = ublox.getSecond();
|
|
||||||
t.tm_min = ublox.getMinute();
|
|
||||||
t.tm_hour = ublox.getHour();
|
|
||||||
t.tm_mday = ublox.getDay();
|
|
||||||
t.tm_mon = ublox.getMonth() - 1;
|
|
||||||
t.tm_year = ublox.getYear() - 1900;
|
|
||||||
t.tm_isdst = false;
|
|
||||||
time_t res = mktime(&t);
|
|
||||||
tv.tv_sec = res;
|
|
||||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
|
||||||
|
|
||||||
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
|
||||||
if (t.tm_year < 0 || t.tm_year >= 300)
|
|
||||||
DEBUG_MSG("Ignoring invalid GPS time\n");
|
|
||||||
else
|
|
||||||
perhapsSetRTC(&tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
|
||||||
{
|
|
||||||
// we only notify if position has changed
|
|
||||||
latitude = ublox.getLatitude() * 1e-7;
|
|
||||||
longitude = ublox.getLongitude() * 1e-7;
|
|
||||||
altitude = ublox.getAltitude() / 1000; // in mm convert to meters
|
|
||||||
DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude, longitude, altitude);
|
|
||||||
|
|
||||||
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0
|
|
||||||
if (hasValidLocation) {
|
|
||||||
wantNewLocation = false;
|
|
||||||
notifyObservers(NULL);
|
|
||||||
// ublox.powerOff();
|
|
||||||
}
|
|
||||||
} else // we didn't get a location update, go back to sleep and hope the characters show up
|
|
||||||
wantNewLocation = true;
|
|
||||||
|
|
||||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over
|
|
||||||
// the serial
|
|
||||||
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPS::startLock()
|
|
||||||
{
|
|
||||||
DEBUG_MSG("Looking for GPS lock\n");
|
|
||||||
wantNewLocation = true;
|
|
||||||
setPeriod(1);
|
|
||||||
}
|
|
||||||
56
src/GPS.h
56
src/GPS.h
@@ -1,56 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Observer.h"
|
|
||||||
#include "PeriodicTask.h"
|
|
||||||
#include "SparkFun_Ublox_Arduino_Library.h"
|
|
||||||
#include "sys/time.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
|
||||||
*
|
|
||||||
* When new data is available it will notify observers.
|
|
||||||
*/
|
|
||||||
class GPS : public PeriodicTask, public Observable<void *>
|
|
||||||
{
|
|
||||||
SFE_UBLOX_GPS ublox;
|
|
||||||
|
|
||||||
public:
|
|
||||||
double latitude, longitude;
|
|
||||||
uint32_t altitude;
|
|
||||||
bool isConnected; // Do we have a GPS we are talking to
|
|
||||||
|
|
||||||
GPS();
|
|
||||||
|
|
||||||
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
|
|
||||||
uint32_t getTime();
|
|
||||||
|
|
||||||
/// Return time since 1970 in secs. If we don't have a GPS lock return zero
|
|
||||||
uint32_t getValidTime();
|
|
||||||
|
|
||||||
void setup();
|
|
||||||
|
|
||||||
|
|
||||||
virtual void doTask();
|
|
||||||
|
|
||||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
|
||||||
void perhapsSetRTC(const struct timeval *tv);
|
|
||||||
|
|
||||||
/// Returns true if we think the board can enter deep or light sleep now (we might be trying to get a GPS lock)
|
|
||||||
bool canSleep();
|
|
||||||
|
|
||||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
|
||||||
void prepareSleep();
|
|
||||||
|
|
||||||
/// Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
|
||||||
void startLock();
|
|
||||||
|
|
||||||
/// Returns ture if we have acquired GPS lock.
|
|
||||||
bool hasLock() const { return hasValidLocation; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void readFromRTC();
|
|
||||||
|
|
||||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
|
||||||
};
|
|
||||||
|
|
||||||
extern GPS gps;
|
|
||||||
126
src/GPSStatus.h
Normal file
126
src/GPSStatus.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Status.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
namespace meshtastic {
|
||||||
|
|
||||||
|
/// Describes the state of the GPS system.
|
||||||
|
class GPSStatus : public Status
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
CallbackObserver<GPSStatus, const GPSStatus *> statusObserver = CallbackObserver<GPSStatus, const GPSStatus *>(this, &GPSStatus::updateStatus);
|
||||||
|
|
||||||
|
bool hasLock = false; // default to false, until we complete our first read
|
||||||
|
bool isConnected = false; // Do we have a GPS we are talking to
|
||||||
|
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
|
||||||
|
int32_t altitude = 0;
|
||||||
|
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs scaling before use)
|
||||||
|
uint32_t heading = 0;
|
||||||
|
uint32_t numSatellites = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
GPSStatus() {
|
||||||
|
statusType = STATUS_TYPE_GPS;
|
||||||
|
}
|
||||||
|
GPSStatus( bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop, uint32_t heading, uint32_t numSatellites ) : Status()
|
||||||
|
{
|
||||||
|
this->hasLock = hasLock;
|
||||||
|
this->isConnected = isConnected;
|
||||||
|
this->latitude = latitude;
|
||||||
|
this->longitude = longitude;
|
||||||
|
this->altitude = altitude;
|
||||||
|
this->dop = dop;
|
||||||
|
this->heading = heading;
|
||||||
|
this->numSatellites = numSatellites;
|
||||||
|
}
|
||||||
|
GPSStatus(const GPSStatus &);
|
||||||
|
GPSStatus &operator=(const GPSStatus &);
|
||||||
|
|
||||||
|
void observe(Observable<const GPSStatus *> *source)
|
||||||
|
{
|
||||||
|
statusObserver.observe(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getHasLock() const
|
||||||
|
{
|
||||||
|
return hasLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getIsConnected() const
|
||||||
|
{
|
||||||
|
return isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getLatitude() const
|
||||||
|
{
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getLongitude() const
|
||||||
|
{
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getAltitude() const
|
||||||
|
{
|
||||||
|
return altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getDOP() const
|
||||||
|
{
|
||||||
|
return dop;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getHeading() const
|
||||||
|
{
|
||||||
|
return heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getNumSatellites() const
|
||||||
|
{
|
||||||
|
return numSatellites;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const GPSStatus *newStatus) const
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
newStatus->hasLock != hasLock ||
|
||||||
|
newStatus->isConnected != isConnected ||
|
||||||
|
newStatus->latitude != latitude ||
|
||||||
|
newStatus->longitude != longitude ||
|
||||||
|
newStatus->altitude != altitude ||
|
||||||
|
newStatus->dop != dop ||
|
||||||
|
newStatus->heading != heading ||
|
||||||
|
newStatus->numSatellites != numSatellites
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int updateStatus(const GPSStatus *newStatus) {
|
||||||
|
// Only update the status if values have actually changed
|
||||||
|
bool isDirty;
|
||||||
|
{
|
||||||
|
isDirty = matches(newStatus);
|
||||||
|
initialized = true;
|
||||||
|
hasLock = newStatus->hasLock;
|
||||||
|
isConnected = newStatus->isConnected;
|
||||||
|
latitude = newStatus->latitude;
|
||||||
|
longitude = newStatus->longitude;
|
||||||
|
altitude = newStatus->altitude;
|
||||||
|
dop = newStatus->dop;
|
||||||
|
heading = newStatus->heading;
|
||||||
|
numSatellites = newStatus->numSatellites;
|
||||||
|
}
|
||||||
|
if(isDirty) {
|
||||||
|
DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%f, heading=%f, sats=%d\n", latitude * 1e-7, longitude * 1e-7, altitude, dop * 1e-2, heading * 1e-5, numSatellites);
|
||||||
|
onNewStatus.notifyObservers(this);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern meshtastic::GPSStatus *gpsStatus;
|
||||||
83
src/NodeStatus.h
Normal file
83
src/NodeStatus.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Status.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
namespace meshtastic {
|
||||||
|
|
||||||
|
/// Describes the state of the NodeDB system.
|
||||||
|
class NodeStatus : public Status
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
CallbackObserver<NodeStatus, const NodeStatus *> statusObserver = CallbackObserver<NodeStatus, const NodeStatus *>(this, &NodeStatus::updateStatus);
|
||||||
|
|
||||||
|
uint8_t numOnline = 0;
|
||||||
|
uint8_t numTotal = 0;
|
||||||
|
|
||||||
|
uint8_t lastNumTotal = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool forceUpdate = false;
|
||||||
|
|
||||||
|
NodeStatus() {
|
||||||
|
statusType = STATUS_TYPE_NODE;
|
||||||
|
}
|
||||||
|
NodeStatus( uint8_t numOnline, uint8_t numTotal, bool forceUpdate = false ) : Status()
|
||||||
|
{
|
||||||
|
this->forceUpdate = forceUpdate;
|
||||||
|
this->numOnline = numOnline;
|
||||||
|
this->numTotal = numTotal;
|
||||||
|
}
|
||||||
|
NodeStatus(const NodeStatus &);
|
||||||
|
NodeStatus &operator=(const NodeStatus &);
|
||||||
|
|
||||||
|
void observe(Observable<const NodeStatus *> *source)
|
||||||
|
{
|
||||||
|
statusObserver.observe(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getNumOnline() const
|
||||||
|
{
|
||||||
|
return numOnline;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getNumTotal() const
|
||||||
|
{
|
||||||
|
return numTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getLastNumTotal() const
|
||||||
|
{
|
||||||
|
return lastNumTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const NodeStatus *newStatus) const
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
newStatus->getNumOnline() != numOnline ||
|
||||||
|
newStatus->getNumTotal() != numTotal
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int updateStatus(const NodeStatus *newStatus) {
|
||||||
|
// Only update the status if values have actually changed
|
||||||
|
lastNumTotal = numTotal;
|
||||||
|
bool isDirty;
|
||||||
|
{
|
||||||
|
isDirty = matches(newStatus);
|
||||||
|
initialized = true;
|
||||||
|
numOnline = newStatus->getNumOnline();
|
||||||
|
numTotal = newStatus->getNumTotal();
|
||||||
|
}
|
||||||
|
if(isDirty || newStatus->forceUpdate) {
|
||||||
|
DEBUG_MSG("Node status update: %d online, %d total\n", numOnline, numTotal);
|
||||||
|
onNewStatus.notifyObservers(this);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern meshtastic::NodeStatus *nodeStatus;
|
||||||
49
src/OSTimer.cpp
Normal file
49
src/OSTimer.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "OSTimer.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a callback to run. The callback must _not_ block, though it is called from regular thread level (not ISR)
|
||||||
|
*
|
||||||
|
* NOTE! xTimerPend... seems to ignore the time passed in on ESP32 and on NRF52
|
||||||
|
* The reason this didn't work is bcause xTimerPednFunctCall really isn't a timer function at all - it just means run the callback
|
||||||
|
* from the timer thread the next time you have spare cycles.
|
||||||
|
*
|
||||||
|
* @return true if successful, false if the timer fifo is too full.
|
||||||
|
|
||||||
|
bool scheduleOSCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec)
|
||||||
|
{
|
||||||
|
return xTimerPendFunctionCall(callback, param1, param2, pdMS_TO_TICKS(delayMsec));
|
||||||
|
} */
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
|
||||||
|
// Super skanky quick hack to use hardware timers of the ESP32
|
||||||
|
static hw_timer_t *timer;
|
||||||
|
static PendableFunction tCallback;
|
||||||
|
static void *tParam1;
|
||||||
|
static uint32_t tParam2;
|
||||||
|
|
||||||
|
static void IRAM_ATTR onTimer()
|
||||||
|
{
|
||||||
|
(*tCallback)(tParam1, tParam2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec)
|
||||||
|
{
|
||||||
|
if (!timer) {
|
||||||
|
timer = timerBegin(0, 80, true); // one usec per tick (main clock is 80MhZ on ESP32)
|
||||||
|
assert(timer);
|
||||||
|
timerAttachInterrupt(timer, &onTimer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
tCallback = callback;
|
||||||
|
tParam1 = param1;
|
||||||
|
tParam2 = param2;
|
||||||
|
|
||||||
|
timerAlarmWrite(timer, delayMsec * 1000L, false); // Do not reload, we want it to be a single shot timer
|
||||||
|
timerRestart(timer);
|
||||||
|
timerAlarmEnable(timer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
8
src/OSTimer.h
Normal file
8
src/OSTimer.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
typedef void (*PendableFunction)(void *pvParameter1, uint32_t ulParameter2);
|
||||||
|
|
||||||
|
/// Uses a hardware timer, but calls the handler in _interrupt_ context
|
||||||
|
bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec);
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#include "PeriodicTask.h"
|
|
||||||
#include "Periodic.h"
|
|
||||||
PeriodicScheduler periodicScheduler;
|
|
||||||
|
|
||||||
PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod) {}
|
|
||||||
|
|
||||||
void PeriodicTask::setup()
|
|
||||||
{
|
|
||||||
periodicScheduler.schedule(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// call this from loop
|
|
||||||
void PeriodicScheduler::loop()
|
|
||||||
{
|
|
||||||
meshtastic::LockGuard lg(&lock);
|
|
||||||
|
|
||||||
uint32_t now = millis();
|
|
||||||
for (auto t : tasks) {
|
|
||||||
if (t->period && (now - t->lastMsec) >= t->period) {
|
|
||||||
|
|
||||||
t->doTask();
|
|
||||||
t->lastMsec = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeriodicScheduler::schedule(PeriodicTask *t)
|
|
||||||
{
|
|
||||||
meshtastic::LockGuard lg(&lock);
|
|
||||||
tasks.insert(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeriodicScheduler::unschedule(PeriodicTask *t)
|
|
||||||
{
|
|
||||||
meshtastic::LockGuard lg(&lock);
|
|
||||||
tasks.erase(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Periodic::doTask()
|
|
||||||
{
|
|
||||||
uint32_t p = callback();
|
|
||||||
setPeriod(p);
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "lock.h"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
class PeriodicTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs all PeriodicTasks in the system.
|
|
||||||
*
|
|
||||||
* Currently called from main loop() but eventually should be its own thread blocked on a freertos timer.
|
|
||||||
*/
|
|
||||||
class PeriodicScheduler
|
|
||||||
{
|
|
||||||
friend class PeriodicTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This really should be some form of heap, and when the period gets changed on a task it should get
|
|
||||||
* rescheduled in that heap. Currently it is just a dumb array and everytime we run loop() we check
|
|
||||||
* _every_ tasks. If it was a heap we'd only have to check the first task.
|
|
||||||
*/
|
|
||||||
std::unordered_set<PeriodicTask *> tasks;
|
|
||||||
|
|
||||||
// Protects the above variables.
|
|
||||||
meshtastic::Lock lock;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Run any next tasks which are due for execution
|
|
||||||
void loop();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void schedule(PeriodicTask *t);
|
|
||||||
void unschedule(PeriodicTask *t);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PeriodicScheduler periodicScheduler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base class for tasks that want their doTask() method invoked periodically
|
|
||||||
*
|
|
||||||
* FIXME: currently just syntatic sugar for polling in loop (you must call .loop), but eventually
|
|
||||||
* generalize with the freertos scheduler so we can save lots of power by having everything either in
|
|
||||||
* something like this or triggered off of an irq.
|
|
||||||
*/
|
|
||||||
class PeriodicTask
|
|
||||||
{
|
|
||||||
friend class PeriodicScheduler;
|
|
||||||
|
|
||||||
uint32_t lastMsec = 0;
|
|
||||||
uint32_t period = 1; // call soon after creation
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~PeriodicTask() { periodicScheduler.unschedule(this); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor (will schedule with the global PeriodicScheduler)
|
|
||||||
*/
|
|
||||||
PeriodicTask(uint32_t initialPeriod = 1);
|
|
||||||
|
|
||||||
/** MUST be be called once at startup (but after threading is running - i.e. not from a constructor)
|
|
||||||
*/
|
|
||||||
void setup();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a new period in msecs (can be called from doTask or elsewhere and the scheduler will cope)
|
|
||||||
* While zero this task is disabled and will not run
|
|
||||||
*/
|
|
||||||
void setPeriod(uint32_t p) { period = p; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Syntatic sugar for suspending tasks
|
|
||||||
*/
|
|
||||||
void disable() { setPeriod(0); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void doTask() = 0;
|
|
||||||
};
|
|
||||||
179
src/Power.cpp
Normal file
179
src/Power.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include "power.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#ifdef TBEAM_V10
|
||||||
|
|
||||||
|
// FIXME. nasty hack cleanup how we load axp192
|
||||||
|
#undef AXP192_SLAVE_ADDRESS
|
||||||
|
#include "axp20x.h"
|
||||||
|
AXP20X_Class axp;
|
||||||
|
bool pmu_irq = false;
|
||||||
|
|
||||||
|
Power *power;
|
||||||
|
|
||||||
|
bool Power::setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
axp192Init();
|
||||||
|
concurrency::PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
|
||||||
|
setPeriod(1);
|
||||||
|
|
||||||
|
return axp192_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads power status to powerStatus singleton.
|
||||||
|
//
|
||||||
|
// TODO(girts): move this and other axp stuff to power.h/power.cpp.
|
||||||
|
void Power::readPowerStatus()
|
||||||
|
{
|
||||||
|
bool hasBattery = axp.isBatteryConnect();
|
||||||
|
int batteryVoltageMv = 0;
|
||||||
|
uint8_t batteryChargePercent = 0;
|
||||||
|
if (hasBattery) {
|
||||||
|
batteryVoltageMv = axp.getBattVoltage();
|
||||||
|
// If the AXP192 returns a valid battery percentage, use it
|
||||||
|
if (axp.getBattPercentage() >= 0) {
|
||||||
|
batteryChargePercent = axp.getBattPercentage();
|
||||||
|
} else {
|
||||||
|
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
||||||
|
// In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in power.h
|
||||||
|
batteryChargePercent = clamp((int)(((batteryVoltageMv - BAT_MILLIVOLTS_EMPTY) * 1e2) / (BAT_MILLIVOLTS_FULL - BAT_MILLIVOLTS_EMPTY)), 0, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify any status instances that are observing us
|
||||||
|
const meshtastic::PowerStatus powerStatus = meshtastic::PowerStatus(hasBattery, axp.isVBUSPlug(), axp.isChargeing(), batteryVoltageMv, batteryChargePercent);
|
||||||
|
newStatus.notifyObservers(&powerStatus);
|
||||||
|
|
||||||
|
// If we have a battery at all and it is less than 10% full, force deep sleep
|
||||||
|
if (powerStatus.getHasBattery() && !powerStatus.getHasUSB() &&
|
||||||
|
axp.getBattVoltage() < MIN_BAT_MILLIVOLTS)
|
||||||
|
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Power::doTask()
|
||||||
|
{
|
||||||
|
readPowerStatus();
|
||||||
|
|
||||||
|
// Only read once every 20 seconds once the power status for the app has been initialized
|
||||||
|
if(statusHandler && statusHandler->isInitialized())
|
||||||
|
setPeriod(1000 * 20);
|
||||||
|
}
|
||||||
|
#endif // TBEAM_V10
|
||||||
|
|
||||||
|
#ifdef AXP192_SLAVE_ADDRESS
|
||||||
|
/**
|
||||||
|
* Init the power manager chip
|
||||||
|
*
|
||||||
|
* axp192 power
|
||||||
|
DCDC1 0.7-3.5V @ 1200mA max -> OLED // If you turn this off you'll lose comms to the axp192 because the OLED and the axp192
|
||||||
|
share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this on!) LDO1
|
||||||
|
30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
|
||||||
|
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
|
||||||
|
*/
|
||||||
|
void Power::axp192Init()
|
||||||
|
{
|
||||||
|
if (axp192_found) {
|
||||||
|
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
||||||
|
DEBUG_MSG("AXP192 Begin PASS\n");
|
||||||
|
|
||||||
|
// axp.setChgLEDMode(LED_BLINK_4HZ);
|
||||||
|
DEBUG_MSG("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("----------------------------------------\n");
|
||||||
|
|
||||||
|
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA radio
|
||||||
|
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS main power
|
||||||
|
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
|
||||||
|
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
|
||||||
|
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
|
||||||
|
axp.setDCDC1Voltage(3300); // for the OLED power
|
||||||
|
|
||||||
|
DEBUG_MSG("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
||||||
|
DEBUG_MSG("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
||||||
|
|
||||||
|
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1320MA); // actual limit (in HW) on the tbeam is 450mA
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
// Not connected
|
||||||
|
//val = 0xfc;
|
||||||
|
//axp._writeByte(AXP202_VHTF_CHGSET, 1, &val); // Set temperature protection
|
||||||
|
|
||||||
|
//not used
|
||||||
|
//val = 0x46;
|
||||||
|
//axp._writeByte(AXP202_OFF_CTL, 1, &val); // enable bat detection
|
||||||
|
#endif
|
||||||
|
axp.debugCharging();
|
||||||
|
|
||||||
|
#ifdef PMU_IRQ
|
||||||
|
pinMode(PMU_IRQ, INPUT);
|
||||||
|
attachInterrupt(
|
||||||
|
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
|
||||||
|
|
||||||
|
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
||||||
|
axp.enableIRQ(AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ | AXP202_CHARGING_IRQ |
|
||||||
|
AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_PEK_SHORTPRESS_IRQ,
|
||||||
|
1);
|
||||||
|
|
||||||
|
axp.clearIRQ();
|
||||||
|
#endif
|
||||||
|
readPowerStatus();
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("AXP192 Begin FAIL\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("AXP192 not found\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Power::loop()
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PMU_IRQ
|
||||||
|
if (pmu_irq) {
|
||||||
|
pmu_irq = false;
|
||||||
|
axp.readIRQ();
|
||||||
|
|
||||||
|
DEBUG_MSG("pmu irq!\n");
|
||||||
|
|
||||||
|
if (axp.isChargingIRQ()) {
|
||||||
|
DEBUG_MSG("Battery start charging\n");
|
||||||
|
}
|
||||||
|
if (axp.isChargingDoneIRQ()) {
|
||||||
|
DEBUG_MSG("Battery fully charged\n");
|
||||||
|
}
|
||||||
|
if (axp.isVbusRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("USB unplugged\n");
|
||||||
|
}
|
||||||
|
if (axp.isVbusPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("USB plugged In\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("Battery inserted\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("Battery removed\n");
|
||||||
|
}
|
||||||
|
if (axp.isPEKShortPressIRQ()) {
|
||||||
|
DEBUG_MSG("PEK short button press\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
readPowerStatus();
|
||||||
|
axp.clearIRQ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // T_BEAM_V10
|
||||||
|
|
||||||
|
}
|
||||||
109
src/PowerFSM.cpp
109
src/PowerFSM.cpp
@@ -5,9 +5,10 @@
|
|||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
static void sdsEnter()
|
static void sdsEnter()
|
||||||
{
|
{
|
||||||
@@ -15,7 +16,7 @@ static void sdsEnter()
|
|||||||
|
|
||||||
// Don't deepsleep if we have USB power or if the user as pressed a button recently
|
// Don't deepsleep if we have USB power or if the user as pressed a button recently
|
||||||
// !isUSBPowered <- doesn't work yet because the axp192 isn't letting the battery fully charge when we are awake - FIXME
|
// !isUSBPowered <- doesn't work yet because the axp192 isn't letting the battery fully charge when we are awake - FIXME
|
||||||
if (millis() - lastPressMs > radioConfig.preferences.mesh_sds_timeout_secs)
|
if (timing::millis() - lastPressMs > radioConfig.preferences.mesh_sds_timeout_secs)
|
||||||
{
|
{
|
||||||
doDeepSleep(radioConfig.preferences.sds_secs);
|
doDeepSleep(radioConfig.preferences.sds_secs);
|
||||||
}
|
}
|
||||||
@@ -26,60 +27,73 @@ static void sdsEnter()
|
|||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
static uint32_t secsSlept;
|
||||||
|
|
||||||
static void lsEnter()
|
static void lsEnter()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
||||||
screen.setOn(false);
|
screen.setOn(false);
|
||||||
|
secsSlept = 0; // How long have we been sleeping this time
|
||||||
|
|
||||||
DEBUG_MSG("lsEnter end\n");
|
DEBUG_MSG("lsEnter end\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsIdle()
|
static void lsIdle()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifndef NO_ESP32
|
||||||
uint32_t secsSlept = 0;
|
|
||||||
esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED;
|
esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||||
bool reached_ls_secs = false;
|
|
||||||
|
|
||||||
while (!reached_ls_secs) {
|
// Do we have more sleeping to do?
|
||||||
|
if (secsSlept < radioConfig.preferences.ls_secs) {
|
||||||
// Briefly come out of sleep long enough to blink the led once every few seconds
|
// Briefly come out of sleep long enough to blink the led once every few seconds
|
||||||
uint32_t sleepTime = 5;
|
uint32_t sleepTime = 30;
|
||||||
|
|
||||||
setLed(false); // Never leave led on while in light sleep
|
// If some other service would stall sleep, don't let sleep happen yet
|
||||||
wakeCause = doLightSleep(sleepTime * 1000LL);
|
if (doPreflightSleep()) {
|
||||||
if (wakeCause != ESP_SLEEP_WAKEUP_TIMER)
|
setLed(false); // Never leave led on while in light sleep
|
||||||
break;
|
wakeCause = doLightSleep(sleepTime * 1000LL);
|
||||||
|
|
||||||
setLed(true); // briefly turn on led
|
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
||||||
doLightSleep(1);
|
// Normal case: timer expired, we should just go back to sleep ASAP
|
||||||
if (wakeCause != ESP_SLEEP_WAKEUP_TIMER)
|
|
||||||
break;
|
|
||||||
|
|
||||||
secsSlept += sleepTime;
|
setLed(true); // briefly turn on led
|
||||||
reached_ls_secs = secsSlept >= radioConfig.preferences.ls_secs;
|
wakeCause = doLightSleep(1); // leave led on for 1ms
|
||||||
}
|
|
||||||
setLed(false);
|
|
||||||
|
|
||||||
if (reached_ls_secs) {
|
secsSlept += sleepTime;
|
||||||
// stay in LS mode but let loop check whatever it wants
|
// DEBUG_MSG("sleeping, flash led!\n");
|
||||||
DEBUG_MSG("reached ls_secs, servicing loop()\n");
|
}
|
||||||
} else {
|
if (wakeCause == ESP_SLEEP_WAKEUP_UART) {
|
||||||
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
// Not currently used (because uart triggers in hw have problems)
|
||||||
|
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
||||||
|
} else {
|
||||||
|
// We woke for some other reason (button press, uart, device interrupt)
|
||||||
|
// uint64_t status = esp_sleep_get_ext1_wakeup_status();
|
||||||
|
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
||||||
|
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
bool pressed = !digitalRead(BUTTON_PIN);
|
bool pressed = !digitalRead(BUTTON_PIN);
|
||||||
#else
|
#else
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
#endif
|
#endif
|
||||||
if (pressed) // If we woke because of press, instead generate a PRESS event.
|
if (pressed) // If we woke because of press, instead generate a PRESS event.
|
||||||
{
|
{
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
} else {
|
||||||
|
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
||||||
|
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
// Someone says we can't sleep now, so just save some power by sleeping the CPU for 100ms or so
|
||||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
delay(100);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Time to stop sleeping!
|
||||||
|
setLed(false);
|
||||||
|
DEBUG_MSG("reached ls_secs, servicing loop()\n");
|
||||||
|
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -87,7 +101,7 @@ static void lsIdle()
|
|||||||
static void lsExit()
|
static void lsExit()
|
||||||
{
|
{
|
||||||
// setGPSPower(true); // restore GPS power
|
// setGPSPower(true); // restore GPS power
|
||||||
gps.startLock();
|
gps->startLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbEnter()
|
static void nbEnter()
|
||||||
@@ -104,6 +118,12 @@ static void darkEnter()
|
|||||||
screen.setOn(false);
|
screen.setOn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serialEnter()
|
||||||
|
{
|
||||||
|
setBluetoothEnable(false);
|
||||||
|
screen.setOn(true);
|
||||||
|
}
|
||||||
|
|
||||||
static void onEnter()
|
static void onEnter()
|
||||||
{
|
{
|
||||||
screen.setOn(true);
|
screen.setOn(true);
|
||||||
@@ -111,10 +131,11 @@ static void onEnter()
|
|||||||
|
|
||||||
static uint32_t lastPingMs;
|
static uint32_t lastPingMs;
|
||||||
|
|
||||||
uint32_t now = millis();
|
uint32_t now = timing::millis();
|
||||||
|
|
||||||
if (now - lastPingMs > 60 * 1000) { // if more than a minute since our last press, ask other nodes to update their state
|
if (now - lastPingMs > 30 * 1000) { // if more than a minute since our last press, ask other nodes to update their state
|
||||||
service.sendNetworkPing(NODENUM_BROADCAST, true);
|
if (displayedNodeNum)
|
||||||
|
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
|
||||||
lastPingMs = now;
|
lastPingMs = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,6 +153,7 @@ State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
|||||||
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
||||||
State stateNB(nbEnter, NULL, NULL, "NB");
|
State stateNB(nbEnter, NULL, NULL, "NB");
|
||||||
State stateDARK(darkEnter, NULL, NULL, "DARK");
|
State stateDARK(darkEnter, NULL, NULL, "DARK");
|
||||||
|
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
|
||||||
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
||||||
State stateON(onEnter, NULL, NULL, "ON");
|
State stateON(onEnter, NULL, NULL, "ON");
|
||||||
Fsm powerFSM(&stateBOOT);
|
Fsm powerFSM(&stateBOOT);
|
||||||
@@ -147,12 +169,20 @@ void PowerFSM_setup()
|
|||||||
|
|
||||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
|
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
|
||||||
|
|
||||||
// Handle press events
|
// Handle press events - note: we ignore button presses when in API mode
|
||||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
||||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
|
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
|
||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
||||||
|
|
||||||
|
// Handle critically low power battery by forcing deep sleep
|
||||||
|
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
|
|
||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||||
|
|
||||||
@@ -165,6 +195,13 @@ void PowerFSM_setup()
|
|||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
|
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
|
||||||
|
|
||||||
|
powerFSM.add_transition(&stateLS, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||||
|
powerFSM.add_transition(&stateNB, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||||
|
powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||||
|
powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||||
|
|
||||||
|
powerFSM.add_transition(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect");
|
||||||
|
|
||||||
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
|
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
|
||||||
|
|
||||||
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#define EVENT_BLUETOOTH_PAIR 7
|
#define EVENT_BLUETOOTH_PAIR 7
|
||||||
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
|
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
|
||||||
#define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth
|
#define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth
|
||||||
|
#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep
|
||||||
|
#define EVENT_SERIAL_CONNECTED 11
|
||||||
|
#define EVENT_SERIAL_DISCONNECTED 12
|
||||||
|
|
||||||
extern Fsm powerFSM;
|
extern Fsm powerFSM;
|
||||||
|
|
||||||
|
|||||||
103
src/PowerStatus.h
Normal file
103
src/PowerStatus.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Status.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
namespace meshtastic {
|
||||||
|
|
||||||
|
/// Describes the state of the GPS system.
|
||||||
|
class PowerStatus : public Status
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
CallbackObserver<PowerStatus, const PowerStatus *> statusObserver = CallbackObserver<PowerStatus, const PowerStatus *>(this, &PowerStatus::updateStatus);
|
||||||
|
|
||||||
|
/// Whether we have a battery connected
|
||||||
|
bool hasBattery;
|
||||||
|
/// Battery voltage in mV, valid if haveBattery is true
|
||||||
|
int batteryVoltageMv;
|
||||||
|
/// Battery charge percentage, either read directly or estimated
|
||||||
|
uint8_t batteryChargePercent;
|
||||||
|
/// Whether USB is connected
|
||||||
|
bool hasUSB;
|
||||||
|
/// Whether we are charging the battery
|
||||||
|
bool isCharging;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PowerStatus() {
|
||||||
|
statusType = STATUS_TYPE_POWER;
|
||||||
|
}
|
||||||
|
PowerStatus( bool hasBattery, bool hasUSB, bool isCharging, int batteryVoltageMv, uint8_t batteryChargePercent ) : Status()
|
||||||
|
{
|
||||||
|
this->hasBattery = hasBattery;
|
||||||
|
this->hasUSB = hasUSB;
|
||||||
|
this->isCharging = isCharging;
|
||||||
|
this->batteryVoltageMv = batteryVoltageMv;
|
||||||
|
this->batteryChargePercent = batteryChargePercent;
|
||||||
|
}
|
||||||
|
PowerStatus(const PowerStatus &);
|
||||||
|
PowerStatus &operator=(const PowerStatus &);
|
||||||
|
|
||||||
|
void observe(Observable<const PowerStatus *> *source)
|
||||||
|
{
|
||||||
|
statusObserver.observe(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getHasBattery() const
|
||||||
|
{
|
||||||
|
return hasBattery;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getHasUSB() const
|
||||||
|
{
|
||||||
|
return hasUSB;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getIsCharging() const
|
||||||
|
{
|
||||||
|
return isCharging;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBatteryVoltageMv() const
|
||||||
|
{
|
||||||
|
return batteryVoltageMv;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getBatteryChargePercent() const
|
||||||
|
{
|
||||||
|
return batteryChargePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const PowerStatus *newStatus) const
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
newStatus->getHasBattery() != hasBattery ||
|
||||||
|
newStatus->getHasUSB() != hasUSB ||
|
||||||
|
newStatus->getBatteryVoltageMv() != batteryVoltageMv
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int updateStatus(const PowerStatus *newStatus) {
|
||||||
|
// Only update the status if values have actually changed
|
||||||
|
bool isDirty;
|
||||||
|
{
|
||||||
|
isDirty = matches(newStatus);
|
||||||
|
initialized = true;
|
||||||
|
hasBattery = newStatus->getHasBattery();
|
||||||
|
batteryVoltageMv = newStatus->getBatteryVoltageMv();
|
||||||
|
batteryChargePercent = newStatus->getBatteryChargePercent();
|
||||||
|
hasUSB = newStatus->getHasUSB();
|
||||||
|
isCharging = newStatus->getIsCharging();
|
||||||
|
}
|
||||||
|
if(isDirty) {
|
||||||
|
DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
|
||||||
|
onNewStatus.notifyObservers(this);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern meshtastic::PowerStatus *powerStatus;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "SerialConsole.h"
|
#include "SerialConsole.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
@@ -21,17 +22,24 @@ void SerialConsole::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we override this to notice when we've received a protobuf over the serial stream. Then we shunt off
|
* we override this to notice when we've received a protobuf over the serial
|
||||||
* debug serial output.
|
* stream. Then we shunt off debug serial output.
|
||||||
*/
|
*/
|
||||||
void SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
void SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
||||||
{
|
{
|
||||||
// Note: for the time being we could _allow_ debug printing to keep going out the console
|
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
|
||||||
// I _think_ this is okay because we currently only print debug msgs from loop() and we are only
|
setDestination(&noopPrint);
|
||||||
// dispatching serial protobuf msgs from loop() as well. When things are more threaded in the future this
|
|
||||||
// will need to change.
|
|
||||||
// setDestination(&noopPrint);
|
|
||||||
canWrite = true;
|
canWrite = true;
|
||||||
|
|
||||||
StreamAPI::handleToRadio(buf, len);
|
StreamAPI::handleToRadio(buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hookable to find out when connection changes
|
||||||
|
void SerialConsole::onConnectionChanged(bool connected)
|
||||||
|
{
|
||||||
|
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
|
||||||
|
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
||||||
|
} else {
|
||||||
|
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,17 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
|
|||||||
* debug serial output.
|
* debug serial output.
|
||||||
*/
|
*/
|
||||||
virtual void handleToRadio(const uint8_t *buf, size_t len);
|
virtual void handleToRadio(const uint8_t *buf, size_t len);
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t c)
|
||||||
|
{
|
||||||
|
if (c == '\n') // prefix any newlines with carriage return
|
||||||
|
RedirectablePrint::write('\r');
|
||||||
|
return RedirectablePrint::write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Hookable to find out when connection changes
|
||||||
|
virtual void onConnectionChanged(bool connected);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SerialConsole console;
|
extern SerialConsole console;
|
||||||
|
|||||||
72
src/Status.h
Normal file
72
src/Status.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Observer.h"
|
||||||
|
|
||||||
|
// Constants for the various status types, so we can tell subclass instances apart
|
||||||
|
#define STATUS_TYPE_BASE 0
|
||||||
|
#define STATUS_TYPE_POWER 1
|
||||||
|
#define STATUS_TYPE_GPS 2
|
||||||
|
#define STATUS_TYPE_NODE 3
|
||||||
|
|
||||||
|
|
||||||
|
namespace meshtastic
|
||||||
|
{
|
||||||
|
|
||||||
|
// A base class for observable status
|
||||||
|
class Status
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Allows us to observe an Observable
|
||||||
|
CallbackObserver<Status, const Status *> statusObserver = CallbackObserver<Status, const Status *>(this, &Status::updateStatus);
|
||||||
|
bool initialized = false;
|
||||||
|
// Workaround for no typeid support
|
||||||
|
int statusType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Allows us to generate observable events
|
||||||
|
Observable<const Status *> onNewStatus;
|
||||||
|
|
||||||
|
// Enable polymorphism ?
|
||||||
|
virtual ~Status() = default;
|
||||||
|
|
||||||
|
Status() {
|
||||||
|
if (!statusType)
|
||||||
|
{
|
||||||
|
statusType = STATUS_TYPE_BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent object copy/move
|
||||||
|
Status(const Status &) = delete;
|
||||||
|
Status &operator=(const Status &) = delete;
|
||||||
|
|
||||||
|
// Start observing a source of data
|
||||||
|
void observe(Observable<const Status *> *source)
|
||||||
|
{
|
||||||
|
statusObserver.observe(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines whether or not existing data matches the data in another Status instance
|
||||||
|
bool matches(const Status *otherStatus) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInitialized() const
|
||||||
|
{
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getStatusType() const
|
||||||
|
{
|
||||||
|
return statusType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the Observable we're observing generates a new notification
|
||||||
|
int updateStatus(const Status *newStatus)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
0
src/StatusHandler.h
Normal file
0
src/StatusHandler.h
Normal file
@@ -1,44 +0,0 @@
|
|||||||
#include "WorkerThread.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
void Thread::start(const char *name, size_t stackSize, uint32_t priority)
|
|
||||||
{
|
|
||||||
auto r = xTaskCreate(callRun, name, stackSize, this, priority, &taskHandle);
|
|
||||||
assert(r == pdPASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thread::callRun(void *_this)
|
|
||||||
{
|
|
||||||
((Thread *)_this)->doRun();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorkerThread::doRun()
|
|
||||||
{
|
|
||||||
while (!wantExit) {
|
|
||||||
block();
|
|
||||||
loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify this thread so it can run
|
|
||||||
*/
|
|
||||||
void NotifiedWorkerThread::notify(uint32_t v, eNotifyAction action)
|
|
||||||
{
|
|
||||||
xTaskNotify(taskHandle, v, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify from an ISR
|
|
||||||
*/
|
|
||||||
void NotifiedWorkerThread::notifyFromISR(BaseType_t *highPriWoken, uint32_t v, eNotifyAction action)
|
|
||||||
{
|
|
||||||
xTaskNotifyFromISR(taskHandle, v, action, highPriWoken);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifiedWorkerThread::block()
|
|
||||||
{
|
|
||||||
xTaskNotifyWait(0, // don't clear notification on entry
|
|
||||||
0, // do not reset notification value on read
|
|
||||||
¬ification, portMAX_DELAY); // Wait forever
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
class Thread
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
TaskHandle_t taskHandle = NULL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set this to true to ask thread to cleanly exit asap
|
|
||||||
*/
|
|
||||||
volatile bool wantExit = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void start(const char *name, size_t stackSize = 1024, uint32_t priority = tskIDLE_PRIORITY);
|
|
||||||
|
|
||||||
virtual ~Thread() { vTaskDelete(taskHandle); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* The method that will be called when start is called.
|
|
||||||
*/
|
|
||||||
virtual void doRun() = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void callRun(void *_this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting onlyschool arduino loop() code.
|
|
||||||
*
|
|
||||||
* Use as a mixin base class for the classes you want to convert.
|
|
||||||
*
|
|
||||||
* https://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html
|
|
||||||
*/
|
|
||||||
class WorkerThread : public Thread
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* A method that should block execution - either waiting ona queue/mutex or a "task notification"
|
|
||||||
*/
|
|
||||||
virtual void block() = 0;
|
|
||||||
|
|
||||||
virtual void loop() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method that will be called when start is called.
|
|
||||||
*/
|
|
||||||
virtual void doRun();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A worker thread that waits on a freertos notification
|
|
||||||
*/
|
|
||||||
class NotifiedWorkerThread : public WorkerThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Notify this thread so it can run
|
|
||||||
*/
|
|
||||||
void notify(uint32_t v = 0, eNotifyAction action = eNoAction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify from an ISR
|
|
||||||
*/
|
|
||||||
void notifyFromISR(BaseType_t *highPriWoken, uint32_t v = 0, eNotifyAction action = eNoAction);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* The notification that was most recently used to wake the thread. Read from loop()
|
|
||||||
*/
|
|
||||||
uint32_t notification = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method that should block execution - either waiting ona queue/mutex or a "task notification"
|
|
||||||
*/
|
|
||||||
virtual void block();
|
|
||||||
};
|
|
||||||
15
src/commands.h
Normal file
15
src/commands.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @brief This class enables on the fly software and hardware setup.
|
||||||
|
* It will contain all command messages to change internal settings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum class Cmd {
|
||||||
|
INVALID,
|
||||||
|
SET_ON,
|
||||||
|
SET_OFF,
|
||||||
|
ON_PRESS,
|
||||||
|
START_BLUETOOTH_PIN_SCREEN,
|
||||||
|
STOP_BLUETOOTH_PIN_SCREEN,
|
||||||
|
STOP_BOOT_SCREEN,
|
||||||
|
PRINT,
|
||||||
|
};
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
#include "lock.h"
|
#include "Lock.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace meshtastic
|
namespace concurrency {
|
||||||
{
|
|
||||||
|
|
||||||
Lock::Lock()
|
Lock::Lock()
|
||||||
{
|
{
|
||||||
@@ -22,14 +20,4 @@ void Lock::unlock()
|
|||||||
assert(xSemaphoreGive(handle));
|
assert(xSemaphoreGive(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
LockGuard::LockGuard(Lock *lock) : lock(lock)
|
} // namespace concurrency
|
||||||
{
|
|
||||||
lock->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
LockGuard::~LockGuard()
|
|
||||||
{
|
|
||||||
lock->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace meshtastic
|
|
||||||
33
src/concurrency/Lock.h
Normal file
33
src/concurrency/Lock.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../freertosinc.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple wrapper around FreeRTOS API for implementing a mutex lock
|
||||||
|
*/
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Lock();
|
||||||
|
|
||||||
|
Lock(const Lock &) = delete;
|
||||||
|
Lock &operator=(const Lock &) = delete;
|
||||||
|
|
||||||
|
/// Locks the lock.
|
||||||
|
//
|
||||||
|
// Must not be called from an ISR.
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
// Unlocks the lock.
|
||||||
|
//
|
||||||
|
// Must not be called from an ISR.
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SemaphoreHandle_t handle;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
15
src/concurrency/LockGuard.cpp
Normal file
15
src/concurrency/LockGuard.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "LockGuard.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
LockGuard::LockGuard(Lock *lock) : lock(lock)
|
||||||
|
{
|
||||||
|
lock->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
LockGuard::~LockGuard()
|
||||||
|
{
|
||||||
|
lock->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
23
src/concurrency/LockGuard.h
Normal file
23
src/concurrency/LockGuard.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Lock.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RAII lock guard
|
||||||
|
*/
|
||||||
|
class LockGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LockGuard(Lock *lock);
|
||||||
|
~LockGuard();
|
||||||
|
|
||||||
|
LockGuard(const LockGuard &) = delete;
|
||||||
|
LockGuard &operator=(const LockGuard &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lock *lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
19
src/concurrency/NotifiedWorkerThread.cpp
Normal file
19
src/concurrency/NotifiedWorkerThread.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "NotifiedWorkerThread.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify this thread so it can run
|
||||||
|
*/
|
||||||
|
void NotifiedWorkerThread::notify(uint32_t v, eNotifyAction action)
|
||||||
|
{
|
||||||
|
xTaskNotify(taskHandle, v, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifiedWorkerThread::block()
|
||||||
|
{
|
||||||
|
xTaskNotifyWait(0, // don't clear notification on entry
|
||||||
|
clearOnRead, ¬ification, portMAX_DELAY); // Wait forever
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
47
src/concurrency/NotifiedWorkerThread.h
Normal file
47
src/concurrency/NotifiedWorkerThread.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "WorkerThread.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A worker thread that waits on a freertos notification
|
||||||
|
*/
|
||||||
|
class NotifiedWorkerThread : public WorkerThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Notify this thread so it can run
|
||||||
|
*/
|
||||||
|
void notify(uint32_t v = 0, eNotifyAction action = eNoAction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify from an ISR
|
||||||
|
*
|
||||||
|
* This must be inline or IRAM_ATTR on ESP32
|
||||||
|
*/
|
||||||
|
inline void notifyFromISR(BaseType_t *highPriWoken, uint32_t v = 0, eNotifyAction action = eNoAction)
|
||||||
|
{
|
||||||
|
xTaskNotifyFromISR(taskHandle, v, action, highPriWoken);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* The notification that was most recently used to wake the thread. Read from loop()
|
||||||
|
*/
|
||||||
|
uint32_t notification = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What notification bits should be cleared just after we read and return them in notification?
|
||||||
|
*
|
||||||
|
* Defaults to clear all of them.
|
||||||
|
*/
|
||||||
|
uint32_t clearOnRead = UINT32_MAX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method that should block execution - either waiting ona queue/mutex or a "task notification"
|
||||||
|
*/
|
||||||
|
virtual void block();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "PeriodicTask.h"
|
#include "PeriodicTask.h"
|
||||||
#include <Arduino.h>
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Periodically invoke a callback.
|
* @brief Periodically invoke a callback. This just provides C-style callback conventions
|
||||||
*
|
* rather than a virtual function - FIXME, remove?
|
||||||
* This just provides C style callback conventions rather than a virtual function - FIXME, remove?
|
|
||||||
*/
|
*/
|
||||||
class Periodic : public PeriodicTask
|
class Periodic : public PeriodicTask
|
||||||
{
|
{
|
||||||
@@ -17,5 +17,10 @@ class Periodic : public PeriodicTask
|
|||||||
Periodic(uint32_t (*_callback)()) : callback(_callback) {}
|
Periodic(uint32_t (*_callback)()) : callback(_callback) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void doTask();
|
void doTask() {
|
||||||
|
uint32_t p = callback();
|
||||||
|
setPeriod(p);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
35
src/concurrency/PeriodicScheduler.cpp
Normal file
35
src/concurrency/PeriodicScheduler.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "PeriodicScheduler.h"
|
||||||
|
#include "PeriodicTask.h"
|
||||||
|
#include "LockGuard.h"
|
||||||
|
#include "../timing.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/// call this from loop
|
||||||
|
void PeriodicScheduler::loop()
|
||||||
|
{
|
||||||
|
LockGuard lg(&lock);
|
||||||
|
|
||||||
|
uint32_t now = timing::millis();
|
||||||
|
for (auto t : tasks) {
|
||||||
|
if (t->period && (now - t->lastMsec) >= t->period) {
|
||||||
|
|
||||||
|
t->doTask();
|
||||||
|
t->lastMsec = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeriodicScheduler::schedule(PeriodicTask *t)
|
||||||
|
{
|
||||||
|
LockGuard lg(&lock);
|
||||||
|
tasks.insert(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeriodicScheduler::unschedule(PeriodicTask *t)
|
||||||
|
{
|
||||||
|
LockGuard lg(&lock);
|
||||||
|
tasks.erase(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
40
src/concurrency/PeriodicScheduler.h
Normal file
40
src/concurrency/PeriodicScheduler.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Lock.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
class PeriodicTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Runs all PeriodicTasks in the system. Currently called from main loop()
|
||||||
|
* but eventually should be its own thread blocked on a freertos timer.
|
||||||
|
*/
|
||||||
|
class PeriodicScheduler
|
||||||
|
{
|
||||||
|
friend class PeriodicTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This really should be some form of heap, and when the period gets changed on a task it should get
|
||||||
|
* rescheduled in that heap. Currently it is just a dumb array and everytime we run loop() we check
|
||||||
|
* _every_ tasks. If it was a heap we'd only have to check the first task.
|
||||||
|
*/
|
||||||
|
std::unordered_set<PeriodicTask *> tasks;
|
||||||
|
|
||||||
|
// Protects the above variables.
|
||||||
|
Lock lock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Run any next tasks which are due for execution
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void schedule(PeriodicTask *t);
|
||||||
|
void unschedule(PeriodicTask *t);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern PeriodicScheduler periodicScheduler;
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
16
src/concurrency/PeriodicTask.cpp
Normal file
16
src/concurrency/PeriodicTask.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include "PeriodicTask.h"
|
||||||
|
#include "Periodic.h"
|
||||||
|
#include "LockGuard.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
PeriodicScheduler periodicScheduler;
|
||||||
|
|
||||||
|
PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod) {}
|
||||||
|
|
||||||
|
void PeriodicTask::setup()
|
||||||
|
{
|
||||||
|
periodicScheduler.schedule(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
56
src/concurrency/PeriodicTask.h
Normal file
56
src/concurrency/PeriodicTask.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PeriodicScheduler.h"
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A base class for tasks that want their doTask() method invoked periodically
|
||||||
|
*
|
||||||
|
* @todo currently just syntatic sugar for polling in loop (you must call .loop), but eventually
|
||||||
|
* generalize with the freertos scheduler so we can save lots of power by having everything either in
|
||||||
|
* something like this or triggered off of an irq.
|
||||||
|
*/
|
||||||
|
class PeriodicTask
|
||||||
|
{
|
||||||
|
friend class PeriodicScheduler;
|
||||||
|
|
||||||
|
uint32_t lastMsec = 0;
|
||||||
|
uint32_t period = 1; // call soon after creation
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~PeriodicTask() { periodicScheduler.unschedule(this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor (will schedule with the global PeriodicScheduler)
|
||||||
|
*/
|
||||||
|
PeriodicTask(uint32_t initialPeriod = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MUST be be called once at startup (but after threading is running - i.e. not from a constructor)
|
||||||
|
*/
|
||||||
|
void setup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new period in msecs (can be called from doTask or elsewhere and the scheduler will cope)
|
||||||
|
* While zero this task is disabled and will not run
|
||||||
|
*/
|
||||||
|
void setPeriod(uint32_t p)
|
||||||
|
{
|
||||||
|
lastMsec = timing::millis(); // reset starting from now
|
||||||
|
period = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getPeriod() const { return period; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syntatic sugar for suspending tasks
|
||||||
|
*/
|
||||||
|
void disable() { setPeriod(0); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void doTask() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
46
src/concurrency/Thread.cpp
Normal file
46
src/concurrency/Thread.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "Thread.h"
|
||||||
|
#include "timing.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include "esp_task_wdt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace concurrency
|
||||||
|
{
|
||||||
|
|
||||||
|
void Thread::start(const char *name, size_t stackSize, uint32_t priority)
|
||||||
|
{
|
||||||
|
auto r = xTaskCreate(callRun, name, stackSize, this, priority, &taskHandle);
|
||||||
|
assert(r == pdPASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::callRun(void *_this)
|
||||||
|
{
|
||||||
|
((Thread *)_this)->doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::serviceWatchdog()
|
||||||
|
{
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::startWatchdog()
|
||||||
|
{
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
auto r = esp_task_wdt_add(taskHandle);
|
||||||
|
assert(r == ESP_OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::stopWatchdog()
|
||||||
|
{
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
auto r = esp_task_wdt_delete(taskHandle);
|
||||||
|
assert(r == ESP_OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
47
src/concurrency/Thread.h
Normal file
47
src/concurrency/Thread.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "freertosinc.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base threading
|
||||||
|
*/
|
||||||
|
class Thread
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
TaskHandle_t taskHandle = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set this to true to ask thread to cleanly exit asap
|
||||||
|
*/
|
||||||
|
volatile bool wantExit = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void start(const char *name, size_t stackSize = 1024, uint32_t priority = tskIDLE_PRIORITY);
|
||||||
|
|
||||||
|
virtual ~Thread() { vTaskDelete(taskHandle); }
|
||||||
|
|
||||||
|
uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* The method that will be called when start is called.
|
||||||
|
*/
|
||||||
|
virtual void doRun() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All thread run methods must periodically call serviceWatchdog, or the system will declare them hung and panic.
|
||||||
|
*
|
||||||
|
* this only applies after startWatchdog() has been called. If you need to sleep for a long time call stopWatchdog()
|
||||||
|
*/
|
||||||
|
void serviceWatchdog();
|
||||||
|
void startWatchdog();
|
||||||
|
void stopWatchdog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void callRun(void *_this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
32
src/concurrency/WorkerThread.cpp
Normal file
32
src/concurrency/WorkerThread.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "WorkerThread.h"
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
void WorkerThread::doRun()
|
||||||
|
{
|
||||||
|
startWatchdog();
|
||||||
|
|
||||||
|
while (!wantExit) {
|
||||||
|
stopWatchdog();
|
||||||
|
block();
|
||||||
|
startWatchdog();
|
||||||
|
|
||||||
|
// no need - startWatchdog is guaranteed to give us one full watchdog interval
|
||||||
|
// serviceWatchdog(); // Let our loop worker have one full watchdog interval (at least) to run
|
||||||
|
|
||||||
|
#ifdef DEBUG_STACK
|
||||||
|
static uint32_t lastPrint = 0;
|
||||||
|
if (timing::millis() - lastPrint > 10 * 1000L) {
|
||||||
|
lastPrint = timing::millis();
|
||||||
|
meshtastic::printThreadInfo("net");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
stopWatchdog();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
29
src/concurrency/WorkerThread.h
Normal file
29
src/concurrency/WorkerThread.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
namespace concurrency {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting
|
||||||
|
* old-school arduino loop() code. Use as a mixin base class for the classes you want to convert.
|
||||||
|
*
|
||||||
|
* @link https://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html
|
||||||
|
*/
|
||||||
|
class WorkerThread : public Thread
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* A method that should block execution - either waiting ona queue/mutex or a "task notification"
|
||||||
|
*/
|
||||||
|
virtual void block() = 0;
|
||||||
|
|
||||||
|
virtual void loop() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method that will be called when start is called.
|
||||||
|
*/
|
||||||
|
virtual void doRun();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace concurrency
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user