Compare commits
1067 commits
add-tinyuf
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eeab5cf9da | ||
|
|
138ea12d9f | ||
|
|
6359af9a0a | ||
|
|
f5b08cd812 | ||
|
|
e998f5be8f | ||
|
|
13bacf5086 | ||
|
|
9902934412 | ||
|
|
1a56a1dcca | ||
|
|
288672980c | ||
|
|
311955ccbb | ||
|
|
a5e85f675e | ||
|
|
e375698ade | ||
|
|
0dcb1d1178 | ||
|
|
ed6e95d4fc | ||
|
|
b3152a4ffc | ||
|
|
10e73be714 | ||
|
|
5c24611b91 | ||
|
|
e3a0a3a6c5 | ||
|
|
d55646344d | ||
|
|
126039663f | ||
|
|
c7520ccef0 | ||
|
|
dbaf6a3226 | ||
|
|
3da3ad2f2d | ||
|
|
67c59a2021 | ||
|
|
0bdad7f2a3 | ||
|
|
e92e631811 | ||
|
|
6fdfccf21b | ||
|
|
2b3b4f05d5 | ||
|
|
ae634a92e3 | ||
|
|
f08efa1fa3 | ||
|
|
a14ce89715 | ||
|
|
69d891434b | ||
|
|
554de56f40 | ||
|
|
c369dca062 | ||
|
|
4c51968acf | ||
|
|
4a3c6d7fbb | ||
|
|
f1712943b4 | ||
|
|
995e603d3a | ||
|
|
cb3329be60 | ||
|
|
349b11d2d8 | ||
|
|
28e9076601 | ||
|
|
cf0a58908d | ||
|
|
439bbb8391 | ||
|
|
cdf606af5f | ||
|
|
f330585717 | ||
|
|
76210797ed | ||
|
|
6a33f0bfc1 | ||
|
|
9641de1b12 | ||
|
|
3ad17de6aa | ||
|
|
211a0ce143 | ||
|
|
000336bad0 | ||
|
|
530c1a43fe | ||
|
|
346e7f4138 | ||
|
|
6cb5184487 | ||
|
|
98d309f84a | ||
|
|
a69c71f6ad | ||
|
|
5ccd9523d6 | ||
|
|
6015fd73e0 | ||
|
|
ac05f18720 | ||
|
|
3f32903125 | ||
|
|
ce7ef9c2ba | ||
|
|
82d56bc679 | ||
|
|
1f0d4b5dc0 | ||
|
|
0a45a06142 | ||
|
|
c6a3bcb014 | ||
|
|
4ee17dea04 | ||
|
|
fbf3c11daa | ||
|
|
87b718a59c | ||
|
|
ee021855a1 | ||
|
|
df3db3c9dc | ||
|
|
ccc0a69ef8 | ||
|
|
6a5839acb2 | ||
|
|
2cb6fbccdb | ||
|
|
241e2576be | ||
|
|
040e0ca42a | ||
|
|
e2c7578fa8 | ||
|
|
b709a78283 | ||
|
|
d3c5a82eed | ||
|
|
1426927c83 | ||
|
|
f84fab5592 | ||
|
|
aab542d658 | ||
|
|
0b9c9362de | ||
|
|
ac961f671a | ||
|
|
18f647611b | ||
|
|
c2d23258f1 | ||
|
|
d4e5c5f969 | ||
|
|
70696df2d6 | ||
|
|
12e881b6d6 | ||
|
|
33c8438263 | ||
|
|
6474127dd4 | ||
|
|
7f75e445f7 | ||
|
|
bc7a549876 | ||
|
|
212b12b625 | ||
|
|
f4fdecc60c | ||
|
|
8cf0818d82 | ||
|
|
2592a7b3bb | ||
|
|
6e60f2f6b9 | ||
|
|
6476260e8f | ||
|
|
6754b1962c | ||
|
|
9a35d9455f | ||
|
|
875b923035 | ||
|
|
ff3cc813fc | ||
|
|
21640ac82a | ||
|
|
5871a80616 | ||
|
|
9e61fa7e4b | ||
|
|
0213200b3d | ||
|
|
e9b0930f9d | ||
|
|
30fb3cbb4f | ||
|
|
b7e5169ea1 | ||
|
|
882ef25a36 | ||
|
|
36d049659b | ||
|
|
bad975daa5 | ||
|
|
95ae8cf9c6 | ||
|
|
18c909a8fd | ||
|
|
dc82467ba4 | ||
|
|
1c79eb823c | ||
|
|
febca6b2f1 | ||
|
|
29035dc689 | ||
|
|
9d84c78cf2 | ||
|
|
bf55924b67 | ||
|
|
01e4d5debb | ||
|
|
ccda9c5f84 | ||
|
|
23c6abc1ac | ||
|
|
05fbda2d6d | ||
|
|
016077e245 | ||
|
|
02be6e8826 | ||
|
|
51f1367d57 | ||
|
|
f7889116b1 | ||
|
|
6d4886cd1f | ||
|
|
4bc5ffc88d | ||
|
|
7462b09bb4 | ||
|
|
ef995b6564 | ||
|
|
228393708d | ||
|
|
0f72681fa0 | ||
|
|
422e52684b | ||
|
|
aaeabb5b87 | ||
|
|
d71135e2ca | ||
|
|
c21ef70a15 | ||
|
|
cbdaee6f52 | ||
|
|
d6a76da0a5 | ||
|
|
0aada091e1 | ||
|
|
89ff465328 | ||
|
|
0007815a11 | ||
|
|
af47bd3008 | ||
|
|
ee347baa7d | ||
|
|
610d951f9d | ||
|
|
1bac8de384 | ||
|
|
e9813c6a52 | ||
|
|
31d22e6ed0 | ||
|
|
0ab9a0fe6f | ||
|
|
e3018b6719 | ||
|
|
cae66e65a3 | ||
|
|
375f2c002d | ||
|
|
460b89201b | ||
|
|
a2880a4c17 | ||
|
|
b5c5655cf0 | ||
|
|
6f56df2a09 | ||
|
|
a6bba43d32 | ||
|
|
6ce7e254c4 | ||
|
|
b7698461ac | ||
|
|
f3ae2a65e2 | ||
|
|
72a582b908 | ||
|
|
15038e64b3 | ||
|
|
91fd517cf1 | ||
|
|
31bfcb27ce | ||
|
|
fa275971cd | ||
|
|
d960f61e0a | ||
|
|
7bafc1b19b | ||
|
|
6c3528ac69 | ||
|
|
07d662a7fc | ||
|
|
542274d5ea | ||
|
|
9090b46da5 | ||
|
|
d85b75c219 | ||
|
|
3f63a4929f | ||
|
|
13cd0d3c3f | ||
|
|
5540afa1ea | ||
|
|
d69ad5e747 | ||
|
|
69cd5a0a66 | ||
|
|
8d5a026c98 | ||
|
|
bc08c49579 | ||
|
|
a83bb93b6d | ||
|
|
6f92b604f6 | ||
|
|
210edfeaa6 | ||
|
|
602f1f6e7f | ||
|
|
15e71a6afd | ||
|
|
158c7aec42 | ||
|
|
b115acea40 | ||
|
|
c9efce6342 | ||
|
|
543fad2bdf | ||
|
|
de72a03ca5 | ||
|
|
d63b876f93 | ||
|
|
16fcdeb0be | ||
|
|
b461e01e22 | ||
|
|
9193c9db1e | ||
|
|
8d121e075f | ||
|
|
5df9b64023 | ||
|
|
8ed97f6fa8 | ||
|
|
5262f5ad5e | ||
|
|
23f3600a4b | ||
|
|
571c2f74f2 | ||
|
|
51023aea79 | ||
|
|
03e9c45084 | ||
|
|
5d0c4b3507 | ||
|
|
c110ca8295 | ||
|
|
a8bead7efb | ||
|
|
e0d4d176ea | ||
|
|
42ae2426af | ||
|
|
ae2ae8dfa0 | ||
|
|
f1223663dd | ||
|
|
9cad83bacf | ||
|
|
60c8206ee6 | ||
|
|
3fcc316d3c | ||
|
|
bd4b32522c | ||
|
|
be57376b6b | ||
|
|
2647cbbbc2 | ||
|
|
8e8b1cbd31 | ||
|
|
d3509ef98b | ||
|
|
7f60945018 | ||
|
|
0cc8eab836 | ||
|
|
b333bf2697 | ||
|
|
23ded939ea | ||
|
|
22f07d01c8 | ||
|
|
7b0298b462 | ||
|
|
998bf80248 | ||
|
|
fbca62fd68 | ||
|
|
a61961d5c9 | ||
|
|
dac2dd907d | ||
|
|
de184bd0cb | ||
|
|
1014937965 | ||
|
|
a3b6fe61ba | ||
|
|
bbaabb183a | ||
|
|
d81c19534f | ||
|
|
17258930e6 | ||
|
|
e37435c442 | ||
|
|
86221479b7 | ||
|
|
1ca9dab521 | ||
|
|
caa597143c | ||
|
|
98611d46dc | ||
|
|
df51bc3aa5 | ||
|
|
9dddc142fc | ||
|
|
cd7f4218e7 | ||
|
|
6273c4ffd8 | ||
|
|
cc2632b3bb | ||
|
|
6c04a93153 | ||
|
|
7fda434d89 | ||
|
|
7c1ac1ae60 | ||
|
|
d66eeb7754 | ||
|
|
3fe2fe5311 | ||
|
|
e30e3c30f1 | ||
|
|
042015efc8 | ||
|
|
6283c15ae2 | ||
|
|
75de09ef29 | ||
|
|
f45cd7bf33 | ||
|
|
9fbcb345b7 | ||
|
|
8af81cdf09 | ||
|
|
d9d3bf48d3 | ||
|
|
100ed8e895 | ||
|
|
0894d7db68 | ||
|
|
af5abd5f61 | ||
|
|
bf90cbd183 | ||
|
|
88cda9ff59 | ||
|
|
66abd86ce9 | ||
|
|
18709faa90 | ||
|
|
e2915c48e8 | ||
|
|
8e62997bfd | ||
|
|
74ee9df48c | ||
|
|
ba2ab1e4bb | ||
|
|
f7c1efccaa | ||
|
|
2a3de9c415 | ||
|
|
c2b0482511 | ||
|
|
07d6a5a0d2 | ||
|
|
bda7c48117 | ||
|
|
e8a243c1db | ||
|
|
d9dbc4af41 | ||
|
|
e680e7b538 | ||
|
|
2276f0b794 | ||
|
|
665d6f8e8d | ||
|
|
bf5265c7d8 | ||
|
|
eeb6a26ed1 | ||
|
|
8575d04ab5 | ||
|
|
4677ea6ad8 | ||
|
|
efb02d30ac | ||
|
|
fb5f11b638 | ||
|
|
9e2f755641 | ||
|
|
684a9312e6 | ||
|
|
7575fa0ce8 | ||
|
|
e3bcc58672 | ||
|
|
923da957e4 | ||
|
|
7485c653bb | ||
|
|
09d89c6da1 | ||
|
|
1467d87454 | ||
|
|
c76c2eab37 | ||
|
|
b33470e44b | ||
|
|
0c18b17ac4 | ||
|
|
164fcc6a61 | ||
|
|
39be694127 | ||
|
|
988dbe2973 | ||
|
|
42bd7456ce | ||
|
|
543a647f2c | ||
|
|
003db9e4c0 | ||
|
|
9a783a5d2c | ||
|
|
cd95e4055b | ||
|
|
978b441cd4 | ||
|
|
eec2af3d35 | ||
|
|
5afafdf4c6 | ||
|
|
646785e086 | ||
|
|
55f4f1bfa8 | ||
|
|
8e9f7c31c9 | ||
|
|
783271b6b5 | ||
|
|
35feed5077 | ||
|
|
f0cf3b1af6 | ||
|
|
18cbd762c9 | ||
|
|
50d85a6e9d | ||
|
|
47343a43f7 | ||
|
|
dbfde15b6a | ||
|
|
758cbd097d | ||
|
|
20e5e706be | ||
|
|
a4ecdb1a0f | ||
|
|
a7907cd07e | ||
|
|
62082398d3 | ||
|
|
5488d5d23f | ||
|
|
6fb55a7f68 | ||
|
|
fb6b788b30 | ||
|
|
606a4049a2 | ||
|
|
7f8c77f9ee | ||
|
|
83abca1604 | ||
|
|
6c3a49cac7 | ||
|
|
7b651b64d6 | ||
|
|
250c1abf78 | ||
|
|
5ba4c21a99 | ||
|
|
6fcaf69097 | ||
|
|
db0bbad934 | ||
|
|
6a1127625c | ||
|
|
8b31d1e1a8 | ||
|
|
b385562fa6 | ||
|
|
6eb99d3ae3 | ||
|
|
2040cbad51 | ||
|
|
1c01fcd196 | ||
|
|
0302b4db47 | ||
|
|
f22866f888 | ||
|
|
402ab56bf1 | ||
|
|
732a7cb4ee | ||
|
|
2fecc482b7 | ||
|
|
15cbb1e857 | ||
|
|
7089c0a188 | ||
|
|
496b841177 | ||
|
|
2a2b81ad6f | ||
|
|
01d9726609 | ||
|
|
fcce93a029 | ||
|
|
0773dd7619 | ||
|
|
4c36c89768 | ||
|
|
a81e2d48f5 | ||
|
|
814371726d | ||
|
|
2f423afc4e | ||
|
|
c23c786749 | ||
|
|
51ef2a1d29 | ||
|
|
e305a483b0 | ||
|
|
7cfe0adc87 | ||
|
|
efb3393aa1 | ||
|
|
30b97d1f91 | ||
|
|
ed9a5d876d | ||
|
|
2cb08193d8 | ||
|
|
5f44c4ebc5 | ||
|
|
9eee1dd559 | ||
|
|
5aaccd8f89 | ||
|
|
10d0bf8ea7 | ||
|
|
e3cc04084d | ||
|
|
b07eb175d8 | ||
|
|
089cbabf17 | ||
|
|
5c41881858 | ||
|
|
9eb7dc6f7b | ||
|
|
352705e607 | ||
|
|
7298959ce5 | ||
|
|
4884c96463 | ||
|
|
bd7a74ee51 | ||
|
|
4fdf9ef854 | ||
|
|
3ffee273fb | ||
|
|
ee33ad5910 | ||
|
|
238c384e4e | ||
|
|
2fc679151c | ||
|
|
4d0ae18aee | ||
|
|
25ebe440e2 | ||
|
|
6bf6df2d6f | ||
|
|
71e57eaf52 | ||
|
|
e2dc5b60f3 | ||
|
|
bce01087d2 | ||
|
|
017f2df8ef | ||
|
|
1ef603aab7 | ||
|
|
7302be9792 | ||
|
|
6f79e03449 | ||
|
|
ba8d04eff2 | ||
|
|
6a6edcbee9 | ||
|
|
0515264aa6 | ||
|
|
eb7258070b | ||
|
|
30e55fc4b7 | ||
|
|
8479b4cd9f | ||
|
|
cd7a775344 | ||
|
|
43c419e31b | ||
|
|
3f7c5976d2 | ||
|
|
0e22bb4bac | ||
|
|
c688f3090f | ||
|
|
1dff8bc759 | ||
|
|
1ef1e7dbac | ||
|
|
7d465f323b | ||
|
|
31dc520c4d | ||
|
|
a207d58f0f | ||
|
|
6005b15947 | ||
|
|
926c043e3a | ||
|
|
4f863d52ba | ||
|
|
ddf8c42af3 | ||
|
|
2c7b76aea8 | ||
|
|
ae274ee897 | ||
|
|
ff7e50482a | ||
|
|
3c3ff48d73 | ||
|
|
64b62dc45b | ||
|
|
8e59a1b777 | ||
|
|
417c7ee25d | ||
|
|
42f9cfca60 | ||
|
|
af541a5c14 | ||
|
|
b6d0553fa5 | ||
|
|
a0d57bb6d0 | ||
|
|
538c57a994 | ||
|
|
aa0c3da729 | ||
|
|
a44e45795c | ||
|
|
6bc971c1a3 | ||
|
|
a7e2e64c5b | ||
|
|
faed832298 | ||
|
|
8b77d91b69 | ||
|
|
c562aeceda | ||
|
|
740fc0b78e | ||
|
|
57339ba58c | ||
|
|
b72e8669df | ||
|
|
44e1559830 | ||
|
|
ce9a34db9a | ||
|
|
71396de822 | ||
|
|
784ef0f286 | ||
|
|
7dc1c92813 | ||
|
|
7205ee81ac | ||
|
|
c6ec112054 | ||
|
|
8f0f46fe54 | ||
|
|
c126f017f8 | ||
|
|
c310c1ade4 | ||
|
|
e060b02328 | ||
|
|
b64b8500cb | ||
|
|
5e7139b8fe | ||
|
|
b4d7227068 | ||
|
|
aef691e0e2 | ||
|
|
77df256f5d | ||
|
|
4cf0f20129 | ||
|
|
a4f96e9280 | ||
|
|
3bf8f23e48 | ||
|
|
217eec6e1e | ||
|
|
c8f23ec65d | ||
|
|
b9a0122f7b | ||
|
|
d072cdd41f | ||
|
|
e17900b02a | ||
|
|
a1f58ad2c8 | ||
|
|
fb6e977aa8 | ||
|
|
59d51de642 | ||
|
|
029a57ff36 | ||
|
|
d55160c2fe | ||
|
|
4ecfd35ec6 | ||
|
|
237523ee2b | ||
|
|
83165f3494 | ||
|
|
9c169fac8b | ||
|
|
c3ddcd74d4 | ||
|
|
2bd1ec4394 | ||
|
|
639a08eb20 | ||
|
|
626a09f8ea | ||
|
|
7e908be100 | ||
|
|
68cafb460d | ||
|
|
3a8d4c5244 | ||
|
|
8cbc395122 | ||
|
|
dfa732419b | ||
|
|
56a9b1d123 | ||
|
|
bfc45db3af | ||
|
|
7c95911ff1 | ||
|
|
07a3e629c8 | ||
|
|
1f9eb74337 | ||
|
|
9c383687e0 | ||
|
|
59bc22a98f | ||
|
|
178af05079 | ||
|
|
de4824fc24 | ||
|
|
5a8cba88c7 | ||
|
|
45d863049a | ||
|
|
3d8014b453 | ||
|
|
d7492b167c | ||
|
|
a281b26bae | ||
|
|
87d988fdb5 | ||
|
|
be95fc5764 | ||
|
|
8c3efc26f6 | ||
|
|
9b9e6afdc6 | ||
|
|
9660e66325 | ||
|
|
538efe3b8c | ||
|
|
2028ba43da | ||
|
|
2f21d6482b | ||
|
|
19e4d0db4a | ||
|
|
cd772f1437 | ||
|
|
7a0775d697 | ||
|
|
7a82b8be83 | ||
|
|
76d1f9e643 | ||
|
|
92dd841ffc | ||
|
|
77c69c38d6 | ||
|
|
e159bf6e46 | ||
|
|
4eeff9bc57 | ||
|
|
c7022caeda | ||
|
|
6ce43695d2 | ||
|
|
af84da6f6a | ||
|
|
9d8df8b315 | ||
|
|
c2ce738cae | ||
|
|
9f5f95e50a | ||
|
|
414e4f3233 | ||
|
|
98da424de6 | ||
|
|
0f3191e34f | ||
|
|
0bcdd2c65f | ||
|
|
4fc8abfafe | ||
|
|
eb1933fde9 | ||
|
|
1730e4e57e | ||
|
|
9417a84918 | ||
|
|
1712fb5eee | ||
|
|
6e57662599 | ||
|
|
962ab3acea | ||
|
|
3dd4b0d112 | ||
|
|
6bc3ce68fe | ||
|
|
ff613b3f29 | ||
|
|
66f7c93db4 | ||
|
|
268b31c3f6 | ||
|
|
f0ded24b3f | ||
|
|
442679d225 | ||
|
|
d7b5bb111e | ||
|
|
f5ce3f7675 | ||
|
|
2b6b5c74ce | ||
|
|
fe0f016b4f | ||
|
|
4a8ba4294e | ||
|
|
3a5dbf241e | ||
|
|
1cdd8e8ce0 | ||
|
|
02b03286a2 | ||
|
|
9c25cef93f | ||
|
|
e9b3f2650e | ||
|
|
3822a68820 | ||
|
|
cc407185a3 | ||
|
|
f8d9ffb74a | ||
|
|
d561685258 | ||
|
|
e99f1fdc6d | ||
|
|
54a7a3ee9a | ||
|
|
1a8e53fe47 | ||
|
|
09a6770320 | ||
|
|
f66ba37d1f | ||
|
|
1ecbbae7d3 | ||
|
|
32e2230de2 | ||
|
|
c0092206a6 | ||
|
|
61d5c49445 | ||
|
|
9f3010f214 | ||
|
|
adcbc2ab59 | ||
|
|
d1df696cd0 | ||
|
|
3dad918cea | ||
|
|
501f8a9a4e | ||
|
|
69825a99f9 | ||
|
|
a80b03e017 | ||
|
|
b170e87d41 | ||
|
|
de93e6e176 | ||
|
|
f1e1f5ab95 | ||
|
|
11f3cff53f | ||
|
|
870468bb25 | ||
|
|
57d0deef2d | ||
|
|
eeecf844a7 | ||
|
|
05102fe853 | ||
|
|
d47771f2cc | ||
|
|
87ad78d787 | ||
|
|
804ee12741 | ||
|
|
a805e0696c | ||
|
|
74e4a744ce | ||
|
|
9aeb1ba548 | ||
|
|
38a4c29fed | ||
|
|
9ac705e5f2 | ||
|
|
a3ee37669e | ||
|
|
9fd1bf362f | ||
|
|
07c510e3ad | ||
|
|
330beb40a5 | ||
|
|
6dfd958983 | ||
|
|
cb83cda06a | ||
|
|
35549272b3 | ||
|
|
6e88445ba9 | ||
|
|
3502b9c7a9 | ||
|
|
bcc357c0ca | ||
|
|
1756bd567c | ||
|
|
a0139bc37d | ||
|
|
0f5219df0e | ||
|
|
dc1a49e6f0 | ||
|
|
4285912a46 | ||
|
|
4944dd0df3 | ||
|
|
0eee5c4a13 | ||
|
|
aefe8a55d3 | ||
|
|
1631466426 | ||
|
|
774201ade3 | ||
|
|
20a28b58bc | ||
|
|
8ac076c44c | ||
|
|
7a33a9eeff | ||
|
|
0045cfa658 | ||
|
|
e509d33d27 | ||
|
|
f1f0e4d4f3 | ||
|
|
01789a7a89 | ||
|
|
c40444ab33 | ||
|
|
f668557b54 | ||
|
|
03bfa52d49 | ||
|
|
9e643c08a7 | ||
|
|
83d35683c3 | ||
|
|
7cfe470d8d | ||
|
|
a7d9b670a8 | ||
|
|
4ca635a3b6 | ||
|
|
59ca4e2d3d | ||
|
|
064d1c4d97 | ||
|
|
edb4ee13d2 | ||
|
|
8570b3d270 | ||
|
|
9e48d9f238 | ||
|
|
ee8931d151 | ||
|
|
ee1bc6ba0a | ||
|
|
612fc4c4bb | ||
|
|
955b277497 | ||
|
|
51b2fb356d | ||
|
|
7849a79435 | ||
|
|
bda8fcb457 | ||
|
|
9dea05b17f | ||
|
|
c676ce7dc0 | ||
|
|
f706c27671 | ||
|
|
592c994817 | ||
|
|
a3f2568a19 | ||
|
|
c6bf1b4816 | ||
|
|
f8e03cfaac | ||
|
|
3edf518825 | ||
|
|
e27a050f5a | ||
|
|
3733c87c83 | ||
|
|
81d2cbca96 | ||
|
|
774f2756f1 | ||
|
|
af4099202d | ||
|
|
f083e2df8d | ||
|
|
ba9a3a1dbd | ||
|
|
3445164e2d | ||
|
|
0d5d50eb41 | ||
|
|
4d1c9bcfa3 | ||
|
|
630377f7d3 | ||
|
|
765173372f | ||
|
|
e12e33c581 | ||
|
|
8ce5f775fe | ||
|
|
5fd7826d9f | ||
|
|
13511a6b65 | ||
|
|
5d873c0787 | ||
|
|
6d6a8f8d32 | ||
|
|
341dc18079 | ||
|
|
733373a049 | ||
|
|
157b4c8643 | ||
|
|
6c99740374 | ||
|
|
ea50cf6f5f | ||
|
|
01b256ca1c | ||
|
|
c3aa74f60a | ||
|
|
c5047286a1 | ||
|
|
b067cd6d7f | ||
|
|
264c858830 | ||
|
|
473b8515ac | ||
|
|
58c0bbc0e9 | ||
|
|
19f611d7ee | ||
|
|
8af91fb4a7 | ||
|
|
e3499bc4b7 | ||
|
|
2ec5584d06 | ||
|
|
cd971319cb | ||
|
|
0db5beffff | ||
|
|
84ddf0ad28 | ||
|
|
753e2032e7 | ||
|
|
482c0a3c26 | ||
|
|
c980fdc996 | ||
|
|
a5a5809eec | ||
|
|
5a06dd9e57 | ||
|
|
a4cbdaf3a8 | ||
|
|
a76b22881a | ||
|
|
8422b745c2 | ||
|
|
69351312e5 | ||
|
|
e403f0b481 | ||
|
|
1f1de2738b | ||
|
|
7a0138462d | ||
|
|
b05f18dad5 | ||
|
|
55bd1d5ee2 | ||
|
|
4bb287eaf6 | ||
|
|
9398d52ddc | ||
|
|
87c0e7763d | ||
|
|
a4c33e3897 | ||
|
|
ae052f414a | ||
|
|
67682088ca | ||
|
|
e68b1cca09 | ||
|
|
7018cd114d | ||
|
|
ab951cf08a | ||
|
|
8d772d5e89 | ||
|
|
462870df24 | ||
|
|
100b3c67cf | ||
|
|
c55f5aa506 | ||
|
|
e989445b62 | ||
|
|
2f89026540 | ||
|
|
3978870f9f | ||
|
|
44a484475c | ||
|
|
a7cec020df | ||
|
|
9e60bbe4bc | ||
|
|
ac0de431e7 | ||
|
|
8c25325e18 | ||
|
|
8a87df3b95 | ||
|
|
648094c733 | ||
|
|
eda6d21d87 | ||
|
|
855da422ba | ||
|
|
4e9eb35752 | ||
|
|
1e04762e3a | ||
|
|
d846311344 | ||
|
|
2c4ce95e16 | ||
|
|
ef23d52d9b | ||
|
|
cbe0f2ff0d | ||
|
|
532d5f2fad | ||
|
|
2853b7c0a4 | ||
|
|
6264d6b72b | ||
|
|
c0dce69fc1 | ||
|
|
eec855a09f | ||
|
|
e964a2deab | ||
|
|
976bda6b49 | ||
|
|
41cdbd99b7 | ||
|
|
e70f4d3819 | ||
|
|
7a4587b4bd | ||
|
|
f06f2d7b07 | ||
|
|
0b8eedea5c | ||
|
|
254c5e43f1 | ||
|
|
4c1095b23f | ||
|
|
b2c805a139 | ||
|
|
019855ff90 | ||
|
|
22fb4026de | ||
|
|
396def3f83 | ||
|
|
e5394ccef7 | ||
|
|
564612dacc | ||
|
|
a8677a074a | ||
|
|
ef5c6b94b3 | ||
|
|
8352caff08 | ||
|
|
77d8095472 | ||
|
|
57518b821c | ||
|
|
e6dc9db764 | ||
|
|
dd4a7d6c5e | ||
|
|
0b842442c9 | ||
|
|
75b29fde57 | ||
|
|
683fea103c | ||
|
|
e04f050639 | ||
|
|
fa6711551d | ||
|
|
4c4906f470 | ||
|
|
5ecda3a7cb | ||
|
|
7633653019 | ||
|
|
df4518d6a1 | ||
|
|
6f84a43611 | ||
|
|
99e68a0518 | ||
|
|
0539ebf322 | ||
|
|
dbdb40280a | ||
|
|
4178e6643b | ||
|
|
edc56a8eb0 | ||
|
|
0a8888d5d6 | ||
|
|
cd3d0bf569 | ||
|
|
60cbb6276a | ||
|
|
6c4e9ee609 | ||
|
|
00b3941de5 | ||
|
|
7fe4aa672c | ||
|
|
4098c53f5f | ||
|
|
c7ac06c83a | ||
|
|
e660261b63 | ||
|
|
c7e01e72a1 | ||
|
|
66c9c0b1a6 | ||
|
|
54f1c22672 | ||
|
|
f77ce040db | ||
|
|
e1673e4c0c | ||
|
|
def319add8 | ||
|
|
41f3e5e236 | ||
|
|
2a971751a7 | ||
|
|
49a3c10ce0 | ||
|
|
b8c9b59b61 | ||
|
|
f53f2dc975 | ||
|
|
a7399e2b68 | ||
|
|
124c2141fc | ||
|
|
16b2d74441 | ||
|
|
ae71b2d0f5 | ||
|
|
4aab8179a2 | ||
|
|
49d9b060ca | ||
|
|
d3f5b9b6ed | ||
|
|
da13c038de | ||
|
|
384cc27bba | ||
|
|
7f1ab63053 | ||
|
|
8792145c01 | ||
|
|
f1df088789 | ||
|
|
5b05a34dff | ||
|
|
c4cbc3e67c | ||
|
|
70786dc5fa | ||
|
|
1a42b87fb5 | ||
|
|
a4fb227b06 | ||
|
|
cddaba6c3f | ||
|
|
0d4ffcf74b | ||
|
|
38d6ed5f12 | ||
|
|
dd86244b4f | ||
|
|
9339c00d34 | ||
|
|
5aaa49e76d | ||
|
|
23b84e5bdd | ||
|
|
2aa4828dcb | ||
|
|
b1b62286db | ||
|
|
393681c1ee | ||
|
|
6244d9a45b | ||
|
|
ad5aaf86b6 | ||
|
|
7d731e0f34 | ||
|
|
3722dbad6c | ||
|
|
3a7eda1ef0 | ||
|
|
9065342f53 | ||
|
|
f5be003d0b | ||
|
|
9e01ebdb3a | ||
|
|
b33fbca9b7 | ||
|
|
0f1f947a72 | ||
|
|
b91e453707 | ||
|
|
0670e20421 | ||
|
|
0fa4aa632c | ||
|
|
b2e67ca278 | ||
|
|
690bdb511d | ||
|
|
e5ea4da382 | ||
|
|
7a82915de2 | ||
|
|
614c72b4d3 | ||
|
|
bd0abb3474 | ||
|
|
77ca7ea7e5 | ||
|
|
3c1e5a9189 | ||
|
|
e850afb15e | ||
|
|
2db730630e | ||
|
|
e54fb9e31f | ||
|
|
f3968897e6 | ||
|
|
b57fe57a7f | ||
|
|
f8232bb9fd | ||
|
|
4b7b5d3d09 | ||
|
|
676a62c7c2 | ||
|
|
792ad7bc33 | ||
|
|
1923f82a0f | ||
|
|
874e2a1a1b | ||
|
|
0ab2c58b6c | ||
|
|
0adf7873d1 | ||
|
|
60b6faacf6 | ||
|
|
6debc5c902 | ||
|
|
4e3523c212 | ||
|
|
762d1a0f69 | ||
|
|
5f663e708a | ||
|
|
88ad677f00 | ||
|
|
bc5efee6cb | ||
|
|
fef3c7369d | ||
|
|
337058ac94 | ||
|
|
36863449e4 | ||
|
|
4a6437d3ea | ||
|
|
09b30e9d77 | ||
|
|
777d0d7004 | ||
|
|
65204d9e6b | ||
|
|
5a078de8ad | ||
|
|
d891ddfec7 | ||
|
|
9e55ccd98e | ||
|
|
47298ffa3d | ||
|
|
ad1de0b37c | ||
|
|
1f2ba1f87f | ||
|
|
26db8cba32 | ||
|
|
0ef2986874 | ||
|
|
1079f4c855 | ||
|
|
d708438b8c | ||
|
|
206c0c71ab | ||
|
|
b77b38e40e | ||
|
|
e7dd6e2ca7 | ||
|
|
bdabb9987d | ||
|
|
0bb59a87d8 | ||
|
|
3f6c34abd2 | ||
|
|
a992967079 | ||
|
|
96c2c71cb3 | ||
|
|
99750cd37e | ||
|
|
6b223391c1 | ||
|
|
76b6ff6500 | ||
|
|
32def87c0b | ||
|
|
c43187a386 | ||
|
|
5c22402025 | ||
|
|
1efab83432 | ||
|
|
2c7f722e70 | ||
|
|
5b7c615a0a | ||
|
|
7d73a74d65 | ||
|
|
cbf1e94dd5 | ||
|
|
f22ddb30b7 | ||
|
|
f33cc7e944 | ||
|
|
a8ce679d81 | ||
|
|
08ef62531d | ||
|
|
3428eb6a9e | ||
|
|
1d895e58e7 | ||
|
|
849ec57ca6 | ||
|
|
211520b4ba | ||
|
|
bc79feb217 | ||
|
|
1ef2208349 | ||
|
|
a31a5fca17 | ||
|
|
e382746b95 | ||
|
|
575a415719 | ||
|
|
034d568d7c | ||
|
|
2928654027 | ||
|
|
e3fedc5e8c | ||
|
|
5d9cd9ac58 | ||
|
|
297757a6bf | ||
|
|
2ba3ed33c1 | ||
|
|
f5b8e27df7 | ||
|
|
ebb77c4611 | ||
|
|
cc50d90ce4 | ||
|
|
e99f40cadd | ||
|
|
640523827b | ||
|
|
dc5bd3814c | ||
|
|
04427c9934 | ||
|
|
55ec22f2e5 | ||
|
|
ce229a1708 | ||
|
|
546ce3806b | ||
|
|
de2fc251db | ||
|
|
f742b742f1 | ||
|
|
8b4c1303f4 | ||
|
|
97c98eb0cb | ||
|
|
ffeebf8da8 | ||
|
|
e33022f3f0 | ||
|
|
a62ad55c31 | ||
|
|
f447a92724 | ||
|
|
21228117ff | ||
|
|
58e61efa44 | ||
|
|
00fb7993ad | ||
|
|
c16a325439 | ||
|
|
16b1aeb745 | ||
|
|
f1cb6b83fa | ||
|
|
79b835059f | ||
|
|
55e340ce47 | ||
|
|
f772fcadfd | ||
|
|
a4ee652506 | ||
|
|
10a48f52e8 | ||
|
|
d8e1374dc3 | ||
|
|
3267469015 | ||
|
|
62bf719186 | ||
|
|
d45f35a2c8 | ||
|
|
3925d51839 | ||
|
|
dcfb257496 | ||
|
|
2b0404bf1c | ||
|
|
b3ad98cbf6 | ||
|
|
d94b32ed20 | ||
|
|
8091b7a77c | ||
|
|
ca28e65f4d | ||
|
|
4717585421 | ||
|
|
097f2ab903 | ||
|
|
316c021b44 | ||
|
|
d164df89de | ||
|
|
ee081b988f | ||
|
|
b1c9506489 | ||
|
|
f2e064d0c2 | ||
|
|
82c36a2fcc | ||
|
|
196e4409c7 | ||
|
|
50ef6f4369 | ||
|
|
356e738ee3 | ||
|
|
f6cbea13b7 | ||
|
|
6adeca446b | ||
|
|
7acd875b78 | ||
|
|
3d92edecf1 | ||
|
|
c7b98a51aa | ||
|
|
a3c8a48eed | ||
|
|
4db2eddd22 | ||
|
|
5de054b47a | ||
|
|
5dd46926c9 | ||
|
|
cb968a7763 | ||
|
|
0c4b35e07e | ||
|
|
e10de73e61 | ||
|
|
ea27a98252 | ||
|
|
a04fceee2f | ||
|
|
e8e251abc6 | ||
|
|
78bb452f8b | ||
|
|
e1cec30494 | ||
|
|
afa5f41328 | ||
|
|
84376a765a | ||
|
|
e883a2ccfa | ||
|
|
c2971f5fe6 | ||
|
|
789b1a8425 | ||
|
|
b59a3687c2 | ||
|
|
1299582047 | ||
|
|
c396834696 | ||
|
|
5a023568a6 | ||
|
|
2f7e7ad730 | ||
|
|
54d996eb03 | ||
|
|
7e7c01aadf | ||
|
|
84086cd4a2 | ||
|
|
b6f7d403d1 | ||
|
|
cf448906b3 | ||
|
|
86b3163c62 | ||
|
|
ae0dc17339 | ||
|
|
6bfcd6d9a9 | ||
|
|
8cab8c9b31 | ||
|
|
9db4a4b72f | ||
|
|
8e75498841 | ||
|
|
2c39877468 | ||
|
|
4960d86ba2 | ||
|
|
6b3a9a9bff | ||
|
|
4070a8799f | ||
|
|
0219c213ce | ||
|
|
e33543c7ea | ||
|
|
66c96dd3d1 | ||
|
|
8d21d6180a | ||
|
|
a45b5af489 | ||
|
|
9caa3638f0 | ||
|
|
da5c6ab9ae | ||
|
|
4909decbff | ||
|
|
557380682c | ||
|
|
05967332e5 | ||
|
|
394ebb673b | ||
|
|
908ca9f022 | ||
|
|
49b94644c6 | ||
|
|
3a0dd1cbe5 | ||
|
|
04b70bbf6a | ||
|
|
93448d7f34 | ||
|
|
f7b4959994 | ||
|
|
8c75c35290 | ||
|
|
8ceb4bacb2 | ||
|
|
858b107bdf | ||
|
|
17888679c7 | ||
|
|
b6ca5a8630 | ||
|
|
34f5456f51 | ||
|
|
8dbb7c0c13 | ||
|
|
0a47f34b34 | ||
|
|
d805b88c32 | ||
|
|
9b32541c0c | ||
|
|
cff2a18aa2 | ||
|
|
78820f2236 | ||
|
|
dcc307665f | ||
|
|
64235dc6d6 | ||
|
|
1a80829435 | ||
|
|
6c6666adc2 | ||
|
|
205781b921 | ||
|
|
e709b9a388 | ||
|
|
e4a57854a6 | ||
|
|
3c1885f8ef | ||
|
|
0523b94e1a | ||
|
|
7bdf67e518 | ||
|
|
7b29bac625 | ||
|
|
baca007957 | ||
|
|
654aeada0a | ||
|
|
91c9ecd3c4 | ||
|
|
f2026f1e34 | ||
|
|
e92b4ca62b | ||
|
|
6345350584 | ||
|
|
9c0d59f9c4 | ||
|
|
75f7b3303b | ||
|
|
f9bb62a91f | ||
|
|
29ede4826c | ||
|
|
896f072f67 | ||
|
|
fcef7395e8 | ||
|
|
c17a688b62 | ||
|
|
82a634845c | ||
|
|
ab322be480 | ||
|
|
0a26a8c4e3 | ||
|
|
2479efb10d | ||
|
|
dce754b693 | ||
|
|
b92ad5574a | ||
|
|
4123e20a2c | ||
|
|
df60991509 | ||
|
|
86040af754 | ||
|
|
6304aaf1c2 | ||
|
|
a6d4252a40 | ||
|
|
a7fcf86826 | ||
|
|
5bcaf99ffd | ||
|
|
629ffc55ed | ||
|
|
f27971ecb6 | ||
|
|
20859d0be4 | ||
|
|
58b9f079d2 | ||
|
|
aed7b4fa59 | ||
|
|
ebca505fef | ||
|
|
2fdd901639 | ||
|
|
b7af090f71 | ||
|
|
c4ad3b7981 | ||
|
|
22d7fc91eb | ||
|
|
e3748c1dca |
2225 changed files with 157900 additions and 70739 deletions
246
.clang-format
Normal file
246
.clang-format
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
# Clang format version: 18.1.3
|
||||||
|
---
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: BlockIndent
|
||||||
|
AlignArrayOfStructures: None
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveShortCaseStatements:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCaseColons: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments:
|
||||||
|
Kind: Always
|
||||||
|
OverEmptyLines: 0
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowBreakBeforeNoexceptSpecifier: Never
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: true
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakAdjacentStringLiterals: true
|
||||||
|
BreakAfterAttributes: Always
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakArrays: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
BreakBeforeInlineASMColon: OnlyMultiline
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 160
|
||||||
|
CommentPragmas: ""
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
EmptyLineAfterAccessModifier: Never
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IfMacros:
|
||||||
|
- KJ_IF_MAYBE
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: ^"(llvm|llvm-c|clang|clang-c)/
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: ^(<|"(gtest|gmock|isl|json)/)
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: .*
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: ""
|
||||||
|
IncludeIsMainSourceRegex: ""
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentExternBlock: NoIndent
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentRequiresClause: false
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: true
|
||||||
|
InsertBraces: true
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
IntegerLiteralSeparator:
|
||||||
|
Binary: 0
|
||||||
|
BinaryMinDigits: 0
|
||||||
|
Decimal: 0
|
||||||
|
DecimalMinDigits: 0
|
||||||
|
Hex: 0
|
||||||
|
HexMinDigits: 0
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtEOF: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
Language: Cpp
|
||||||
|
LineEnding: LF
|
||||||
|
MacroBlockBegin: ""
|
||||||
|
MacroBlockEnd: ""
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PPIndentWidth: -1
|
||||||
|
PackConstructorInitializers: BinPack
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakScopeResolution: 500
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
QualifierAlignment: Leave
|
||||||
|
ReferenceAlignment: Pointer
|
||||||
|
ReflowComments: false
|
||||||
|
RemoveBracesLLVM: false
|
||||||
|
RemoveParentheses: Leave
|
||||||
|
RemoveSemicolon: false
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
RequiresExpressionIndentation: OuterScope
|
||||||
|
SeparateDefinitionBlocks: Leave
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SkipMacroDefinitionBody: false
|
||||||
|
SortIncludes: Never
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: LexicographicNumeric
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeJsonColon: false
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterForeachMacros: true
|
||||||
|
AfterFunctionDeclarationName: false
|
||||||
|
AfterFunctionDefinitionName: false
|
||||||
|
AfterIfMacros: true
|
||||||
|
AfterOverloadedOperator: true
|
||||||
|
AfterPlacementOperator: true
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParens: Never
|
||||||
|
SpacesInParensOptions:
|
||||||
|
InConditionalStatements: false
|
||||||
|
InCStyleCasts: false
|
||||||
|
InEmptyParentheses: false
|
||||||
|
Other: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
VerilogBreakBetweenInstancePorts: true
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- STRINGIZE
|
||||||
|
BracedInitializerIndentWidth: 2
|
||||||
8
.codespellrc
Normal file
8
.codespellrc
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[codespell]
|
||||||
|
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc
|
||||||
|
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
|
||||||
|
ignore-words-list = ba,licence,ot,dout,als,exten,emac
|
||||||
|
skip = ./.git,./.licenses,__pycache__,.clang-format,.codespellrc,.editorconfig,.flake8,.prettierignore,.yamllint.yml,.gitignore,boards.txt,platform.txt,programmers.txt
|
||||||
|
builtin = clear,informal,en-GB_to_en-US
|
||||||
|
check-filenames =
|
||||||
|
check-hidden =
|
||||||
60
.editorconfig
Normal file
60
.editorconfig
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/general/.editorconfig
|
||||||
|
# See: https://editorconfig.org/
|
||||||
|
# The formatting style defined in this file is the official standardized style to be used in all Arduino Tooling
|
||||||
|
# projects and should not be modified.
|
||||||
|
# Note: indent style for each file type is defined even when it matches the universal config in order to make it clear
|
||||||
|
# that this type has an official style.
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{adoc,asc,asciidoc}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{bash,sh}]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{go,mod}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{js,jsx,json,jsonc,json5,ts,tsx}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{md,mdx,mkdn,mdown,markdown}]
|
||||||
|
indent_size = unset
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.proto]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.svg]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[{.gitconfig,.gitmodules}]
|
||||||
|
indent_style = tab
|
||||||
10
.flake8
Normal file
10
.flake8
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-python/.flake8
|
||||||
|
# See: https://flake8.pycqa.org/en/latest/user/configuration.html
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
doctests = True
|
||||||
|
# W503 and W504 are mutually exclusive. PEP 8 recommends line break before.
|
||||||
|
ignore = W503,E203
|
||||||
|
max-complexity = 20
|
||||||
|
max-line-length = 120
|
||||||
|
select = E,W,F,C,N
|
||||||
81
.github/CODEOWNERS
vendored
Normal file
81
.github/CODEOWNERS
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
# CODEOWNERS for ESP32 Arduino Core
|
||||||
|
|
||||||
|
# This file is used to specify the code owners for the ESP32 Arduino Core.
|
||||||
|
# Read more about CODEOWNERS:
|
||||||
|
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
||||||
|
# Note that order matters. The last matching pattern will be used.
|
||||||
|
|
||||||
|
# The default owners are the active developers of the ESP32 Arduino Core.
|
||||||
|
# Refrain from using @espressif/arduino-esp32 to avoid spamming non-developers with review requests.
|
||||||
|
* @espressif/arduino-devs
|
||||||
|
|
||||||
|
# CI
|
||||||
|
/.github/ @lucasssvaz @me-no-dev @P-R-O-C-H-Y
|
||||||
|
/.github/codeql/ @lucasssvaz
|
||||||
|
/.gitlab/ @lucasssvaz
|
||||||
|
/tests/ @lucasssvaz @P-R-O-C-H-Y
|
||||||
|
|
||||||
|
# Tools
|
||||||
|
/tools/ @me-no-dev
|
||||||
|
/tools/pre-commit/ @lucasssvaz
|
||||||
|
/tools/add_lib.sh @P-R-O-C-H-Y
|
||||||
|
|
||||||
|
# Pre-commit
|
||||||
|
/.* @lucasssvaz # Files in root directory that start with a dot.
|
||||||
|
|
||||||
|
# Git Files
|
||||||
|
/.gitignore @espressif/arduino-devs
|
||||||
|
/.gitmodules @espressif/arduino-devs
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
/docs/ @pedrominatel
|
||||||
|
/.github/ISSUE_TEMPLATE/ @pedrominatel
|
||||||
|
/.github/PULL_REQUEST_TEMPLATE.md @pedrominatel
|
||||||
|
/.readthedocs.yaml @pedrominatel
|
||||||
|
/*.md @pedrominatel
|
||||||
|
|
||||||
|
# Boards
|
||||||
|
/variants/ @P-R-O-C-H-Y
|
||||||
|
/boards.txt @P-R-O-C-H-Y
|
||||||
|
|
||||||
|
# Arduino as Component
|
||||||
|
/idf_component_examples/ @SuGlider
|
||||||
|
/idf_component.yml @SuGlider @me-no-dev
|
||||||
|
/CMakeLists.txt @SuGlider @me-no-dev
|
||||||
|
/Kconfig.projbuild @SuGlider @me-no-dev
|
||||||
|
|
||||||
|
# Build System
|
||||||
|
/package.json @me-no-dev
|
||||||
|
/platform.txt @me-no-dev
|
||||||
|
/programmers.txt @me-no-dev
|
||||||
|
/package/ @me-no-dev
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
/libraries/ArduinoOTA/ @me-no-dev
|
||||||
|
/libraries/AsyncUDP/ @me-no-dev
|
||||||
|
/libraries/BLE/ @lucasssvaz @SuGlider
|
||||||
|
/libraries/ESP_I2S/ @me-no-dev
|
||||||
|
/libraries/ESP_NOW/ @P-R-O-C-H-Y @lucasssvaz
|
||||||
|
/libraries/ESP_SR/ @me-no-dev
|
||||||
|
/libraries/ESPmDNS/ @me-no-dev
|
||||||
|
/libraries/Ethernet/ @me-no-dev
|
||||||
|
/libraries/Matter/ @SuGlider
|
||||||
|
/libraries/NetBIOS/ @me-no-dev
|
||||||
|
/libraries/Network/ @me-no-dev
|
||||||
|
/libraries/OpenThread/ @SuGlider
|
||||||
|
/libraries/PPP/ @me-no-dev
|
||||||
|
/libraries/SPI/ @me-no-dev
|
||||||
|
/libraries/Update/ @me-no-dev
|
||||||
|
/libraries/USB/ @SuGlider @me-no-dev
|
||||||
|
/libraries/WiFi/ @me-no-dev
|
||||||
|
/libraries/WiFiProv/ @me-no-dev
|
||||||
|
/libraries/Wire/ @me-no-dev
|
||||||
|
/libraries/Zigbee/ @P-R-O-C-H-Y
|
||||||
|
|
||||||
|
# CI JSON
|
||||||
|
# Keep this after other libraries and tests to avoid being overridden.
|
||||||
|
**/ci.json @lucasssvaz
|
||||||
|
|
||||||
|
# The CODEOWNERS file should be owned by the developers of the ESP32 Arduino Core.
|
||||||
|
# Leave this entry as the last one to avoid being overridden.
|
||||||
|
/.github/CODEOWNERS @espressif/arduino-devs
|
||||||
1
.github/ISSUE_TEMPLATE/Feature-request.yml
vendored
1
.github/ISSUE_TEMPLATE/Feature-request.yml
vendored
|
|
@ -5,6 +5,7 @@ body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
|
* Please note that we can only process feature requests reported in English to ensure effective communication and support. Feature requests written in other languages will be closed, with a request to rewrite them in English.
|
||||||
* We welcome any ideas or feature requests! It is helpful if you can explain exactly why the feature would be useful.
|
* We welcome any ideas or feature requests! It is helpful if you can explain exactly why the feature would be useful.
|
||||||
* There are usually some outstanding feature requests in the [existing issues list](https://github.com/espressif/arduino-esp32/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature+request%22), feel free to add comments to them.
|
* There are usually some outstanding feature requests in the [existing issues list](https://github.com/espressif/arduino-esp32/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature+request%22), feel free to add comments to them.
|
||||||
* If you would like to contribute, please read the [contributions guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html).
|
* If you would like to contribute, please read the [contributions guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html).
|
||||||
|
|
|
||||||
49
.github/ISSUE_TEMPLATE/Issue-report.yml
vendored
49
.github/ISSUE_TEMPLATE/Issue-report.yml
vendored
|
|
@ -5,6 +5,7 @@ body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
|
* Please note that we can only process issues reported in English to ensure effective communication and support. Issues written in other languages will be closed, with a request to rewrite them in English.
|
||||||
* Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue)
|
* Before reporting a new issue please check and search in [List of existing issues](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue)
|
||||||
* Please check [Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/index.html)
|
* Please check [Online Documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/index.html)
|
||||||
* Take a look on [Troubleshooting guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html)
|
* Take a look on [Troubleshooting guide](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html)
|
||||||
|
|
@ -24,7 +25,7 @@ body:
|
||||||
description: What development board or other hardware is the chip attached to?
|
description: What development board or other hardware is the chip attached to?
|
||||||
placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo.
|
placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: other-hw
|
id: other-hw
|
||||||
attributes:
|
attributes:
|
||||||
|
|
@ -39,8 +40,27 @@ body:
|
||||||
label: Version
|
label: Version
|
||||||
description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version.
|
description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version.
|
||||||
options:
|
options:
|
||||||
- latest master (checkout manually)
|
- latest stable Release (if not listed below)
|
||||||
- latest development Release Candidate (RC-X)
|
- latest development Release Candidate (RC-X)
|
||||||
|
- latest master (checkout manually)
|
||||||
|
- v3.3.0
|
||||||
|
- v3.2.1
|
||||||
|
- v3.2.0
|
||||||
|
- v3.1.3
|
||||||
|
- v3.1.2
|
||||||
|
- v3.1.1
|
||||||
|
- v3.1.0
|
||||||
|
- v3.0.7
|
||||||
|
- v3.0.6
|
||||||
|
- v3.0.5
|
||||||
|
- v3.0.4
|
||||||
|
- v3.0.3
|
||||||
|
- v3.0.2
|
||||||
|
- v3.0.1
|
||||||
|
- v3.0.0
|
||||||
|
- v2.0.17
|
||||||
|
- v2.0.16
|
||||||
|
- v2.0.15
|
||||||
- v2.0.14
|
- v2.0.14
|
||||||
- v2.0.13
|
- v2.0.13
|
||||||
- v2.0.12
|
- v2.0.12
|
||||||
|
|
@ -60,14 +80,25 @@ body:
|
||||||
- other
|
- other
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: type
|
||||||
|
attributes:
|
||||||
|
label: Type
|
||||||
|
description: How would you define the type of the issue? Please select from the types below.
|
||||||
|
options:
|
||||||
|
- Task
|
||||||
|
- Bug
|
||||||
|
- Question
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: IDE
|
id: IDE
|
||||||
attributes:
|
attributes:
|
||||||
label: IDE Name
|
label: IDE Name
|
||||||
description: What IDE are you using?
|
description: What IDE are you using?
|
||||||
placeholder: eg. Arduino IDE, PlatformIO, Sloeber...
|
placeholder: eg. Arduino IDE, VSCode, Sloeber...
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: os
|
id: os
|
||||||
attributes:
|
attributes:
|
||||||
|
|
@ -90,8 +121,8 @@ body:
|
||||||
label: PSRAM enabled
|
label: PSRAM enabled
|
||||||
description: Is PSRAM enabled?
|
description: Is PSRAM enabled?
|
||||||
options:
|
options:
|
||||||
- 'yes'
|
- "yes"
|
||||||
- 'no'
|
- "no"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
|
|
@ -106,8 +137,8 @@ body:
|
||||||
id: Description
|
id: Description
|
||||||
attributes:
|
attributes:
|
||||||
label: Description
|
label: Description
|
||||||
description: Please describe your problem here and expected behaviour
|
description: Please describe your problem here and expected behavior
|
||||||
placeholder: ex. Can't connect/weird behaviour/wrong function/missing parameter..
|
placeholder: ex. Can't connect/weird behavior/wrong function/missing parameter..
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|
@ -118,7 +149,7 @@ body:
|
||||||
placeholder: ex. Related part of the code to replicate the issue
|
placeholder: ex. Related part of the code to replicate the issue
|
||||||
render: cpp
|
render: cpp
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: Debug
|
id: Debug
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
||||||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
9
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,8 +1,5 @@
|
||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Arduino ESP32 Gitter Channel
|
- name: Arduino Core for Espressif Discord Server
|
||||||
url: https://gitter.im/espressif/arduino-esp32
|
url: https://discord.gg/8xY6e9crwv
|
||||||
about: Community channel for questions and help
|
about: Community Discord server for questions and help
|
||||||
- name: ESP32 Forum - Arduino
|
|
||||||
url: https://esp32.com/viewforum.php?f=19
|
|
||||||
about: Official Forum for questions
|
|
||||||
|
|
|
||||||
26
.github/codeql/codeql-config.yml
vendored
Normal file
26
.github/codeql/codeql-config.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
name: "CodeQL config"
|
||||||
|
|
||||||
|
packs:
|
||||||
|
- trailofbits/cpp-queries
|
||||||
|
- githubsecuritylab/codeql-cpp-queries
|
||||||
|
- githubsecuritylab/codeql-python-queries
|
||||||
|
|
||||||
|
queries:
|
||||||
|
- uses: security-extended
|
||||||
|
- uses: security-and-quality
|
||||||
|
|
||||||
|
query-filters:
|
||||||
|
- exclude:
|
||||||
|
query path:
|
||||||
|
- /^experimental\/.*/
|
||||||
|
- exclude:
|
||||||
|
tags contain:
|
||||||
|
- experimental
|
||||||
|
- exclude:
|
||||||
|
problem.severity:
|
||||||
|
- recommendation
|
||||||
|
- exclude:
|
||||||
|
id: tob/cpp/use-of-legacy-algorithm
|
||||||
|
|
||||||
|
paths-ignore:
|
||||||
|
- tests/**
|
||||||
5
.github/scripts/check-cmakelists.sh
vendored
5
.github/scripts/check-cmakelists.sh
vendored
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#
|
#
|
||||||
# This script is used in the CI workflow. It checks all non-examples source files in libraries/ and cores/ are listed in
|
# This script is used in the CI workflow. It checks all non-examples source files in libraries/ and cores/ are listed in
|
||||||
# CMakeLists.txt for the cmake-based IDF component
|
# CMakeLists.txt for the cmake-based IDF component
|
||||||
|
|
@ -12,10 +13,10 @@ set -e
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
# find all source files in repo
|
# find all source files in repo
|
||||||
REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
|
REPO_SRCS=$(find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort)
|
||||||
|
|
||||||
# find all source files named in CMakeLists.txt COMPONENT_SRCS
|
# find all source files named in CMakeLists.txt COMPONENT_SRCS
|
||||||
CMAKE_SRCS=`cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort`
|
CMAKE_SRCS=$(cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort)
|
||||||
|
|
||||||
if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then
|
if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then
|
||||||
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"
|
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"
|
||||||
|
|
|
||||||
30
.github/scripts/find_all_boards.sh
vendored
30
.github/scripts/find_all_boards.sh
vendored
|
|
@ -3,33 +3,37 @@
|
||||||
# Get all boards
|
# Get all boards
|
||||||
boards_array=()
|
boards_array=()
|
||||||
|
|
||||||
for line in `grep '.tarch=' boards.txt`; do
|
boards_list=$(grep '.tarch=' boards.txt)
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
|
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
|
||||||
|
# skip esp32c2 as we dont build libs for it
|
||||||
|
if [ "$board_name" == "esp32c2" ]; then
|
||||||
|
echo "Skipping 'espressif:esp32:$board_name'"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
boards_array+=("espressif:esp32:$board_name")
|
boards_array+=("espressif:esp32:$board_name")
|
||||||
echo "Added 'espressif:esp32:$board_name' to array"
|
echo "Added 'espressif:esp32:$board_name' to array"
|
||||||
done
|
done <<< "$boards_list"
|
||||||
|
|
||||||
# Create JSON like string with all boards found and pass it to env variable
|
# Create JSON like string with all boards found and pass it to env variable
|
||||||
board_count=${#boards_array[@]}
|
board_count=${#boards_array[@]}
|
||||||
echo "Boards found: $board_count"
|
echo "Boards found: $board_count"
|
||||||
echo "BOARD-COUNT=$board_count" >> $GITHUB_ENV
|
echo "BOARD-COUNT=$board_count" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
if [ $board_count -gt 0 ]
|
if [ "$board_count" -gt 0 ]; then
|
||||||
then
|
|
||||||
json_matrix='['
|
json_matrix='['
|
||||||
for board in ${boards_array[@]}
|
for board in "${boards_array[@]}"; do
|
||||||
do
|
|
||||||
json_matrix+='"'$board'"'
|
json_matrix+='"'$board'"'
|
||||||
if [ $board_count -gt 1 ]
|
if [ "$board_count" -gt 1 ]; then
|
||||||
then
|
|
||||||
json_matrix+=","
|
json_matrix+=","
|
||||||
fi
|
fi
|
||||||
board_count=$(($board_count - 1))
|
board_count=$((board_count - 1))
|
||||||
done
|
done
|
||||||
json_matrix+=']'
|
json_matrix+=']'
|
||||||
|
|
||||||
echo $json_matrix
|
echo "$json_matrix"
|
||||||
echo "FQBNS=${json_matrix}" >> $GITHUB_ENV
|
echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV"
|
||||||
else
|
else
|
||||||
echo "FQBNS=" >> $GITHUB_ENV
|
echo "FQBNS=" >> "$GITHUB_ENV"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
88
.github/scripts/find_new_boards.sh
vendored
88
.github/scripts/find_new_boards.sh
vendored
|
|
@ -2,89 +2,61 @@
|
||||||
|
|
||||||
# Get inputs from command
|
# Get inputs from command
|
||||||
owner_repository=$1
|
owner_repository=$1
|
||||||
pr_number=$2
|
base_ref=$2
|
||||||
|
|
||||||
url="https://api.github.com/repos/$owner_repository/pulls/$pr_number/files"
|
# Download the boards.txt file from the base branch
|
||||||
echo $url
|
curl -L -o boards_base.txt https://raw.githubusercontent.com/"$owner_repository"/"$base_ref"/boards.txt
|
||||||
|
|
||||||
# Get changes in boards.txt file from PR
|
# Compare boards.txt file in the repo with the modified file from PR
|
||||||
Patch=$(curl $url | jq -r '.[] | select(.filename == "boards.txt") | .patch ')
|
diff=$(diff -u boards_base.txt boards.txt)
|
||||||
|
|
||||||
# Extract only changed lines number and count
|
# Check if the diff is empty
|
||||||
substring_patch=$(echo "$Patch" | grep -o '@@[^@]*@@')
|
if [ -z "$diff" ]; then
|
||||||
|
echo "No changes in boards.txt file"
|
||||||
|
echo "FQBNS="
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
params_array=()
|
# Extract added or modified lines (lines starting with '+' or '-')
|
||||||
|
modified_lines=$(echo "$diff" | grep -E '^[+-][^+-]')
|
||||||
|
|
||||||
IFS=$'\n' read -d '' -ra params <<< $(echo "$substring_patch" | grep -oE '[-+][0-9]+,[0-9]+')
|
# Print the modified lines for debugging
|
||||||
|
echo "Modified lines:"
|
||||||
for param in "${params[@]}"
|
echo "$modified_lines"
|
||||||
do
|
|
||||||
echo "The parameter is $param"
|
|
||||||
params_array+=("$param")
|
|
||||||
done
|
|
||||||
|
|
||||||
boards_array=()
|
boards_array=()
|
||||||
previous_board=""
|
previous_board=""
|
||||||
file="boards.txt"
|
|
||||||
|
|
||||||
# Loop through boards.txt file and extract all boards that were added
|
# Extract board names from the modified lines, and add them to the boards_array
|
||||||
for (( c=0; c<${#params_array[@]}; c+=2 ))
|
while read -r line; do
|
||||||
do
|
|
||||||
deletion_count=$( echo "${params_array[c]}" | cut -d',' -f2 | cut -d' ' -f1 )
|
|
||||||
addition_line=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f1 )
|
|
||||||
addition_count=$( echo "${params_array[c+1]}" | cut -d'+' -f2 | cut -d',' -f2 | cut -d' ' -f1 )
|
|
||||||
addition_end=$(($addition_line+$addition_count))
|
|
||||||
|
|
||||||
addition_line=$(($addition_line + 3))
|
|
||||||
addition_end=$(($addition_end - $deletion_count))
|
|
||||||
|
|
||||||
echo $addition_line
|
|
||||||
echo $addition_end
|
|
||||||
|
|
||||||
i=0
|
|
||||||
|
|
||||||
while read -r line
|
|
||||||
do
|
|
||||||
i=$((i+1))
|
|
||||||
if [ $i -lt $addition_line ]
|
|
||||||
then
|
|
||||||
continue
|
|
||||||
elif [ $i -gt $addition_end ]
|
|
||||||
then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
|
board_name=$(echo "$line" | cut -d '.' -f1 | cut -d '#' -f1)
|
||||||
if [ "$board_name" != "" ]
|
# remove + or - from the board name at the beginning
|
||||||
then
|
board_name=${board_name#[-+]}
|
||||||
if [ "$board_name" != "$previous_board" ]
|
if [ "$board_name" != "" ] && [ "$board_name" != "+" ] && [ "$board_name" != "-" ] && [ "$board_name" != "esp32_family" ]; then
|
||||||
then
|
if [ "$board_name" != "$previous_board" ]; then
|
||||||
boards_array+=("espressif:esp32:$board_name")
|
boards_array+=("espressif:esp32:$board_name")
|
||||||
previous_board="$board_name"
|
previous_board="$board_name"
|
||||||
echo "Added 'espressif:esp32:$board_name' to array"
|
echo "Added 'espressif:esp32:$board_name' to array"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done < "$file"
|
done <<< "$modified_lines"
|
||||||
done
|
|
||||||
|
|
||||||
# Create JSON like string with all boards found and pass it to env variable
|
# Create JSON like string with all boards found and pass it to env variable
|
||||||
board_count=${#boards_array[@]}
|
board_count=${#boards_array[@]}
|
||||||
|
|
||||||
if [ $board_count -gt 0 ]
|
if [ "$board_count" -gt 0 ]; then
|
||||||
then
|
|
||||||
json_matrix='{"fqbn": ['
|
json_matrix='{"fqbn": ['
|
||||||
for board in ${boards_array[@]}
|
for board in "${boards_array[@]}"; do
|
||||||
do
|
|
||||||
json_matrix+='"'$board'"'
|
json_matrix+='"'$board'"'
|
||||||
if [ $board_count -gt 1 ]
|
if [ "$board_count" -gt 1 ]; then
|
||||||
then
|
|
||||||
json_matrix+=","
|
json_matrix+=","
|
||||||
fi
|
fi
|
||||||
board_count=$(($board_count - 1))
|
board_count=$((board_count - 1))
|
||||||
done
|
done
|
||||||
json_matrix+=']}'
|
json_matrix+=']}'
|
||||||
|
|
||||||
echo $json_matrix
|
echo "$json_matrix"
|
||||||
echo "FQBNS=${json_matrix}" >> $GITHUB_ENV
|
echo "FQBNS=${json_matrix}" >> "$GITHUB_ENV"
|
||||||
else
|
else
|
||||||
echo "FQBNS=" >> $GITHUB_ENV
|
echo "FQBNS=" >> "$GITHUB_ENV"
|
||||||
fi
|
fi
|
||||||
11
.github/scripts/install-arduino-cli.sh
vendored
11
.github/scripts/install-arduino-cli.sh
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
OSBITS=`arch`
|
OSBITS=$(uname -m)
|
||||||
if [[ "$OSTYPE" == "linux"* ]]; then
|
if [[ "$OSTYPE" == "linux"* ]]; then
|
||||||
export OS_IS_LINUX="1"
|
export OS_IS_LINUX="1"
|
||||||
if [[ "$OSBITS" == "i686" ]]; then
|
if [[ "$OSBITS" == "i686" ]]; then
|
||||||
|
|
@ -41,6 +41,11 @@ fi
|
||||||
if [ ! -d "$ARDUINO_IDE_PATH" ] || [ ! -f "$ARDUINO_IDE_PATH/arduino-cli" ]; then
|
if [ ! -d "$ARDUINO_IDE_PATH" ] || [ ! -f "$ARDUINO_IDE_PATH/arduino-cli" ]; then
|
||||||
echo "Installing Arduino CLI on $OS_NAME ..."
|
echo "Installing Arduino CLI on $OS_NAME ..."
|
||||||
mkdir -p "$ARDUINO_IDE_PATH"
|
mkdir -p "$ARDUINO_IDE_PATH"
|
||||||
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
|
curl -fsSL https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip -o arduino-cli.zip
|
||||||
|
unzip -q arduino-cli.zip -d "$ARDUINO_IDE_PATH"
|
||||||
|
rm arduino-cli.zip
|
||||||
|
else
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$ARDUINO_IDE_PATH" sh
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
16
.github/scripts/install-arduino-core-esp32.sh
vendored
16
.github/scripts/install-arduino-core-esp32.sh
vendored
|
|
@ -5,7 +5,7 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
|
||||||
echo "Installing ESP32 Arduino Core ..."
|
echo "Installing ESP32 Arduino Core ..."
|
||||||
script_init_path="$PWD"
|
script_init_path="$PWD"
|
||||||
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
|
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
|
||||||
cd "$ARDUINO_USR_PATH/hardware/espressif"
|
cd "$ARDUINO_USR_PATH/hardware/espressif" || exit
|
||||||
|
|
||||||
echo "Installing Python Serial ..."
|
echo "Installing Python Serial ..."
|
||||||
pip install pyserial > /dev/null
|
pip install pyserial > /dev/null
|
||||||
|
|
@ -15,21 +15,25 @@ if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
|
||||||
pip install requests > /dev/null
|
pip install requests > /dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -z "$GITHUB_REPOSITORY" ]; then
|
if [ -n "$GITHUB_REPOSITORY" ]; then
|
||||||
echo "Linking Core..."
|
echo "Linking Core..."
|
||||||
ln -s $GITHUB_WORKSPACE esp32
|
ln -s "$GITHUB_WORKSPACE" esp32
|
||||||
else
|
else
|
||||||
echo "Cloning Core Repository..."
|
echo "Cloning Core Repository..."
|
||||||
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
|
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#echo "Updating Submodules ..."
|
#echo "Updating Submodules ..."
|
||||||
cd esp32
|
cd esp32 || exit
|
||||||
#git submodule update --init --recursive > /dev/null 2>&1
|
#git submodule update --init --recursive > /dev/null 2>&1
|
||||||
|
|
||||||
echo "Installing Platform Tools ..."
|
echo "Installing Platform Tools ..."
|
||||||
cd tools && python get.py
|
if [ "$OS_IS_WINDOWS" == "1" ]; then
|
||||||
cd $script_init_path
|
cd tools && ./get.exe
|
||||||
|
else
|
||||||
|
cd tools && python get.py
|
||||||
|
fi
|
||||||
|
cd "$script_init_path" || exit
|
||||||
|
|
||||||
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
|
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
||||||
3
.github/scripts/install-arduino-ide.sh
vendored
3
.github/scripts/install-arduino-ide.sh
vendored
|
|
@ -4,7 +4,7 @@
|
||||||
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
|
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
|
||||||
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
|
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
|
||||||
|
|
||||||
OSBITS=`arch`
|
OSBITS=$(uname -m)
|
||||||
if [[ "$OSTYPE" == "linux"* ]]; then
|
if [[ "$OSTYPE" == "linux"* ]]; then
|
||||||
export OS_IS_LINUX="1"
|
export OS_IS_LINUX="1"
|
||||||
ARCHIVE_FORMAT="tar.xz"
|
ARCHIVE_FORMAT="tar.xz"
|
||||||
|
|
@ -77,4 +77,3 @@ if [ ! -d "$ARDUINO_IDE_PATH" ]; then
|
||||||
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
|
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
180
.github/scripts/install-platformio-esp32.sh
vendored
180
.github/scripts/install-platformio-esp32.sh
vendored
|
|
@ -1,180 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
|
|
||||||
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git"
|
|
||||||
|
|
||||||
TOOLCHAIN_VERSION="12.2.0+20230208"
|
|
||||||
ESPTOOLPY_VERSION="~1.40501.0"
|
|
||||||
ESPRESSIF_ORGANIZATION_NAME="espressif"
|
|
||||||
|
|
||||||
echo "Installing Python Wheel ..."
|
|
||||||
pip install wheel > /dev/null 2>&1
|
|
||||||
|
|
||||||
echo "Installing PlatformIO ..."
|
|
||||||
pip install -U https://github.com/platformio/platformio/archive/master.zip > /dev/null 2>&1
|
|
||||||
|
|
||||||
echo "Installing Platform ESP32 ..."
|
|
||||||
python -m platformio platform install $PLATFORMIO_ESP32_URL > /dev/null 2>&1
|
|
||||||
|
|
||||||
echo "Replacing the package versions ..."
|
|
||||||
replace_script="import json; import os;"
|
|
||||||
replace_script+="fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+');"
|
|
||||||
replace_script+="data=json.load(fp);"
|
|
||||||
# Use framework sources from the repository
|
|
||||||
replace_script+="data['packages']['framework-arduinoespressif32']['version'] = '*';"
|
|
||||||
replace_script+="del data['packages']['framework-arduinoespressif32']['owner'];"
|
|
||||||
# Use toolchain packages from the "espressif" organization
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32s2']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
|
|
||||||
replace_script+="data['packages']['toolchain-riscv32-esp']['owner']='$ESPRESSIF_ORGANIZATION_NAME';"
|
|
||||||
# Update versions to use the upstream
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32']['version']='$TOOLCHAIN_VERSION';"
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32s2']['version']='$TOOLCHAIN_VERSION';"
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32s3']['version']='$TOOLCHAIN_VERSION';"
|
|
||||||
replace_script+="data['packages']['toolchain-riscv32-esp']['version']='$TOOLCHAIN_VERSION';"
|
|
||||||
# Add new "framework-arduinoespressif32-libs" package
|
|
||||||
# Read "package_esp32_index.template.json" to extract a url to a zip package for "esp32-arduino-libs"
|
|
||||||
replace_script+="fpackage=open(os.path.join('package', 'package_esp32_index.template.json'), 'r+');"
|
|
||||||
replace_script+="package_data=json.load(fpackage);"
|
|
||||||
replace_script+="fpackage.close();"
|
|
||||||
replace_script+="libs_package_archive_url=next(next(system['url'] for system in tool['systems'] if system['host'] == 'x86_64-pc-linux-gnu') for tool in package_data['packages'][0]['tools'] if tool['name'] == 'esp32-arduino-libs');"
|
|
||||||
replace_script+="data['packages'].update({'framework-arduinoespressif32-libs':{'type':'framework','optional':False,'version':libs_package_archive_url}});"
|
|
||||||
replace_script+="data['packages']['toolchain-xtensa-esp32'].update({'optional':False});"
|
|
||||||
# esptool.py may require an upstream version (for now platformio is the owner)
|
|
||||||
replace_script+="data['packages']['tool-esptoolpy']['version']='$ESPTOOLPY_VERSION';"
|
|
||||||
# Save results
|
|
||||||
replace_script+="fp.seek(0);fp.truncate();json.dump(data, fp, indent=2);fp.close()"
|
|
||||||
python -c "$replace_script"
|
|
||||||
|
|
||||||
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
|
|
||||||
echo "Linking Core..."
|
|
||||||
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
|
|
||||||
else
|
|
||||||
echo "Cloning Core Repository ..."
|
|
||||||
git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "PlatformIO for ESP32 has been installed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
function build_pio_sketch(){ # build_pio_sketch <board> <options> <path-to-ino>
|
|
||||||
if [ "$#" -lt 3 ]; then
|
|
||||||
echo "ERROR: Illegal number of parameters"
|
|
||||||
echo "USAGE: build_pio_sketch <board> <options> <path-to-ino>"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local board="$1"
|
|
||||||
local options="$2"
|
|
||||||
local sketch="$3"
|
|
||||||
local sketch_dir=$(dirname "$sketch")
|
|
||||||
echo ""
|
|
||||||
echo "Compiling '"$(basename "$sketch")"' ..."
|
|
||||||
python -m platformio ci --board "$board" "$sketch_dir" --project-option="$options"
|
|
||||||
}
|
|
||||||
|
|
||||||
function count_sketches(){ # count_sketches <examples-path>
|
|
||||||
local examples="$1"
|
|
||||||
rm -rf sketches.txt
|
|
||||||
if [ ! -d "$examples" ]; then
|
|
||||||
touch sketches.txt
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
local sketches=$(find $examples -name *.ino)
|
|
||||||
local sketchnum=0
|
|
||||||
for sketch in $sketches; do
|
|
||||||
local sketchdir=$(dirname $sketch)
|
|
||||||
local sketchdirname=$(basename $sketchdir)
|
|
||||||
local sketchname=$(basename $sketch)
|
|
||||||
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [[ -f "$sketchdir/.test.skip" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
echo $sketch >> sketches.txt
|
|
||||||
sketchnum=$(($sketchnum + 1))
|
|
||||||
done
|
|
||||||
return $sketchnum
|
|
||||||
}
|
|
||||||
|
|
||||||
function build_pio_sketches(){ # build_pio_sketches <board> <options> <examples-path> <chunk> <total-chunks>
|
|
||||||
if [ "$#" -lt 3 ]; then
|
|
||||||
echo "ERROR: Illegal number of parameters"
|
|
||||||
echo "USAGE: build_pio_sketches <board> <options> <examples-path> [<chunk> <total-chunks>]"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local board=$1
|
|
||||||
local options="$2"
|
|
||||||
local examples=$3
|
|
||||||
local chunk_idex=$4
|
|
||||||
local chunks_num=$5
|
|
||||||
|
|
||||||
if [ "$#" -lt 5 ]; then
|
|
||||||
chunk_idex="0"
|
|
||||||
chunks_num="1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$chunks_num" -le 0 ]; then
|
|
||||||
echo "ERROR: Chunks count must be positive number"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if [ "$chunk_idex" -ge "$chunks_num" ]; then
|
|
||||||
echo "ERROR: Chunk index must be less than chunks count"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set +e
|
|
||||||
count_sketches "$examples"
|
|
||||||
local sketchcount=$?
|
|
||||||
set -e
|
|
||||||
local sketches=$(cat sketches.txt)
|
|
||||||
rm -rf sketches.txt
|
|
||||||
|
|
||||||
local chunk_size=$(( $sketchcount / $chunks_num ))
|
|
||||||
local all_chunks=$(( $chunks_num * $chunk_size ))
|
|
||||||
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
|
||||||
chunk_size=$(( $chunk_size + 1 ))
|
|
||||||
fi
|
|
||||||
|
|
||||||
local start_index=$(( $chunk_idex * $chunk_size ))
|
|
||||||
if [ "$sketchcount" -le "$start_index" ]; then
|
|
||||||
echo "Skipping job"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
|
|
||||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
|
||||||
end_index=$sketchcount
|
|
||||||
fi
|
|
||||||
|
|
||||||
local start_num=$(( $start_index + 1 ))
|
|
||||||
echo "Found $sketchcount Sketches";
|
|
||||||
echo "Chunk Count : $chunks_num"
|
|
||||||
echo "Chunk Size : $chunk_size"
|
|
||||||
echo "Start Sketch: $start_num"
|
|
||||||
echo "End Sketch : $end_index"
|
|
||||||
|
|
||||||
local sketchnum=0
|
|
||||||
for sketch in $sketches; do
|
|
||||||
local sketchdir=$(dirname $sketch)
|
|
||||||
local sketchdirname=$(basename $sketchdir)
|
|
||||||
local sketchname=$(basename $sketch)
|
|
||||||
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|
|
||||||
|| [ -f "$sketchdir/.test.skip" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
sketchnum=$(($sketchnum + 1))
|
|
||||||
if [ "$sketchnum" -le "$start_index" ] \
|
|
||||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
build_pio_sketch "$board" "$options" "$sketch"
|
|
||||||
local result=$?
|
|
||||||
if [ $result -ne 0 ]; then
|
|
||||||
return $result
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
74
.github/scripts/merge_packages.py
vendored
74
.github/scripts/merge_packages.py
vendored
|
|
@ -1,46 +1,55 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# This script merges two Arduino Board Manager package json files.
|
# This script merges two Arduino Board Manager package json files.
|
||||||
# Usage:
|
# Usage:
|
||||||
# python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json
|
# python merge_packages.py package_esp8266com_index.json version/new/package_esp8266com_index.json
|
||||||
# Written by Ivan Grokhotkov, 2015
|
# Written by Ivan Grokhotkov, 2015
|
||||||
|
# Updated by lucasssvaz to handle Chinese version sorting, 2025
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from distutils.version import LooseVersion
|
|
||||||
|
# from distutils.version import LooseVersion
|
||||||
|
from packaging.version import Version
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def load_package(filename):
|
def load_package(filename):
|
||||||
pkg = json.load(open(filename))['packages'][0]
|
pkg = json.load(open(filename))["packages"][0]
|
||||||
print("Loaded package {0} from {1}".format(pkg['name'], filename), file=sys.stderr)
|
print("Loaded package {0} from {1}".format(pkg["name"], filename), file=sys.stderr)
|
||||||
print("{0} platform(s), {1} tools".format(len(pkg['platforms']), len(pkg['tools'])), file=sys.stderr)
|
print("{0} platform(s), {1} tools".format(len(pkg["platforms"]), len(pkg["tools"])), file=sys.stderr)
|
||||||
return pkg
|
return pkg
|
||||||
|
|
||||||
|
|
||||||
def merge_objects(versions, obj):
|
def merge_objects(versions, obj):
|
||||||
for o in obj:
|
for o in obj:
|
||||||
name = o['name'].encode('ascii')
|
name = o["name"].encode("ascii")
|
||||||
ver = o['version'].encode('ascii')
|
ver = o["version"].encode("ascii")
|
||||||
if not name in versions:
|
if name not in versions:
|
||||||
print("found new object, {0}".format(name), file=sys.stderr)
|
print("found new object, {0}".format(name), file=sys.stderr)
|
||||||
versions[name] = {}
|
versions[name] = {}
|
||||||
if not ver in versions[name]:
|
if ver not in versions[name]:
|
||||||
print("found new version {0} for object {1}".format(ver, name), file=sys.stderr)
|
print("found new version {0} for object {1}".format(ver, name), file=sys.stderr)
|
||||||
versions[name][ver] = o
|
versions[name][ver] = o
|
||||||
return versions
|
return versions
|
||||||
|
|
||||||
# Normalize ESP release version string (x.x.x) by adding '-rc<MAXINT>' (x.x.x-rc9223372036854775807) to ensure having REL above any RC
|
|
||||||
# Dummy approach, functional anyway for current ESP package versioning (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap)
|
|
||||||
def pkgVersionNormalized(versionString):
|
|
||||||
|
|
||||||
verStr = str(versionString)
|
# Normalize ESP release version string (x.x.x) by adding '-rc<MAXINT>' (x.x.x-rc9223372036854775807)
|
||||||
verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE)
|
# to ensure having REL above any RC. CN version will be sorted after the official version if they happen
|
||||||
|
# to be mixed (normally, CN and non-CN versions should not be mixed)
|
||||||
|
# Dummy approach, functional anyway for current ESP package versioning
|
||||||
|
# (unlike NormalizedVersion/LooseVersion/StrictVersion & similar crap)
|
||||||
|
def pkgVersionNormalized(versionString):
|
||||||
|
verStr = str(versionString).replace("-cn", "")
|
||||||
|
verParts = re.split(r"\.|-rc|-alpha", verStr, flags=re.IGNORECASE)
|
||||||
|
|
||||||
if len(verParts) == 3:
|
if len(verParts) == 3:
|
||||||
if (sys.version_info > (3, 0)): # Python 3
|
if "-cn" in str(versionString):
|
||||||
verStr = str(versionString) + '-rc' + str(sys.maxsize)
|
verStr = verStr + "-rc" + str(sys.maxsize // 2)
|
||||||
else: # Python 2
|
else:
|
||||||
verStr = str(versionString) + '-rc' + str(sys.maxint)
|
verStr = verStr + "-rc" + str(sys.maxsize)
|
||||||
|
|
||||||
elif len(verParts) != 4:
|
elif len(verParts) != 4:
|
||||||
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
|
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)
|
||||||
|
|
||||||
|
|
@ -55,28 +64,35 @@ def main(args):
|
||||||
tools = {}
|
tools = {}
|
||||||
platforms = {}
|
platforms = {}
|
||||||
pkg1 = load_package(args[1])
|
pkg1 = load_package(args[1])
|
||||||
tools = merge_objects(tools, pkg1['tools']);
|
tools = merge_objects(tools, pkg1["tools"])
|
||||||
platforms = merge_objects(platforms, pkg1['platforms']);
|
platforms = merge_objects(platforms, pkg1["platforms"])
|
||||||
pkg2 = load_package(args[2])
|
pkg2 = load_package(args[2])
|
||||||
tools = merge_objects(tools, pkg2['tools']);
|
tools = merge_objects(tools, pkg2["tools"])
|
||||||
platforms = merge_objects(platforms, pkg2['platforms']);
|
platforms = merge_objects(platforms, pkg2["platforms"])
|
||||||
|
|
||||||
pkg1['tools'] = []
|
pkg1["tools"] = []
|
||||||
pkg1['platforms'] = []
|
pkg1["platforms"] = []
|
||||||
|
|
||||||
for name in tools:
|
for name in tools:
|
||||||
for version in tools[name]:
|
for version in tools[name]:
|
||||||
print("Adding tool {0}-{1}".format(name, version), file=sys.stderr)
|
print("Adding tool {0}-{1}".format(name, version), file=sys.stderr)
|
||||||
pkg1['tools'].append(tools[name][version])
|
pkg1["tools"].append(tools[name][version])
|
||||||
|
|
||||||
for name in platforms:
|
for name in platforms:
|
||||||
for version in platforms[name]:
|
for version in platforms[name]:
|
||||||
print("Adding platform {0}-{1}".format(name, version), file=sys.stderr)
|
print("Adding platform {0}-{1}".format(name, version), file=sys.stderr)
|
||||||
pkg1['platforms'].append(platforms[name][version])
|
pkg1["platforms"].append(platforms[name][version])
|
||||||
|
|
||||||
pkg1['platforms'] = sorted(pkg1['platforms'], key=lambda k: LooseVersion(pkgVersionNormalized(k['version'])), reverse=True)
|
# pkg1["platforms"] = sorted(
|
||||||
|
# pkg1["platforms"], key=lambda k: LooseVersion(pkgVersionNormalized(k["version"])), reverse=True
|
||||||
|
# )
|
||||||
|
|
||||||
json.dump({'packages':[pkg1]}, sys.stdout, indent=2)
|
pkg1["platforms"] = sorted(
|
||||||
|
pkg1["platforms"], key=lambda k: Version(pkgVersionNormalized(k["version"])), reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
json.dump({"packages": [pkg1]}, sys.stdout, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
sys.exit(main(sys.argv))
|
sys.exit(main(sys.argv))
|
||||||
|
|
|
||||||
69
.github/scripts/on-pages.sh
vendored
69
.github/scripts/on-pages.sh
vendored
|
|
@ -1,12 +1,13 @@
|
||||||
#/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
function get_file_size(){
|
function get_file_size {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
eval `stat -s "$file"`
|
eval "$(stat -s "$file")"
|
||||||
local res="$?"
|
local res="$?"
|
||||||
echo "$st_size"
|
echo "${st_size:?}"
|
||||||
return $res
|
return $res
|
||||||
else
|
else
|
||||||
stat --printf="%s" "$file"
|
stat --printf="%s" "$file"
|
||||||
|
|
@ -15,25 +16,32 @@ function get_file_size(){
|
||||||
}
|
}
|
||||||
|
|
||||||
#git_remove_from_pages <file>
|
#git_remove_from_pages <file>
|
||||||
function git_remove_from_pages(){
|
function git_remove_from_pages {
|
||||||
local path=$1
|
local path=$1
|
||||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
local info
|
||||||
local type=`echo "$info" | jq -r '.type'`
|
local type
|
||||||
if [ ! $type == "file" ]; then
|
local sha
|
||||||
if [ ! $type == "null" ]; then
|
local message
|
||||||
|
|
||||||
|
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages")
|
||||||
|
type=$(echo "$info" | jq -r '.type')
|
||||||
|
|
||||||
|
if [ ! "$type" == "file" ]; then
|
||||||
|
if [ ! "$type" == "null" ]; then
|
||||||
echo "Wrong type '$type'"
|
echo "Wrong type '$type'"
|
||||||
else
|
else
|
||||||
echo "File is not on Pages"
|
echo "File is not on Pages"
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
local sha=`echo "$info" | jq -r '.sha'`
|
|
||||||
local message="Deleting "$(basename $path)
|
sha=$(echo "$info" | jq -r '.sha')
|
||||||
|
message="Deleting "$(basename "$path")
|
||||||
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
|
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
|
||||||
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_upload_to_pages(){
|
function git_upload_to_pages {
|
||||||
local path=$1
|
local path=$1
|
||||||
local src=$2
|
local src=$2
|
||||||
|
|
||||||
|
|
@ -42,41 +50,50 @@ function git_upload_to_pages(){
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
local info
|
||||||
local type=`echo "$info" | jq -r '.type'`
|
local type
|
||||||
local message=$(basename $path)
|
local message
|
||||||
local sha=""
|
local sha=""
|
||||||
local content=""
|
local content=""
|
||||||
|
|
||||||
if [ $type == "file" ]; then
|
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages")
|
||||||
sha=`echo "$info" | jq -r '.sha'`
|
type=$(echo "$info" | jq -r '.type')
|
||||||
|
message=$(basename "$path")
|
||||||
|
|
||||||
|
if [ "$type" == "file" ]; then
|
||||||
|
sha=$(echo "$info" | jq -r '.sha')
|
||||||
sha=",\"sha\":\"$sha\""
|
sha=",\"sha\":\"$sha\""
|
||||||
message="Updating $message"
|
message="Updating $message"
|
||||||
elif [ ! $type == "null" ]; then
|
elif [ ! "$type" == "null" ]; then
|
||||||
>&2 echo "Wrong type '$type'"
|
>&2 echo "Wrong type '$type'"
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
message="Creating $message"
|
message="Creating $message"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
content=`base64 -i "$src"`
|
content=$(base64 -i "$src")
|
||||||
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||||
|
|
||||||
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_safe_upload_to_pages(){
|
function git_safe_upload_to_pages {
|
||||||
local path=$1
|
local path=$1
|
||||||
local file="$2"
|
local file="$2"
|
||||||
local name=$(basename "$file")
|
local name
|
||||||
local size=`get_file_size "$file"`
|
local size
|
||||||
local upload_res=`git_upload_to_pages "$path" "$file"`
|
local upload_res
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
|
name=$(basename "$file")
|
||||||
|
size=$(get_file_size "$file")
|
||||||
|
|
||||||
|
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
|
||||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
|
||||||
if [ $up_size -ne $size ]; then
|
up_size=$(echo "$upload_res" | jq -r '.content.size')
|
||||||
|
if [ "$up_size" -ne "$size" ]; then
|
||||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
#git_delete_asset
|
#git_delete_asset
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
33
.github/scripts/on-push-idf.sh
vendored
Normal file
33
.github/scripts/on-push-idf.sh
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CHECK_REQUIREMENTS="./components/arduino-esp32/.github/scripts/sketch_utils.sh check_requirements"
|
||||||
|
|
||||||
|
# Export IDF environment
|
||||||
|
. ${IDF_PATH}/export.sh
|
||||||
|
|
||||||
|
# Find all examples in ./components/arduino-esp32/idf_component_examples
|
||||||
|
idf_component_examples=$(find ./components/arduino-esp32/idf_component_examples -mindepth 1 -maxdepth 1 -type d)
|
||||||
|
|
||||||
|
for example in $idf_component_examples; do
|
||||||
|
if [ -f "$example"/ci.json ]; then
|
||||||
|
# If the target is listed as false, skip the sketch. Otherwise, include it.
|
||||||
|
is_target=$(jq -r --arg target "$IDF_TARGET" '.targets[$target]' "$example"/ci.json)
|
||||||
|
if [[ "$is_target" == "false" ]]; then
|
||||||
|
printf "\n\033[93mSkipping %s for target %s\033[0m\n\n" "$example" "$IDF_TARGET"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
idf.py -C "$example" set-target "$IDF_TARGET"
|
||||||
|
|
||||||
|
has_requirements=$(${CHECK_REQUIREMENTS} "$example" "$example/sdkconfig")
|
||||||
|
if [ "$has_requirements" -eq 0 ]; then
|
||||||
|
printf "\n\033[93m%s does not meet the requirements for %s. Skipping...\033[0m\n\n" "$example" "$IDF_TARGET"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\n\033[95mBuilding %s\033[0m\n\n" "$example"
|
||||||
|
idf.py -C "$example" -DEXTRA_COMPONENT_DIRS="$PWD/components" build
|
||||||
|
done
|
||||||
130
.github/scripts/on-push.sh
vendored
130
.github/scripts/on-push.sh
vendored
|
|
@ -4,36 +4,45 @@ set -e
|
||||||
|
|
||||||
export ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
|
export ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
|
||||||
|
|
||||||
function build(){
|
function build {
|
||||||
local target=$1
|
local target=$1
|
||||||
local fqbn=$2
|
local chunk_index=$2
|
||||||
local chunk_index=$3
|
local chunks_cnt=$3
|
||||||
local chunks_cnt=$4
|
local build_log=$4
|
||||||
shift; shift; shift; shift;
|
local log_level=${5:-none}
|
||||||
local sketches=$*
|
local sketches_file=$6
|
||||||
|
shift 6
|
||||||
|
local sketches=("$@")
|
||||||
|
|
||||||
local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build"
|
local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build"
|
||||||
local BUILD_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
|
local BUILD_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
|
||||||
|
|
||||||
local args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH"
|
local args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH" "-t" "$target")
|
||||||
|
|
||||||
args+=" -t $target -fqbn $fqbn"
|
|
||||||
|
|
||||||
if [ "$OS_IS_LINUX" == "1" ]; then
|
if [ "$OS_IS_LINUX" == "1" ]; then
|
||||||
args+=" -p $ARDUINO_ESP32_PATH/libraries"
|
args+=("-p" "$ARDUINO_ESP32_PATH/libraries" "-i" "$chunk_index" "-m" "$chunks_cnt" "-d" "$log_level")
|
||||||
args+=" -i $chunk_index -m $chunks_cnt"
|
if [ -n "$sketches_file" ]; then
|
||||||
${BUILD_SKETCHES} ${args}
|
args+=("-f" "$sketches_file")
|
||||||
|
fi
|
||||||
|
if [ "$build_log" -eq 1 ]; then
|
||||||
|
args+=("-l" "$build_log")
|
||||||
|
fi
|
||||||
|
${BUILD_SKETCHES} "${args[@]}"
|
||||||
else
|
else
|
||||||
for sketch in ${sketches}; do
|
for sketch in "${sketches[@]}"; do
|
||||||
local sargs="$args -s $(dirname $sketch)"
|
local sargs=("${args[@]}")
|
||||||
|
local ctags_version
|
||||||
|
local preprocessor_version
|
||||||
|
sargs+=("-s" "$(dirname "$sketch")")
|
||||||
if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then
|
if [ "$OS_IS_WINDOWS" == "1" ] && [ -d "$ARDUINO_IDE_PATH/tools-builder" ]; then
|
||||||
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
|
ctags_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/ctags/")
|
||||||
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
|
preprocessor_version=$(ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/")
|
||||||
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version
|
sargs+=(
|
||||||
-prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
|
"-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version"
|
||||||
sargs+=" ${win_opts}"
|
"-prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
${BUILD_SKETCH} ${sargs}
|
${BUILD_SKETCH} "${sargs[@]}"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
@ -45,61 +54,54 @@ fi
|
||||||
|
|
||||||
CHUNK_INDEX=$1
|
CHUNK_INDEX=$1
|
||||||
CHUNKS_CNT=$2
|
CHUNKS_CNT=$2
|
||||||
BUILD_PIO=0
|
BUILD_LOG=$3
|
||||||
|
LOG_LEVEL=$4
|
||||||
|
SKETCHES_FILE=$5
|
||||||
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
|
||||||
CHUNK_INDEX=0
|
CHUNK_INDEX=0
|
||||||
CHUNKS_CNT=1
|
CHUNKS_CNT=1
|
||||||
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
|
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
|
||||||
CHUNK_INDEX=$CHUNKS_CNT
|
CHUNK_INDEX=$CHUNKS_CNT
|
||||||
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
|
fi
|
||||||
BUILD_PIO=1
|
|
||||||
|
if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then
|
||||||
|
BUILD_LOG=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#echo "Updating submodules ..."
|
#echo "Updating submodules ..."
|
||||||
#git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
#git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
|
||||||
|
|
||||||
SCRIPTS_DIR="./.github/scripts"
|
SCRIPTS_DIR="./.github/scripts"
|
||||||
if [ "$BUILD_PIO" -eq 0 ]; then
|
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
|
||||||
#source ${SCRIPTS_DIR}/install-arduino-ide.sh
|
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh"
|
||||||
source ${SCRIPTS_DIR}/install-arduino-cli.sh
|
|
||||||
source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
|
|
||||||
|
|
||||||
FQBN_ESP32="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
|
SKETCHES_ESP32=(
|
||||||
FQBN_ESP32S2="espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app"
|
"$ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
|
||||||
FQBN_ESP32S3="espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app"
|
"$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino"
|
||||||
FQBN_ESP32C3="espressif:esp32:esp32c3:PartitionScheme=huge_app"
|
"$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
||||||
FQBN_ESP32C6="espressif:esp32:esp32c6:PartitionScheme=huge_app"
|
"$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino"
|
||||||
FQBN_ESP32H2="espressif:esp32:esp32h2:PartitionScheme=huge_app"
|
)
|
||||||
|
#create sizes_file
|
||||||
|
sizes_file="$GITHUB_WORKSPACE/cli_compile_$CHUNK_INDEX.json"
|
||||||
|
|
||||||
SKETCHES_ESP32="\
|
if [ "$BUILD_LOG" -eq 1 ]; then
|
||||||
$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\
|
#create sizes_file and echo start of JSON array with "boards" key
|
||||||
$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\
|
echo "{\"boards\": [" > "$sizes_file"
|
||||||
$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\
|
fi
|
||||||
$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\
|
|
||||||
"
|
#build sketches for different targets
|
||||||
|
build "esp32c5" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32s3" $FQBN_ESP32S3 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32s2" $FQBN_ESP32S2 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32c3" $FQBN_ESP32C3 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32c6" $FQBN_ESP32C6 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32h2" $FQBN_ESP32H2 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
build "esp32" $FQBN_ESP32 $CHUNK_INDEX $CHUNKS_CNT $SKETCHES_ESP32
|
build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
else
|
build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}"
|
||||||
source ${SCRIPTS_DIR}/install-platformio-esp32.sh
|
|
||||||
# PlatformIO ESP32 Test
|
if [ "$BUILD_LOG" -eq 1 ]; then
|
||||||
BOARD="esp32dev"
|
#remove last comma from the last JSON object
|
||||||
OPTIONS="board_build.partitions = huge_app.csv"
|
sed -i '$ s/,$//' "$sizes_file"
|
||||||
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
|
#echo end of JSON array
|
||||||
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
|
echo "]}" >> "$sizes_file"
|
||||||
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
|
|
||||||
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" && \
|
|
||||||
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
|
|
||||||
|
|
||||||
# Basic sanity testing for other series
|
|
||||||
for board in "esp32-c3-devkitm-1" "esp32-s2-saola-1" "esp32-s3-devkitc-1"
|
|
||||||
do
|
|
||||||
python -m platformio ci --board "$board" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient" --project-option="board_build.partitions = huge_app.csv"
|
|
||||||
done
|
|
||||||
|
|
||||||
#build_pio_sketches "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries"
|
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
338
.github/scripts/on-release.sh
vendored
338
.github/scripts/on-release.sh
vendored
|
|
@ -1,52 +1,65 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Disable shellcheck warning about using 'cat' to read a file.
|
||||||
|
# Disable shellcheck warning about using individual redirections for each command.
|
||||||
|
# Disable shellcheck warning about $? uses.
|
||||||
|
# shellcheck disable=SC2002,SC2129,SC2181,SC2319
|
||||||
|
|
||||||
if [ ! $GITHUB_EVENT_NAME == "release" ]; then
|
if [ ! "$GITHUB_EVENT_NAME" == "release" ]; then
|
||||||
echo "Wrong event '$GITHUB_EVENT_NAME'!"
|
echo "Wrong event '$GITHUB_EVENT_NAME'!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
|
EVENT_JSON=$(cat "$GITHUB_EVENT_PATH")
|
||||||
|
|
||||||
action=`echo $EVENT_JSON | jq -r '.action'`
|
action=$(echo "$EVENT_JSON" | jq -r '.action')
|
||||||
if [ ! $action == "published" ]; then
|
if [ ! "$action" == "published" ]; then
|
||||||
echo "Wrong action '$action'. Exiting now..."
|
echo "Wrong action '$action'. Exiting now..."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
draft=`echo $EVENT_JSON | jq -r '.release.draft'`
|
draft=$(echo "$EVENT_JSON" | jq -r '.release.draft')
|
||||||
if [ $draft == "true" ]; then
|
if [ "$draft" == "true" ]; then
|
||||||
echo "It's a draft release. Exiting now..."
|
echo "It's a draft release. Exiting now..."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
|
RELEASE_PRE=$(echo "$EVENT_JSON" | jq -r '.release.prerelease')
|
||||||
RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
|
RELEASE_TAG=$(echo "$EVENT_JSON" | jq -r '.release.tag_name')
|
||||||
RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
|
RELEASE_BRANCH=$(echo "$EVENT_JSON" | jq -r '.release.target_commitish')
|
||||||
RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
|
RELEASE_ID=$(echo "$EVENT_JSON" | jq -r '.release.id')
|
||||||
|
|
||||||
|
SCRIPTS_DIR="./.github/scripts"
|
||||||
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
|
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
|
||||||
PACKAGE_NAME="esp32-$RELEASE_TAG"
|
PACKAGE_NAME="esp32-$RELEASE_TAG"
|
||||||
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
|
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
|
||||||
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
|
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
|
||||||
PACKAGE_JSON_DEV="package_esp32_dev_index.json"
|
PACKAGE_JSON_DEV="package_esp32_dev_index.json"
|
||||||
PACKAGE_JSON_REL="package_esp32_index.json"
|
PACKAGE_JSON_REL="package_esp32_index.json"
|
||||||
|
PACKAGE_JSON_DEV_CN="package_esp32_dev_index_cn.json"
|
||||||
|
PACKAGE_JSON_REL_CN="package_esp32_index_cn.json"
|
||||||
|
|
||||||
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
|
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
|
||||||
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
|
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
|
||||||
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
|
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
|
||||||
|
|
||||||
# Try extracting something like a JSON with a "boards" array/element and "vendor" fields
|
# Try extracting something like a JSON with a "boards" array/element and "vendor" fields
|
||||||
BOARDS=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null`
|
BOARDS=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.boards[]? // .boards? // empty' | xargs echo -n 2>/dev/null)
|
||||||
VENDOR=`echo $RELEASE_BODY | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null`
|
VENDOR=$(echo "$RELEASE_BODY" | grep -Pzo '(?s){.*}' | jq -r '.vendor? // empty' | xargs echo -n 2>/dev/null)
|
||||||
if ! [ -z "${BOARDS}" ]; then echo "Releasing board(s): $BOARDS" ; fi
|
|
||||||
if ! [ -z "${VENDOR}" ]; then echo "Setting packager: $VENDOR" ; fi
|
|
||||||
|
|
||||||
function get_file_size(){
|
if [ -n "${BOARDS}" ]; then
|
||||||
|
echo "Releasing board(s): $BOARDS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${VENDOR}" ]; then
|
||||||
|
echo "Setting packager: $VENDOR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
function get_file_size {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
eval `stat -s "$file"`
|
eval "$(stat -s "$file")"
|
||||||
local res="$?"
|
local res="$?"
|
||||||
echo "$st_size"
|
echo "${st_size:?}"
|
||||||
return $res
|
return $res
|
||||||
else
|
else
|
||||||
stat --printf="%s" "$file"
|
stat --printf="%s" "$file"
|
||||||
|
|
@ -54,23 +67,29 @@ function get_file_size(){
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_upload_asset(){
|
function git_upload_asset {
|
||||||
local name=$(basename "$1")
|
local name
|
||||||
|
name=$(basename "$1")
|
||||||
# local mime=$(file -b --mime-type "$1")
|
# local mime=$(file -b --mime-type "$1")
|
||||||
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
|
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_safe_upload_asset(){
|
function git_safe_upload_asset {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
local name=$(basename "$file")
|
local name
|
||||||
local size=`get_file_size "$file"`
|
local size
|
||||||
local upload_res=`git_upload_asset "$file"`
|
local upload_res
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
|
name=$(basename "$file")
|
||||||
|
size=$(get_file_size "$file")
|
||||||
|
|
||||||
|
if ! upload_res=$(git_upload_asset "$file"); then
|
||||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
up_size=`echo "$upload_res" | jq -r '.size'`
|
|
||||||
if [ $up_size -ne $size ]; then
|
up_size=$(echo "$upload_res" | jq -r '.size')
|
||||||
|
if [ "$up_size" -ne "$size" ]; then
|
||||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
#git_delete_asset
|
#git_delete_asset
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -79,7 +98,7 @@ function git_safe_upload_asset(){
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_upload_to_pages(){
|
function git_upload_to_pages {
|
||||||
local path=$1
|
local path=$1
|
||||||
local src=$2
|
local src=$2
|
||||||
|
|
||||||
|
|
@ -88,41 +107,50 @@ function git_upload_to_pages(){
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
|
local info
|
||||||
local type=`echo "$info" | jq -r '.type'`
|
local type
|
||||||
local message=$(basename $path)
|
local message
|
||||||
local sha=""
|
local sha=""
|
||||||
local content=""
|
local content=""
|
||||||
|
|
||||||
if [ $type == "file" ]; then
|
info=$(curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages")
|
||||||
sha=`echo "$info" | jq -r '.sha'`
|
type=$(echo "$info" | jq -r '.type')
|
||||||
|
message=$(basename "$path")
|
||||||
|
|
||||||
|
if [ "$type" == "file" ]; then
|
||||||
|
sha=$(echo "$info" | jq -r '.sha')
|
||||||
sha=",\"sha\":\"$sha\""
|
sha=",\"sha\":\"$sha\""
|
||||||
message="Updating $message"
|
message="Updating $message"
|
||||||
elif [ ! $type == "null" ]; then
|
elif [ ! "$type" == "null" ]; then
|
||||||
>&2 echo "Wrong type '$type'"
|
>&2 echo "Wrong type '$type'"
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
message="Creating $message"
|
message="Creating $message"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
content=`base64 -i "$src"`
|
content=$(base64 -i "$src")
|
||||||
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
|
||||||
|
|
||||||
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
|
||||||
}
|
}
|
||||||
|
|
||||||
function git_safe_upload_to_pages(){
|
function git_safe_upload_to_pages {
|
||||||
local path=$1
|
local path=$1
|
||||||
local file="$2"
|
local file="$2"
|
||||||
local name=$(basename "$file")
|
local name
|
||||||
local size=`get_file_size "$file"`
|
local size
|
||||||
local upload_res=`git_upload_to_pages "$path" "$file"`
|
local upload_res
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
|
name=$(basename "$file")
|
||||||
|
size=$(get_file_size "$file")
|
||||||
|
|
||||||
|
if ! upload_res=$(git_upload_to_pages "$path" "$file"); then
|
||||||
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
>&2 echo "ERROR: Failed to upload '$name' ($?)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
up_size=`echo "$upload_res" | jq -r '.content.size'`
|
|
||||||
if [ $up_size -ne $size ]; then
|
up_size=$(echo "$upload_res" | jq -r '.content.size')
|
||||||
|
if [ "$up_size" -ne "$size" ]; then
|
||||||
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
|
||||||
#git_delete_asset
|
#git_delete_asset
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -131,15 +159,20 @@ function git_safe_upload_to_pages(){
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge_package_json(){
|
function merge_package_json {
|
||||||
local jsonLink=$1
|
local jsonLink=$1
|
||||||
local jsonOut=$2
|
local jsonOut=$2
|
||||||
local old_json=$OUTPUT_DIR/oldJson.json
|
local old_json=$OUTPUT_DIR/oldJson.json
|
||||||
local merged_json=$OUTPUT_DIR/mergedJson.json
|
local merged_json=$OUTPUT_DIR/mergedJson.json
|
||||||
|
local error_code=0
|
||||||
|
|
||||||
echo "Downloading previous JSON $jsonLink ..."
|
echo "Downloading previous JSON $jsonLink ..."
|
||||||
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
|
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
|
||||||
if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
|
error_code=$?
|
||||||
|
if [ $error_code -ne 0 ]; then
|
||||||
|
echo "ERROR: Download Failed! $error_code"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Creating new JSON ..."
|
echo "Creating new JSON ..."
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -147,7 +180,7 @@ function merge_package_json(){
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
set -v
|
set -v
|
||||||
if [ ! -s $merged_json ]; then
|
if [ ! -s "$merged_json" ]; then
|
||||||
rm -f "$merged_json"
|
rm -f "$merged_json"
|
||||||
echo "Nothing to merge"
|
echo "Nothing to merge"
|
||||||
else
|
else
|
||||||
|
|
@ -188,10 +221,14 @@ else
|
||||||
done
|
done
|
||||||
# Copy only relevant variant files
|
# Copy only relevant variant files
|
||||||
mkdir "$PKG_DIR/variants/"
|
mkdir "$PKG_DIR/variants/"
|
||||||
for variant in `cat ${PKG_DIR}/boards.txt | grep "\.variant=" | cut -d= -f2` ; do
|
board_list=$(cat "${PKG_DIR}"/boards.txt | grep "\.variant=" | cut -d= -f2)
|
||||||
|
while IFS= read -r variant; do
|
||||||
cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/"
|
cp -Rf "$GITHUB_WORKSPACE/variants/${variant}" "$PKG_DIR/variants/"
|
||||||
done
|
done <<< "$board_list"
|
||||||
fi
|
fi
|
||||||
|
cp -f "$GITHUB_WORKSPACE/CMakeLists.txt" "$PKG_DIR/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/idf_component.yml" "$PKG_DIR/"
|
||||||
|
cp -f "$GITHUB_WORKSPACE/Kconfig.projbuild" "$PKG_DIR/"
|
||||||
cp -f "$GITHUB_WORKSPACE/package.json" "$PKG_DIR/"
|
cp -f "$GITHUB_WORKSPACE/package.json" "$PKG_DIR/"
|
||||||
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
|
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
|
||||||
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
|
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
|
||||||
|
|
@ -204,7 +241,7 @@ cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.py" "$PKG_DIR/tools/"
|
||||||
cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.exe" "$PKG_DIR/tools/"
|
cp -f "$GITHUB_WORKSPACE/tools/gen_insights_package.exe" "$PKG_DIR/tools/"
|
||||||
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
|
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
|
||||||
cp -Rf "$GITHUB_WORKSPACE/tools/ide-debug" "$PKG_DIR/tools/"
|
cp -Rf "$GITHUB_WORKSPACE/tools/ide-debug" "$PKG_DIR/tools/"
|
||||||
cp -f "$GITHUB_WORKSPACE/tools/platformio-build.py" "$PKG_DIR/tools/"
|
cp -f "$GITHUB_WORKSPACE/tools/pioarduino-build.py" "$PKG_DIR/tools/"
|
||||||
|
|
||||||
# Remove unnecessary files in the package folder
|
# Remove unnecessary files in the package folder
|
||||||
echo "Cleaning up folders ..."
|
echo "Cleaning up folders ..."
|
||||||
|
|
@ -216,47 +253,50 @@ find "$PKG_DIR" -name '*.git*' -type f -delete
|
||||||
##
|
##
|
||||||
RVTC_NAME="riscv32-esp-elf-gcc"
|
RVTC_NAME="riscv32-esp-elf-gcc"
|
||||||
RVTC_NEW_NAME="esp-rv32"
|
RVTC_NEW_NAME="esp-rv32"
|
||||||
|
X32TC_NAME="xtensa-esp-elf-gcc"
|
||||||
|
X32TC_NEW_NAME="esp-x32"
|
||||||
|
|
||||||
# Replace tools locations in platform.txt
|
# Replace tools locations in platform.txt
|
||||||
echo "Generating platform.txt..."
|
echo "Generating platform.txt..."
|
||||||
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
cat "$GITHUB_WORKSPACE/platform.txt" | \
|
||||||
sed "s/version=.*/version=$RELEASE_TAG/g" | \
|
sed "s/version=.*/version=$RELEASE_TAG/g" | \
|
||||||
|
sed 's/tools\.esp32-arduino-libs\.path\.windows=.*//g' | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \
|
sed 's/{runtime\.platform\.path}.tools.esp32-arduino-libs/\{runtime.tools.esp32-arduino-libs.path\}/g' | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \
|
sed 's/{runtime\.platform\.path}.tools.xtensa-esp-elf-gdb/\{runtime.tools.xtensa-esp-elf-gdb.path\}/g' | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.xtensa-esp32-elf/\{runtime.tools.xtensa-esp32-elf-gcc.path\}/g' | \
|
sed "s/{runtime\.platform\.path}.tools.xtensa-esp-elf/\\{runtime.tools.$X32TC_NEW_NAME.path\\}/g" | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.xtensa-esp32s2-elf/\{runtime.tools.xtensa-esp32s2-elf-gcc.path\}/g' | \
|
|
||||||
sed 's/{runtime\.platform\.path}.tools.xtensa-esp32s3-elf/\{runtime.tools.xtensa-esp32s3-elf-gcc.path\}/g' | \
|
|
||||||
sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \
|
sed 's/{runtime\.platform\.path}.tools.riscv32-esp-elf-gdb/\{runtime.tools.riscv32-esp-elf-gdb.path\}/g' | \
|
||||||
sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \
|
sed "s/{runtime\.platform\.path}.tools.riscv32-esp-elf/\\{runtime.tools.$RVTC_NEW_NAME.path\\}/g" | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \
|
sed 's/{runtime\.platform\.path}.tools.esptool/\{runtime.tools.esptool_py.path\}/g' | \
|
||||||
sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' \
|
sed 's/{runtime\.platform\.path}.tools.openocd-esp32/\{runtime.tools.openocd-esp32.path\}/g' > "$PKG_DIR/platform.txt"
|
||||||
> "$PKG_DIR/platform.txt"
|
|
||||||
|
|
||||||
if ! [ -z ${VENDOR} ]; then
|
if [ -n "${VENDOR}" ]; then
|
||||||
# Append vendor name to platform.txt to create a separate section
|
# Append vendor name to platform.txt to create a separate section
|
||||||
sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt"
|
sed -i "/^name=.*/s/$/ ($VENDOR)/" "$PKG_DIR/platform.txt"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add header with version information
|
# Add header with version information
|
||||||
echo "Generating core_version.h ..."
|
echo "Generating core_version.h ..."
|
||||||
ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
|
ver_define=$(echo "$RELEASE_TAG" | tr "[:lower:].\055" "[:upper:]_")
|
||||||
ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null`
|
ver_hex=$(git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null)
|
||||||
echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h"
|
echo \#define ARDUINO_ESP32_GIT_VER 0x"$ver_hex" > "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h"
|
echo \#define ARDUINO_ESP32_GIT_DESC "$(git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null)" >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
echo \#define ARDUINO_ESP32_RELEASE_$ver_define >> "$PKG_DIR/cores/esp32/core_version.h"
|
echo \#define ARDUINO_ESP32_RELEASE_"$ver_define" >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >> "$PKG_DIR/cores/esp32/core_version.h"
|
echo \#define ARDUINO_ESP32_RELEASE \""$ver_define"\" >> "$PKG_DIR/cores/esp32/core_version.h"
|
||||||
|
|
||||||
# Compress package folder
|
# Compress package folder
|
||||||
echo "Creating ZIP ..."
|
echo "Creating ZIP ..."
|
||||||
pushd "$OUTPUT_DIR" >/dev/null
|
pushd "$OUTPUT_DIR" >/dev/null
|
||||||
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
|
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
|
||||||
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Calculate SHA-256
|
# Calculate SHA-256
|
||||||
echo "Calculating SHA sum ..."
|
echo "Calculating SHA sum ..."
|
||||||
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
|
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
|
||||||
PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
|
PACKAGE_SHA=$(shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' ')
|
||||||
PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
|
PACKAGE_SIZE=$(get_file_size "$PACKAGE_ZIP")
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf "$PKG_DIR"
|
rm -rf "$PKG_DIR"
|
||||||
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
|
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
|
||||||
|
|
@ -264,86 +304,28 @@ echo
|
||||||
|
|
||||||
# Upload package to release page
|
# Upload package to release page
|
||||||
echo "Uploading package to release page ..."
|
echo "Uploading package to release page ..."
|
||||||
PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"`
|
PACKAGE_URL=$(git_safe_upload_asset "$PACKAGE_PATH")
|
||||||
echo "Package Uploaded"
|
echo "Package Uploaded"
|
||||||
echo "Download URL: $PACKAGE_URL"
|
echo "Download URL: $PACKAGE_URL"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
##
|
|
||||||
## LIBS PACKAGE ZIP
|
|
||||||
##
|
|
||||||
|
|
||||||
LIBS_PROJ_NAME="esp32-arduino-libs"
|
|
||||||
LIBS_PKG_DIR="$OUTPUT_DIR/$LIBS_PROJ_NAME"
|
|
||||||
LIBS_PACKAGE_ZIP="$LIBS_PROJ_NAME-$RELEASE_TAG.zip"
|
|
||||||
|
|
||||||
# Get the libs package URL from the template
|
|
||||||
LIBS_PACKAGE_SRC_ZIP="$OUTPUT_DIR/src-$LIBS_PROJ_NAME.zip"
|
|
||||||
LIBS_PACKAGE_SRC_URL=`cat $PACKAGE_JSON_TEMPLATE | jq -r ".packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\") | .systems[0].url"`
|
|
||||||
|
|
||||||
# Download the libs package
|
|
||||||
echo "Downloading the libs archive ..."
|
|
||||||
curl -o "$LIBS_PACKAGE_SRC_ZIP" -LJO --url "$LIBS_PACKAGE_SRC_URL" || exit 1
|
|
||||||
|
|
||||||
# Extract the libs package
|
|
||||||
echo "Extracting the archive ..."
|
|
||||||
unzip -q -d "$OUTPUT_DIR" "$LIBS_PACKAGE_SRC_ZIP" || exit 1
|
|
||||||
EXTRACTED_DIR=`ls "$OUTPUT_DIR" | grep "^$LIBS_PROJ_NAME"`
|
|
||||||
mv "$OUTPUT_DIR/$EXTRACTED_DIR" "$LIBS_PKG_DIR" || exit 1
|
|
||||||
|
|
||||||
# Remove unnecessary files in the package folder
|
|
||||||
echo "Cleaning up folders ..."
|
|
||||||
find "$LIBS_PKG_DIR" -name '*.DS_Store' -exec rm -f {} \;
|
|
||||||
find "$LIBS_PKG_DIR" -name '*.git*' -type f -delete
|
|
||||||
|
|
||||||
# Compress package folder
|
|
||||||
echo "Creating ZIP ..."
|
|
||||||
pushd "$OUTPUT_DIR" >/dev/null
|
|
||||||
zip -qr "$LIBS_PACKAGE_ZIP" "$LIBS_PROJ_NAME"
|
|
||||||
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $LIBS_PACKAGE_ZIP ($?)"; exit 1; fi
|
|
||||||
|
|
||||||
# Calculate SHA-256
|
|
||||||
echo "Calculating SHA sum ..."
|
|
||||||
LIBS_PACKAGE_PATH="$OUTPUT_DIR/$LIBS_PACKAGE_ZIP"
|
|
||||||
LIBS_PACKAGE_SHA=`shasum -a 256 "$LIBS_PACKAGE_ZIP" | cut -f 1 -d ' '`
|
|
||||||
LIBS_PACKAGE_SIZE=`get_file_size "$LIBS_PACKAGE_ZIP"`
|
|
||||||
popd >/dev/null
|
|
||||||
rm -rf "$LIBS_PKG_DIR"
|
|
||||||
echo "'$LIBS_PACKAGE_ZIP' Created! Size: $LIBS_PACKAGE_SIZE, SHA-256: $LIBS_PACKAGE_SHA"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Upload package to release page
|
|
||||||
echo "Uploading libs package to release page ..."
|
|
||||||
LIBS_PACKAGE_URL=`git_safe_upload_asset "$LIBS_PACKAGE_PATH"`
|
|
||||||
echo "Libs Package Uploaded"
|
|
||||||
echo "Libs Download URL: $LIBS_PACKAGE_URL"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Construct JQ argument with libs package data
|
|
||||||
libs_jq_arg="\
|
|
||||||
(.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].url = \"$LIBS_PACKAGE_URL\" |\
|
|
||||||
(.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].archiveFileName = \"$LIBS_PACKAGE_ZIP\" |\
|
|
||||||
(.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].size = \"$LIBS_PACKAGE_SIZE\" |\
|
|
||||||
(.packages[0].tools[] | select(.name==\"$LIBS_PROJ_NAME\")).systems[].checksum = \"SHA-256:$LIBS_PACKAGE_SHA\""
|
|
||||||
|
|
||||||
# Update template values for the libs package and store it in the build folder
|
|
||||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$libs_jq_arg" > "$OUTPUT_DIR/package-$LIBS_PROJ_NAME.json"
|
|
||||||
# Overwrite the template location with the newly edited one
|
|
||||||
PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-$LIBS_PROJ_NAME.json"
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS
|
## TEMP WORKAROUND FOR RV32 LONG PATH ON WINDOWS
|
||||||
##
|
##
|
||||||
RVTC_VERSION=`cat $PACKAGE_JSON_TEMPLATE | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2`
|
RVTC_VERSION=$(cat "$PACKAGE_JSON_TEMPLATE" | jq -r ".packages[0].platforms[0].toolsDependencies[] | select(.name == \"$RVTC_NAME\") | .version" | cut -d '_' -f 2)
|
||||||
# RVTC_VERSION=`date -j -f '%Y%m%d' "$RVTC_VERSION" '+%y%m'` # MacOS
|
# RVTC_VERSION=`date -j -f '%Y%m%d' "$RVTC_VERSION" '+%y%m'` # MacOS
|
||||||
RVTC_VERSION=`date -d "$RVTC_VERSION" '+%y%m'`
|
RVTC_VERSION=$(date -d "$RVTC_VERSION" '+%y%m')
|
||||||
rvtc_jq_arg="\
|
rvtc_jq_arg="\
|
||||||
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\
|
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\
|
||||||
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\
|
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\
|
||||||
(.packages[0].tools[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\
|
(.packages[0].tools[] | select(.name==\"$RVTC_NAME\")).version = \"$RVTC_VERSION\" |\
|
||||||
(.packages[0].tools[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\""
|
(.packages[0].tools[] | select(.name==\"$RVTC_NAME\")).name = \"$RVTC_NEW_NAME\" |\
|
||||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json"
|
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\
|
||||||
PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-$LIBS_PROJ_NAME-rvfix.json"
|
(.packages[0].platforms[0].toolsDependencies[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\" |\
|
||||||
|
(.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).version = \"$RVTC_VERSION\" |\
|
||||||
|
(.packages[0].tools[] | select(.name==\"$X32TC_NAME\")).name = \"$X32TC_NEW_NAME\""
|
||||||
|
cat "$PACKAGE_JSON_TEMPLATE" | jq "$rvtc_jq_arg" > "$OUTPUT_DIR/package-rvfix.json"
|
||||||
|
PACKAGE_JSON_TEMPLATE="$OUTPUT_DIR/package-rvfix.json"
|
||||||
|
|
||||||
##
|
##
|
||||||
## PACKAGE JSON
|
## PACKAGE JSON
|
||||||
|
|
@ -357,17 +339,26 @@ jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \
|
||||||
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
|
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
|
||||||
|
|
||||||
# Generate package JSONs
|
# Generate package JSONs
|
||||||
echo "Genarating $PACKAGE_JSON_DEV ..."
|
echo "Generating $PACKAGE_JSON_DEV ..."
|
||||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||||
|
# On MacOS the sed command won't skip the first match. Use gsed instead.
|
||||||
|
sed '0,/github\.com\//!s|github\.com/|dl.espressif.cn/github_assets/|g' "$OUTPUT_DIR/$PACKAGE_JSON_DEV" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
|
||||||
|
python "$SCRIPTS_DIR/release_append_cn.py" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
|
||||||
if [ "$RELEASE_PRE" == "false" ]; then
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
echo "Genarating $PACKAGE_JSON_REL ..."
|
echo "Generating $PACKAGE_JSON_REL ..."
|
||||||
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
|
# On MacOS the sed command won't skip the first match. Use gsed instead.
|
||||||
|
sed '0,/github\.com\//!s|github\.com/|dl.espressif.cn/github_assets/|g' "$OUTPUT_DIR/$PACKAGE_JSON_REL" > "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
|
||||||
|
python "$SCRIPTS_DIR/release_append_cn.py" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Figure out the last release or pre-release
|
# Figure out the last release or pre-release
|
||||||
echo "Getting previous releases ..."
|
echo "Getting previous releases ..."
|
||||||
releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
|
releasesJson=$(curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null)
|
||||||
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Get Releases Failed! ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
|
||||||
|
|
@ -387,27 +378,94 @@ echo "Previous (any)release: $prev_any_release"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
# Merge package JSONs with previous releases
|
# Merge package JSONs with previous releases
|
||||||
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
if [ -n "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
||||||
echo "Merging with JSON from $prev_any_release ..."
|
echo "Merging with JSON from $prev_any_release ..."
|
||||||
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||||
|
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV_CN" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$RELEASE_PRE" == "false" ]; then
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
if [ -n "$prev_release" ] && [ "$prev_release" != "null" ]; then
|
||||||
echo "Merging with JSON from $prev_release ..."
|
echo "Merging with JSON from $prev_release ..."
|
||||||
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
|
merge_package_json "$prev_release/$PACKAGE_JSON_REL_CN" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Test the package JSONs
|
||||||
|
|
||||||
|
echo "Installing arduino-cli ..."
|
||||||
|
export PATH="/home/runner/bin:$PATH"
|
||||||
|
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
|
||||||
|
|
||||||
|
# For the Chinese mirror, we can't test the package JSONs as the Chinese mirror might not be updated yet.
|
||||||
|
|
||||||
|
echo "Testing $PACKAGE_JSON_DEV install ..."
|
||||||
|
|
||||||
|
echo "Installing esp32 ..."
|
||||||
|
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_DEV"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to install esp32 ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Compiling example ..."
|
||||||
|
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to compile example ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Uninstalling esp32 ..."
|
||||||
|
arduino-cli core uninstall esp32:esp32
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to uninstall esp32 ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Test successful!"
|
||||||
|
|
||||||
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
|
echo "Testing $PACKAGE_JSON_REL install ..."
|
||||||
|
|
||||||
|
echo "Installing esp32 ..."
|
||||||
|
arduino-cli core install esp32:esp32 --additional-urls "file://$OUTPUT_DIR/$PACKAGE_JSON_REL"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to install esp32 ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Compiling example ..."
|
||||||
|
arduino-cli compile --fqbn esp32:esp32:esp32 "$GITHUB_WORKSPACE"/libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to compile example ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Uninstalling esp32 ..."
|
||||||
|
arduino-cli core uninstall esp32:esp32
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: Failed to uninstall esp32 ($?)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Test successful!"
|
||||||
|
fi
|
||||||
|
|
||||||
# Upload package JSONs
|
# Upload package JSONs
|
||||||
|
|
||||||
echo "Uploading $PACKAGE_JSON_DEV ..."
|
echo "Uploading $PACKAGE_JSON_DEV ..."
|
||||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV")"
|
||||||
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
|
echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV")"
|
||||||
|
echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")"
|
||||||
|
echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_DEV_CN" "$OUTPUT_DIR/$PACKAGE_JSON_DEV_CN")"
|
||||||
echo
|
echo
|
||||||
if [ "$RELEASE_PRE" == "false" ]; then
|
if [ "$RELEASE_PRE" == "false" ]; then
|
||||||
echo "Uploading $PACKAGE_JSON_REL ..."
|
echo "Uploading $PACKAGE_JSON_REL ..."
|
||||||
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
echo "Download URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL")"
|
||||||
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
|
echo "Pages URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL")"
|
||||||
|
echo "Download CN URL: $(git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")"
|
||||||
|
echo "Pages CN URL: $(git_safe_upload_to_pages "$PACKAGE_JSON_REL_CN" "$OUTPUT_DIR/$PACKAGE_JSON_REL_CN")"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
57
.github/scripts/release_append_cn.py
vendored
Executable file
57
.github/scripts/release_append_cn.py
vendored
Executable file
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Arduino IDE provides by default a package file for the ESP32. This causes version conflicts
|
||||||
|
# when the user tries to use the JSON file with the Chinese mirrors.
|
||||||
|
#
|
||||||
|
# The downside is that the Arduino IDE will always warn the user that updates are available as it
|
||||||
|
# will consider the version from the Chinese mirrors as a pre-release version.
|
||||||
|
#
|
||||||
|
# This script is used to append "-cn" to all versions in the package_esp32_index_cn.json file so that
|
||||||
|
# the user can select the Chinese mirrors without conflicts.
|
||||||
|
#
|
||||||
|
# If Arduino ever stops providing the package_esp32_index.json file by default,
|
||||||
|
# this script can be removed and the tags reverted.
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
def append_cn_to_versions(obj):
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
# Skip tools that are not from the esp32 package
|
||||||
|
packager = obj.get("packager")
|
||||||
|
if packager is not None and packager != "esp32":
|
||||||
|
return
|
||||||
|
|
||||||
|
for key, value in obj.items():
|
||||||
|
if key == "version" and isinstance(value, str):
|
||||||
|
if not value.endswith("-cn"):
|
||||||
|
obj[key] = value + "-cn"
|
||||||
|
else:
|
||||||
|
append_cn_to_versions(value)
|
||||||
|
|
||||||
|
elif isinstance(obj, list):
|
||||||
|
for item in obj:
|
||||||
|
append_cn_to_versions(item)
|
||||||
|
|
||||||
|
def process_json_file(input_path, output_path=None):
|
||||||
|
with open(input_path, "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
append_cn_to_versions(data)
|
||||||
|
|
||||||
|
if output_path is None:
|
||||||
|
output_path = input_path
|
||||||
|
|
||||||
|
with open(output_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
|
print(f"Updated JSON written to {output_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python release_append_cn.py input.json [output.json]")
|
||||||
|
else:
|
||||||
|
input_file = sys.argv[1]
|
||||||
|
output_file = sys.argv[2] if len(sys.argv) > 2 else None
|
||||||
|
process_json_file(input_file, output_file)
|
||||||
84
.github/scripts/set_push_chunks.sh
vendored
Normal file
84
.github/scripts/set_push_chunks.sh
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
build_all=false
|
||||||
|
chunks_count=0
|
||||||
|
|
||||||
|
if [[ $CORE_CHANGED == 'true' ]] || [[ $IS_PR != 'true' ]]; then
|
||||||
|
echo "Core files changed or not a PR. Building all."
|
||||||
|
build_all=true
|
||||||
|
chunks_count=$MAX_CHUNKS
|
||||||
|
elif [[ $LIB_CHANGED == 'true' ]]; then
|
||||||
|
echo "Libraries changed. Building only affected sketches."
|
||||||
|
if [[ $NETWORKING_CHANGED == 'true' ]]; then
|
||||||
|
echo "Networking libraries changed. Building networking related sketches."
|
||||||
|
networking_sketches="$(find libraries/WiFi -name '*.ino') "
|
||||||
|
networking_sketches+="$(find libraries/Ethernet -name '*.ino') "
|
||||||
|
networking_sketches+="$(find libraries/PPP -name '*.ino') "
|
||||||
|
networking_sketches+="$(find libraries/NetworkClientSecure -name '*.ino') "
|
||||||
|
networking_sketches+="$(find libraries/WebServer -name '*.ino') "
|
||||||
|
fi
|
||||||
|
if [[ $FS_CHANGED == 'true' ]]; then
|
||||||
|
echo "FS libraries changed. Building FS related sketches."
|
||||||
|
fs_sketches="$(find libraries/SD -name '*.ino') "
|
||||||
|
fs_sketches+="$(find libraries/SD_MMC -name '*.ino') "
|
||||||
|
fs_sketches+="$(find libraries/SPIFFS -name '*.ino') "
|
||||||
|
fs_sketches+="$(find libraries/LittleFS -name '*.ino') "
|
||||||
|
fs_sketches+="$(find libraries/FFat -name '*.ino') "
|
||||||
|
fi
|
||||||
|
sketches="$networking_sketches $fs_sketches"
|
||||||
|
for file in $LIB_FILES; do
|
||||||
|
lib=$(echo "$file" | awk -F "/" '{print $1"/"$2}')
|
||||||
|
if [[ "$file" == *.ino ]]; then
|
||||||
|
# If file ends with .ino, add it to the list of sketches
|
||||||
|
echo "Sketch found: $file"
|
||||||
|
sketches+="$file "
|
||||||
|
elif [[ "$file" == "$lib/src/"* ]]; then
|
||||||
|
# If file is inside the src directory, find all sketches in the lib/examples directory
|
||||||
|
echo "Library src file found: $file"
|
||||||
|
if [[ -d $lib/examples ]]; then
|
||||||
|
lib_sketches=$(find "$lib"/examples -name '*.ino')
|
||||||
|
sketches+="$lib_sketches "
|
||||||
|
echo "Library sketches: $lib_sketches"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# If file is in a example folder but it is not a sketch, find all sketches in the current directory
|
||||||
|
echo "File in example folder found: $file"
|
||||||
|
sketch=$(find "$(dirname "$file")" -name '*.ino')
|
||||||
|
sketches+="$sketch "
|
||||||
|
echo "Sketch in example folder: $sketch"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $sketches ]]; then
|
||||||
|
# Remove duplicates
|
||||||
|
sketches=$(echo "$sketches" | tr ' ' '\n' | sort | uniq)
|
||||||
|
for sketch in $sketches; do
|
||||||
|
echo "$sketch" >> sketches_found.txt
|
||||||
|
chunks_count=$((chunks_count+1))
|
||||||
|
done
|
||||||
|
echo "Number of sketches found: $chunks_count"
|
||||||
|
echo "Sketches:"
|
||||||
|
echo "$sketches"
|
||||||
|
|
||||||
|
if [[ $chunks_count -gt $MAX_CHUNKS ]]; then
|
||||||
|
echo "More sketches than the allowed number of chunks found. Limiting to $MAX_CHUNKS chunks."
|
||||||
|
chunks_count=$MAX_CHUNKS
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
chunks='["0"'
|
||||||
|
for i in $(seq 1 $(( chunks_count - 1 )) ); do
|
||||||
|
chunks+=",\"$i\""
|
||||||
|
done
|
||||||
|
chunks+="]"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "build_all=$build_all"
|
||||||
|
echo "build_libraries=$BUILD_LIBRARIES"
|
||||||
|
echo "build_static_sketches=$BUILD_STATIC_SKETCHES"
|
||||||
|
echo "build_idf=$BUILD_IDF"
|
||||||
|
echo "chunk_count=$chunks_count"
|
||||||
|
echo "chunks=$chunks"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
423
.github/scripts/sketch_utils.sh
vendored
423
.github/scripts/sketch_utils.sh
vendored
|
|
@ -1,7 +1,60 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [extra-options]
|
if [ -d "$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs" ]; then
|
||||||
while [ ! -z "$1" ]; do
|
SDKCONFIG_DIR="$ARDUINO_ESP32_PATH/tools/esp32-arduino-libs"
|
||||||
|
elif [ -d "$GITHUB_WORKSPACE/tools/esp32-arduino-libs" ]; then
|
||||||
|
SDKCONFIG_DIR="$GITHUB_WORKSPACE/tools/esp32-arduino-libs"
|
||||||
|
else
|
||||||
|
SDKCONFIG_DIR="tools/esp32-arduino-libs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
function check_requirements { # check_requirements <sketchdir> <sdkconfig_path>
|
||||||
|
local sketchdir=$1
|
||||||
|
local sdkconfig_path=$2
|
||||||
|
local has_requirements=1
|
||||||
|
local requirements
|
||||||
|
local requirements_or
|
||||||
|
|
||||||
|
if [ ! -f "$sdkconfig_path" ] || [ ! -f "$sketchdir/ci.json" ]; then
|
||||||
|
echo "WARNING: sdkconfig or ci.json not found. Assuming requirements are met." 1>&2
|
||||||
|
# Return 1 on error to force the sketch to be built and fail. This way the
|
||||||
|
# CI will fail and the user will know that the sketch has a problem.
|
||||||
|
else
|
||||||
|
# Check if the sketch requires any configuration options (AND)
|
||||||
|
requirements=$(jq -r '.requires[]? // empty' "$sketchdir/ci.json")
|
||||||
|
if [[ "$requirements" != "null" && "$requirements" != "" ]]; then
|
||||||
|
for requirement in $requirements; do
|
||||||
|
requirement=$(echo "$requirement" | xargs)
|
||||||
|
found_line=$(grep -E "^$requirement" "$sdkconfig_path")
|
||||||
|
if [[ "$found_line" == "" ]]; then
|
||||||
|
has_requirements=0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the sketch requires any configuration options (OR)
|
||||||
|
requirements_or=$(jq -r '.requires_any[]? // empty' "$sketchdir/ci.json")
|
||||||
|
if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then
|
||||||
|
local found=false
|
||||||
|
for requirement in $requirements_or; do
|
||||||
|
requirement=$(echo "$requirement" | xargs)
|
||||||
|
found_line=$(grep -E "^$requirement" "$sdkconfig_path")
|
||||||
|
if [[ "$found_line" != "" ]]; then
|
||||||
|
found=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$found" == "false" ]]; then
|
||||||
|
has_requirements=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $has_requirements
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [extra-options]
|
||||||
|
while [ -n "$1" ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-ai )
|
-ai )
|
||||||
shift
|
shift
|
||||||
|
|
@ -27,6 +80,18 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
shift
|
shift
|
||||||
sketchdir=$1
|
sketchdir=$1
|
||||||
;;
|
;;
|
||||||
|
-i )
|
||||||
|
shift
|
||||||
|
chunk_index=$1
|
||||||
|
;;
|
||||||
|
-l )
|
||||||
|
shift
|
||||||
|
log_compilation=$1
|
||||||
|
;;
|
||||||
|
-d )
|
||||||
|
shift
|
||||||
|
debug_level="DebugLevel=$1"
|
||||||
|
;;
|
||||||
* )
|
* )
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
|
|
@ -34,9 +99,10 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
xtra_opts=$*
|
xtra_opts=("$@")
|
||||||
|
len=0
|
||||||
|
|
||||||
if [ -z $sketchdir ]; then
|
if [ -z "$sketchdir" ]; then
|
||||||
echo "ERROR: Sketch directory not provided"
|
echo "ERROR: Sketch directory not provided"
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -44,8 +110,8 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
|
|
||||||
# No FQBN was passed, try to get it from other options
|
# No FQBN was passed, try to get it from other options
|
||||||
|
|
||||||
if [ -z $fqbn ]; then
|
if [ -z "$fqbn" ]; then
|
||||||
if [ -z $target ]; then
|
if [ -z "$target" ]; then
|
||||||
echo "ERROR: Unspecified chip"
|
echo "ERROR: Unspecified chip"
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -56,48 +122,83 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
# precedence. Note that the following logic also falls to the default
|
# precedence. Note that the following logic also falls to the default
|
||||||
# parameters if no arguments were passed and no file was found.
|
# parameters if no arguments were passed and no file was found.
|
||||||
|
|
||||||
if [ -z $options ] && [ -f $sketchdir/cfg.json ]; then
|
if [ -z "$options" ] && [ -f "$sketchdir"/ci.json ]; then
|
||||||
# The config file could contain multiple FQBNs for one chip. If
|
# The config file could contain multiple FQBNs for one chip. If
|
||||||
# that's the case we build one time for every FQBN.
|
# that's the case we build one time for every FQBN.
|
||||||
|
|
||||||
len=`jq -r --arg chip $target '.targets[] | select(.name==$chip) | .fqbn | length' $sketchdir/cfg.json`
|
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json)
|
||||||
fqbn=`jq -r --arg chip $target '.targets[] | select(.name==$chip) | .fqbn' $sketchdir/cfg.json`
|
if [ "$len" -gt 0 ]; then
|
||||||
else
|
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | sort' "$sketchdir"/ci.json)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$options" ] || [ "$len" -eq 0 ]; then
|
||||||
# Since we are passing options, we will end up with only one FQBN to
|
# Since we are passing options, we will end up with only one FQBN to
|
||||||
# build.
|
# build.
|
||||||
|
|
||||||
len=1
|
len=1
|
||||||
|
|
||||||
# Default FQBN options if none were passed in the command line.
|
if [ -f "$sketchdir"/ci.json ]; then
|
||||||
|
fqbn_append=$(jq -r '.fqbn_append' "$sketchdir"/ci.json)
|
||||||
|
if [ "$fqbn_append" == "null" ]; then
|
||||||
|
fqbn_append=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
esp32_opts="PSRAM=enabled,PartitionScheme=huge_app"
|
# Default FQBN options if none were passed in the command line.
|
||||||
esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app"
|
# Replace any double commas with a single one and strip leading and
|
||||||
esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app"
|
# trailing commas.
|
||||||
esp32c3_opts="PartitionScheme=huge_app"
|
|
||||||
esp32c6_opts="PartitionScheme=huge_app"
|
esp32_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
esp32h2_opts="PartitionScheme=huge_app"
|
esp32s2_opts=$(echo "PSRAM=enabled,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32s3_opts=$(echo "PSRAM=opi,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32c3_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32c6_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32h2_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32p4_opts=$(echo "PSRAM=enabled,USBMode=default,$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
esp32c5_opts=$(echo "$debug_level,$fqbn_append" | sed 's/^,*//;s/,*$//;s/,\{2,\}/,/g')
|
||||||
|
|
||||||
# Select the common part of the FQBN based on the target. The rest will be
|
# Select the common part of the FQBN based on the target. The rest will be
|
||||||
# appended depending on the passed options.
|
# appended depending on the passed options.
|
||||||
|
|
||||||
|
opt=""
|
||||||
|
|
||||||
case "$target" in
|
case "$target" in
|
||||||
"esp32")
|
"esp32")
|
||||||
fqbn="espressif:esp32:esp32:${options:-$esp32_opts}"
|
[ -n "${options:-$esp32_opts}" ] && opt=":${options:-$esp32_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32$opt"
|
||||||
;;
|
;;
|
||||||
"esp32s2")
|
"esp32s2")
|
||||||
fqbn="espressif:esp32:esp32s2:${options:-$esp32s2_opts}"
|
[ -n "${options:-$esp32s2_opts}" ] && opt=":${options:-$esp32s2_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32s2$opt"
|
||||||
;;
|
;;
|
||||||
"esp32c3")
|
"esp32c3")
|
||||||
fqbn="espressif:esp32:esp32c3:${options:-$esp32c3_opts}"
|
[ -n "${options:-$esp32c3_opts}" ] && opt=":${options:-$esp32c3_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32c3$opt"
|
||||||
;;
|
;;
|
||||||
"esp32s3")
|
"esp32s3")
|
||||||
fqbn="espressif:esp32:esp32s3:${options:-$esp32s3_opts}"
|
[ -n "${options:-$esp32s3_opts}" ] && opt=":${options:-$esp32s3_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32s3$opt"
|
||||||
;;
|
;;
|
||||||
"esp32c6")
|
"esp32c6")
|
||||||
fqbn="espressif:esp32:esp32c6:${options:-$esp32c6_opts}"
|
[ -n "${options:-$esp32c6_opts}" ] && opt=":${options:-$esp32c6_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32c6$opt"
|
||||||
;;
|
;;
|
||||||
"esp32h2")
|
"esp32h2")
|
||||||
fqbn="espressif:esp32:esp32h2:${options:-$esp32h2_opts}"
|
[ -n "${options:-$esp32h2_opts}" ] && opt=":${options:-$esp32h2_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32h2$opt"
|
||||||
|
;;
|
||||||
|
"esp32p4")
|
||||||
|
[ -n "${options:-$esp32p4_opts}" ] && opt=":${options:-$esp32p4_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32p4$opt"
|
||||||
|
;;
|
||||||
|
"esp32c5")
|
||||||
|
[ -n "${options:-$esp32c5_opts}" ] && opt=":${options:-$esp32c5_opts}"
|
||||||
|
fqbn="espressif:esp32:esp32c5$opt"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Invalid chip: $target"
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
@ -113,11 +214,11 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$fqbn" ]; then
|
if [ -z "$fqbn" ]; then
|
||||||
echo "No FQBN passed or unvalid chip: $target"
|
echo "No FQBN passed or invalid chip: $target"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The directory that will hold all the artifcats (the build directory) is
|
# The directory that will hold all the artifacts (the build directory) is
|
||||||
# provided through:
|
# provided through:
|
||||||
# 1. An env variable called ARDUINO_BUILD_DIR.
|
# 1. An env variable called ARDUINO_BUILD_DIR.
|
||||||
# 2. Created at the sketch level as "build" in the case of a single
|
# 2. Created at the sketch level as "build" in the case of a single
|
||||||
|
|
@ -125,69 +226,107 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
# 3. Created at the sketch level as "buildX" where X is the number
|
# 3. Created at the sketch level as "buildX" where X is the number
|
||||||
# of configuration built in case of a multiconfiguration test.
|
# of configuration built in case of a multiconfiguration test.
|
||||||
|
|
||||||
sketchname=$(basename $sketchdir)
|
sketchname=$(basename "$sketchdir")
|
||||||
|
local has_requirements
|
||||||
|
|
||||||
if [[ -n $target ]] && [[ -f "$sketchdir/.skip.$target" ]]; then
|
if [ -f "$sketchdir"/ci.json ]; then
|
||||||
echo "Skipping $sketchname for target $target"
|
# If the target is listed as false, skip the sketch. Otherwise, include it.
|
||||||
exit 0
|
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
|
||||||
|
if [[ "$is_target" == "false" ]]; then
|
||||||
|
echo "Skipping $sketchname for target $target"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig")
|
||||||
|
if [ "$has_requirements" == "0" ]; then
|
||||||
|
echo "Target $target does not meet the requirements for $sketchname. Skipping."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
|
||||||
if [ -n "$ARDUINO_BUILD_DIR" ]; then
|
if [ -n "$ARDUINO_BUILD_DIR" ]; then
|
||||||
build_dir="$ARDUINO_BUILD_DIR"
|
build_dir="$ARDUINO_BUILD_DIR"
|
||||||
elif [ $len -eq 1 ]; then
|
elif [ "$len" -eq 1 ]; then
|
||||||
# build_dir="$sketchdir/build"
|
# build_dir="$sketchdir/build"
|
||||||
build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
|
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$ARDUINO_CACHE_DIR"
|
output_file="$HOME/.arduino/cli_compile_output.txt"
|
||||||
for i in `seq 0 $(($len - 1))`
|
sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json"
|
||||||
do
|
|
||||||
if [ $len -ne 1 ]; then
|
|
||||||
# build_dir="$sketchdir/build$i"
|
|
||||||
build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
|
|
||||||
fi
|
|
||||||
rm -rf $build_dir
|
|
||||||
mkdir -p $build_dir
|
|
||||||
|
|
||||||
currfqbn=`echo $fqbn | jq -r --argjson i $i '.[$i]'`
|
mkdir -p "$ARDUINO_CACHE_DIR"
|
||||||
|
for i in $(seq 0 $((len - 1))); do
|
||||||
|
if [ "$len" -ne 1 ]; then
|
||||||
|
# build_dir="$sketchdir/build$i"
|
||||||
|
build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp"
|
||||||
|
fi
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
mkdir -p "$build_dir"
|
||||||
|
|
||||||
|
currfqbn=$(echo "$fqbn" | jq -r --argjson i "$i" '.[$i]')
|
||||||
|
|
||||||
if [ -f "$ide_path/arduino-cli" ]; then
|
if [ -f "$ide_path/arduino-cli" ]; then
|
||||||
echo "Building $sketchname with arduino-cli and FQBN=$currfqbn"
|
echo "Building $sketchname with arduino-cli and FQBN=$currfqbn"
|
||||||
|
|
||||||
curroptions=`echo "$currfqbn" | cut -d':' -f4`
|
curroptions=$(echo "$currfqbn" | cut -d':' -f4)
|
||||||
currfqbn=`echo "$currfqbn" | cut -d':' -f1-3`
|
currfqbn=$(echo "$currfqbn" | cut -d':' -f1-3)
|
||||||
$ide_path/arduino-cli compile \
|
"$ide_path"/arduino-cli compile \
|
||||||
--fqbn "$currfqbn" \
|
--fqbn "$currfqbn" \
|
||||||
--board-options "$curroptions" \
|
--board-options "$curroptions" \
|
||||||
--warnings "all" \
|
--warnings "all" \
|
||||||
--build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \
|
--build-property "compiler.warning_flags.all=-Wall -Werror=all -Wextra" \
|
||||||
--build-cache-path "$ARDUINO_CACHE_DIR" \
|
|
||||||
--build-path "$build_dir" \
|
--build-path "$build_dir" \
|
||||||
$xtra_opts "${sketchdir}"
|
"${xtra_opts[@]}" "${sketchdir}" \
|
||||||
|
2>&1 | tee "$output_file"
|
||||||
|
|
||||||
exit_status=$?
|
exit_status=${PIPESTATUS[0]}
|
||||||
if [ $exit_status -ne 0 ]; then
|
if [ "$exit_status" -ne 0 ]; then
|
||||||
echo ""ERROR: Compilation failed with error code $exit_status""
|
echo "ERROR: Compilation failed with error code $exit_status"
|
||||||
exit $exit_status
|
exit "$exit_status"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$log_compilation" ]; then
|
||||||
|
#Extract the program storage space and dynamic memory usage in bytes and percentage in separate variables from the output, just the value without the string
|
||||||
|
flash_bytes=$(grep -oE 'Sketch uses ([0-9]+) bytes' "$output_file" | awk '{print $3}')
|
||||||
|
flash_percentage=$(grep -oE 'Sketch uses ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $5}' | tr -d '(%)')
|
||||||
|
ram_bytes=$(grep -oE 'Global variables use ([0-9]+) bytes' "$output_file" | awk '{print $4}')
|
||||||
|
ram_percentage=$(grep -oE 'Global variables use ([0-9]+) bytes \(([0-9]+)%\)' "$output_file" | awk '{print $6}' | tr -d '(%)')
|
||||||
|
|
||||||
|
# Extract the directory path excluding the filename
|
||||||
|
directory_path=$(dirname "$sketch")
|
||||||
|
# Define the constant part
|
||||||
|
constant_part="/home/runner/Arduino/hardware/espressif/esp32/libraries/"
|
||||||
|
# Extract the desired substring
|
||||||
|
lib_sketch_name="${directory_path#"$constant_part"}"
|
||||||
|
#append json file where key is fqbn, sketch name, sizes -> extracted values
|
||||||
|
echo "{\"name\": \"$lib_sketch_name\",
|
||||||
|
\"sizes\": [{
|
||||||
|
\"flash_bytes\": $flash_bytes,
|
||||||
|
\"flash_percentage\": $flash_percentage,
|
||||||
|
\"ram_bytes\": $ram_bytes,
|
||||||
|
\"ram_percentage\": $ram_percentage
|
||||||
|
}]
|
||||||
|
}," >> "$sizes_file"
|
||||||
|
fi
|
||||||
|
|
||||||
elif [ -f "$ide_path/arduino-builder" ]; then
|
elif [ -f "$ide_path/arduino-builder" ]; then
|
||||||
echo "Building $sketchname with arduino-builder and FQBN=$currfqbn"
|
echo "Building $sketchname with arduino-builder and FQBN=$currfqbn"
|
||||||
echo "Build path = $build_dir"
|
echo "Build path = $build_dir"
|
||||||
|
|
||||||
$ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \
|
"$ide_path"/arduino-builder -compile -logger=human -core-api-version=10810 \
|
||||||
-fqbn=\"$currfqbn\" \
|
-fqbn=\""$currfqbn"\" \
|
||||||
-warnings="all" \
|
-warnings="all" \
|
||||||
-tools "$ide_path/tools-builder" \
|
-tools "$ide_path/tools-builder" \
|
||||||
-hardware "$user_path/hardware" \
|
-hardware "$user_path/hardware" \
|
||||||
-libraries "$user_path/libraries" \
|
-libraries "$user_path/libraries" \
|
||||||
-build-cache "$ARDUINO_CACHE_DIR" \
|
-build-cache "$ARDUINO_CACHE_DIR" \
|
||||||
-build-path "$build_dir" \
|
-build-path "$build_dir" \
|
||||||
$xtra_opts "${sketchdir}/${sketchname}.ino"
|
"${xtra_opts[@]}" "${sketchdir}/${sketchname}.ino"
|
||||||
|
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
if [ $exit_status -ne 0 ]; then
|
if [ $exit_status -ne 0 ]; then
|
||||||
echo ""ERROR: Compilation failed with error code $exit_status""
|
echo "ERROR: Compilation failed with error code $exit_status"
|
||||||
exit $exit_status
|
exit $exit_status
|
||||||
fi
|
fi
|
||||||
# $ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \
|
# $ide_path/arduino-builder -compile -logger=human -core-api-version=10810 \
|
||||||
|
|
@ -204,48 +343,72 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
|
||||||
# $xtra_opts "${sketchdir}/${sketchname}.ino"
|
# $xtra_opts "${sketchdir}/${sketchname}.ino"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
unset fqbn
|
unset fqbn
|
||||||
unset xtra_opts
|
unset xtra_opts
|
||||||
unset options
|
unset options
|
||||||
}
|
}
|
||||||
|
|
||||||
function count_sketches(){ # count_sketches <path> [target]
|
function count_sketches { # count_sketches <path> [target] [file] [ignore-requirements]
|
||||||
local path=$1
|
local path=$1
|
||||||
local target=$2
|
local target=$2
|
||||||
|
local ignore_requirements=$3
|
||||||
|
local file=$4
|
||||||
|
local sketches
|
||||||
|
|
||||||
if [ $# -lt 1 ]; then
|
if [ $# -lt 1 ]; then
|
||||||
echo "ERROR: Illegal number of parameters"
|
echo "ERROR: Illegal number of parameters"
|
||||||
echo "USAGE: ${0} count <path> [target]"
|
echo "USAGE: ${0} count <path> [target]"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf sketches.txt
|
rm -rf sketches.txt
|
||||||
|
touch sketches.txt
|
||||||
if [ ! -d "$path" ]; then
|
if [ ! -d "$path" ]; then
|
||||||
touch sketches.txt
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local sketches=$(find $path -name *.ino | sort)
|
if [ -f "$file" ]; then
|
||||||
|
sketches=$(cat "$file")
|
||||||
|
else
|
||||||
|
sketches=$(find "$path" -name '*.ino' | sort)
|
||||||
|
fi
|
||||||
|
|
||||||
local sketchnum=0
|
local sketchnum=0
|
||||||
for sketch in $sketches; do
|
for sketch in $sketches; do
|
||||||
local sketchdir=$(dirname $sketch)
|
local sketchdir
|
||||||
local sketchdirname=$(basename $sketchdir)
|
local sketchdirname
|
||||||
local sketchname=$(basename $sketch)
|
local sketchname
|
||||||
|
local has_requirements
|
||||||
|
|
||||||
|
sketchdir=$(dirname "$sketch")
|
||||||
|
sketchdirname=$(basename "$sketchdir")
|
||||||
|
sketchname=$(basename "$sketch")
|
||||||
|
|
||||||
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
|
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
|
||||||
continue
|
continue
|
||||||
elif [[ -n $target ]] && [[ -f "$sketchdir/.skip.$target" ]]; then
|
elif [[ -n $target ]] && [[ -f $sketchdir/ci.json ]]; then
|
||||||
continue
|
# If the target is listed as false, skip the sketch. Otherwise, include it.
|
||||||
else
|
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
|
||||||
echo $sketch >> sketches.txt
|
if [[ "$is_target" == "false" ]]; then
|
||||||
sketchnum=$(($sketchnum + 1))
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ignore_requirements" != "1" ]; then
|
||||||
|
has_requirements=$(check_requirements "$sketchdir" "$SDKCONFIG_DIR/$target/sdkconfig")
|
||||||
|
if [ "$has_requirements" == "0" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
echo "$sketch" >> sketches.txt
|
||||||
|
sketchnum=$((sketchnum + 1))
|
||||||
done
|
done
|
||||||
return $sketchnum
|
return $sketchnum
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options]
|
function build_sketches { # build_sketches <ide_path> <user_path> <target> <path> <chunk> <total-chunks> [extra-options]
|
||||||
|
local args=()
|
||||||
local args=""
|
while [ -n "$1" ]; do
|
||||||
while [ ! -z "$1" ]; do
|
|
||||||
case $1 in
|
case $1 in
|
||||||
-ai )
|
-ai )
|
||||||
shift
|
shift
|
||||||
|
|
@ -258,12 +421,12 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
-t )
|
-t )
|
||||||
shift
|
shift
|
||||||
target=$1
|
target=$1
|
||||||
args+=" -t $target"
|
args+=("-t" "$target")
|
||||||
;;
|
;;
|
||||||
-fqbn )
|
-fqbn )
|
||||||
shift
|
shift
|
||||||
fqbn=$1
|
fqbn=$1
|
||||||
args+=" -fqbn $fqbn"
|
args+=("-fqbn" "$fqbn")
|
||||||
;;
|
;;
|
||||||
-p )
|
-p )
|
||||||
shift
|
shift
|
||||||
|
|
@ -277,6 +440,19 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
shift
|
shift
|
||||||
chunk_max=$1
|
chunk_max=$1
|
||||||
;;
|
;;
|
||||||
|
-l )
|
||||||
|
shift
|
||||||
|
log_compilation=$1
|
||||||
|
;;
|
||||||
|
-f )
|
||||||
|
shift
|
||||||
|
sketches_file=$1
|
||||||
|
;;
|
||||||
|
-d )
|
||||||
|
shift
|
||||||
|
debug_level="$1"
|
||||||
|
args+=("-d" "$debug_level")
|
||||||
|
;;
|
||||||
* )
|
* )
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
|
|
@ -284,10 +460,10 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
local xtra_opts=$*
|
local xtra_opts=("$@")
|
||||||
|
|
||||||
if [ -z $chunk_index ] || [ -z $chunk_max ]; then
|
if [ -z "$chunk_index" ] || [ -z "$chunk_max" ]; then
|
||||||
echo "ERROR: Invalid chunk paramters"
|
echo "ERROR: Invalid chunk parameters"
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -297,21 +473,29 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$chunk_index" -gt "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then
|
if [ "$chunk_index" -gt "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then
|
||||||
chunk_index=$chunk_max
|
chunk_index=$chunk_max
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
count_sketches "$path" "$target"
|
if [ -n "$sketches_file" ]; then
|
||||||
local sketchcount=$?
|
count_sketches "$path" "$target" "0" "$sketches_file"
|
||||||
|
local sketchcount=$?
|
||||||
|
else
|
||||||
|
count_sketches "$path" "$target"
|
||||||
|
local sketchcount=$?
|
||||||
|
fi
|
||||||
set -e
|
set -e
|
||||||
local sketches=$(cat sketches.txt)
|
local sketches
|
||||||
|
sketches=$(cat sketches.txt)
|
||||||
rm -rf sketches.txt
|
rm -rf sketches.txt
|
||||||
|
|
||||||
local chunk_size=$(( $sketchcount / $chunk_max ))
|
local chunk_size
|
||||||
local all_chunks=$(( $chunk_max * $chunk_size ))
|
local all_chunks
|
||||||
|
chunk_size=$(( sketchcount / chunk_max ))
|
||||||
|
all_chunks=$(( chunk_max * chunk_size ))
|
||||||
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||||
chunk_size=$(( $chunk_size + 1 ))
|
chunk_size=$(( chunk_size + 1 ))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local start_index=0
|
local start_index=0
|
||||||
|
|
@ -320,19 +504,20 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
start_index=$chunk_index
|
start_index=$chunk_index
|
||||||
end_index=$sketchcount
|
end_index=$sketchcount
|
||||||
else
|
else
|
||||||
start_index=$(( $chunk_index * $chunk_size ))
|
start_index=$(( chunk_index * chunk_size ))
|
||||||
if [ "$sketchcount" -le "$start_index" ]; then
|
if [ "$sketchcount" -le "$start_index" ]; then
|
||||||
echo "Skipping job"
|
echo "No sketches to build for $target in this chunk"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
|
end_index=$(( $(( chunk_index + 1 )) * chunk_size ))
|
||||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||||
end_index=$sketchcount
|
end_index=$sketchcount
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local start_num=$(( $start_index + 1 ))
|
local start_num
|
||||||
|
start_num=$(( start_index + 1 ))
|
||||||
echo "Found $sketchcount Sketches for target '$target'";
|
echo "Found $sketchcount Sketches for target '$target'";
|
||||||
echo "Chunk Index : $chunk_index"
|
echo "Chunk Index : $chunk_index"
|
||||||
echo "Chunk Count : $chunk_max"
|
echo "Chunk Count : $chunk_max"
|
||||||
|
|
@ -340,53 +525,89 @@ function build_sketches(){ # build_sketches <ide_path> <user_path> <target> <pat
|
||||||
echo "Start Sketch: $start_num"
|
echo "Start Sketch: $start_num"
|
||||||
echo "End Sketch : $end_index"
|
echo "End Sketch : $end_index"
|
||||||
|
|
||||||
|
#if fqbn is not passed then set it to default for compilation log
|
||||||
|
if [ -z "$fqbn" ]; then
|
||||||
|
log_fqbn="espressif:esp32:$target"
|
||||||
|
else
|
||||||
|
log_fqbn=$fqbn
|
||||||
|
fi
|
||||||
|
|
||||||
|
sizes_file="$GITHUB_WORKSPACE/cli_compile_$chunk_index.json"
|
||||||
|
if [ -n "$log_compilation" ]; then
|
||||||
|
#echo board,target and start of sketches to sizes_file json
|
||||||
|
echo "{ \"board\": \"$log_fqbn\",
|
||||||
|
\"target\": \"$target\",
|
||||||
|
\"sketches\": [" >> "$sizes_file"
|
||||||
|
fi
|
||||||
|
|
||||||
local sketchnum=0
|
local sketchnum=0
|
||||||
args+=" -ai $ide_path -au $user_path"
|
args+=("-ai" "$ide_path" "-au" "$user_path" "-i" "$chunk_index")
|
||||||
|
if [ -n "$log_compilation" ]; then
|
||||||
|
args+=("-l" "$log_compilation")
|
||||||
|
fi
|
||||||
for sketch in $sketches; do
|
for sketch in $sketches; do
|
||||||
local sketchdir=$(dirname $sketch)
|
local sketchdir
|
||||||
local sketchdirname=$(basename $sketchdir)
|
local sketchdirname
|
||||||
sketchnum=$(($sketchnum + 1))
|
|
||||||
|
sketchdir=$(dirname "$sketch")
|
||||||
|
sketchdirname=$(basename "$sketchdir")
|
||||||
|
sketchnum=$((sketchnum + 1))
|
||||||
|
|
||||||
if [ "$sketchnum" -le "$start_index" ] \
|
if [ "$sketchnum" -le "$start_index" ] \
|
||||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo "Building Sketch Index $(($sketchnum - 1)) - $sketchdirname"
|
echo "Building Sketch Index $sketchnum - $sketchdirname"
|
||||||
build_sketch $args -s $sketchdir $xtra_opts
|
build_sketch "${args[@]}" -s "$sketchdir" "${xtra_opts[@]}"
|
||||||
local result=$?
|
local result=$?
|
||||||
if [ $result -ne 0 ]; then
|
if [ $result -ne 0 ]; then
|
||||||
return $result
|
return $result
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -n "$log_compilation" ]; then
|
||||||
|
#remove last comma from json
|
||||||
|
if [ "$i" -eq $((len - 1)) ]; then
|
||||||
|
sed -i '$ s/.$//' "$sizes_file"
|
||||||
|
fi
|
||||||
|
#echo end of sketches sizes_file json
|
||||||
|
echo "]" >> "$sizes_file"
|
||||||
|
#echo end of board sizes_file json
|
||||||
|
echo "}," >> "$sizes_file"
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
USAGE="
|
USAGE="
|
||||||
USAGE: ${0} [command] [options]
|
USAGE: ${0} [command] [options]
|
||||||
Available commands:
|
Available commands:
|
||||||
count: Count sketches.
|
count: Count sketches.
|
||||||
build: Build a sketch.
|
build: Build a sketch.
|
||||||
chunk_build: Build a chunk of sketches.
|
chunk_build: Build a chunk of sketches.
|
||||||
|
check_requirements: Check if target meets sketch requirements.
|
||||||
"
|
"
|
||||||
|
|
||||||
cmd=$1
|
cmd=$1
|
||||||
shift
|
shift
|
||||||
if [ -z $cmd ]; then
|
if [ -z "$cmd" ]; then
|
||||||
echo "ERROR: No command supplied"
|
echo "ERROR: No command supplied"
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$cmd" in
|
case "$cmd" in
|
||||||
"count") count_sketches $*
|
"count") count_sketches "$@"
|
||||||
;;
|
;;
|
||||||
"build") build_sketch $*
|
"build") build_sketch "$@"
|
||||||
;;
|
;;
|
||||||
"chunk_build") build_sketches $*
|
"chunk_build") build_sketches "$@"
|
||||||
|
;;
|
||||||
|
"check_requirements") check_requirements "$@"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: Unrecognized command"
|
echo "ERROR: Unrecognized command"
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 2
|
exit 2
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
||||||
54
.github/scripts/tests_build.sh
vendored
54
.github/scripts/tests_build.sh
vendored
|
|
@ -2,19 +2,20 @@
|
||||||
|
|
||||||
USAGE="
|
USAGE="
|
||||||
USAGE:
|
USAGE:
|
||||||
${0} -c <chunk_build_opts>
|
${0} -c -type <test_type> <chunk_build_opts>
|
||||||
Example: ${0} -c -t esp32 -i 0 -m 15
|
Example: ${0} -c -type validation -t esp32 -i 0 -m 15
|
||||||
${0} -s sketch_name <build_opts>
|
${0} -s sketch_name <build_opts>
|
||||||
Example: ${0} -s hello_world -t esp32
|
Example: ${0} -s hello_world -t esp32
|
||||||
${0} -clean
|
${0} -clean
|
||||||
Remove build and test generated files
|
Remove build and test generated files
|
||||||
"
|
"
|
||||||
|
|
||||||
function clean(){
|
function clean {
|
||||||
rm -rf tests/*/build*/
|
|
||||||
rm -rf tests/.pytest_cache
|
rm -rf tests/.pytest_cache
|
||||||
rm -rf tests/*/__pycache__/
|
find tests/ -type d -name 'build*' -exec rm -rf "{}" \+
|
||||||
rm -rf tests/*/*.xml
|
find tests/ -type d -name '__pycache__' -exec rm -rf "{}" \+
|
||||||
|
find tests/ -name '*.xml' -exec rm -rf "{}" \+
|
||||||
|
find tests/ -name 'result_*.json' -exec rm -rf "{}" \+
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPTS_DIR="./.github/scripts"
|
SCRIPTS_DIR="./.github/scripts"
|
||||||
|
|
@ -22,7 +23,7 @@ BUILD_CMD=""
|
||||||
|
|
||||||
chunk_build=0
|
chunk_build=0
|
||||||
|
|
||||||
while [ ! -z "$1" ]; do
|
while [ -n "$1" ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
-c )
|
-c )
|
||||||
chunk_build=1
|
chunk_build=1
|
||||||
|
|
@ -35,30 +36,45 @@ while [ ! -z "$1" ]; do
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
-type )
|
||||||
|
shift
|
||||||
|
test_type=$1
|
||||||
|
;;
|
||||||
-clean )
|
-clean )
|
||||||
clean
|
clean
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
* )
|
* )
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
#source ${SCRIPTS_DIR}/install-arduino-ide.sh
|
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
|
||||||
source ${SCRIPTS_DIR}/install-arduino-cli.sh
|
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh"
|
||||||
source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
|
|
||||||
|
|
||||||
args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH"
|
args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH")
|
||||||
|
|
||||||
|
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
|
||||||
|
if [ -n "$sketch" ]; then
|
||||||
|
tmp_sketch_path=$(find tests -name "$sketch".ino)
|
||||||
|
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
|
||||||
|
echo "Sketch $sketch test type: $test_type"
|
||||||
|
test_folder="$PWD/tests/$test_type"
|
||||||
|
else
|
||||||
|
test_folder="$PWD/tests"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
test_folder="$PWD/tests/$test_type"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $chunk_build -eq 1 ]; then
|
if [ $chunk_build -eq 1 ]; then
|
||||||
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
|
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
|
||||||
args+=" -p $PWD/tests"
|
args+=("-p" "$test_folder" "-i" "0" "-m" "1")
|
||||||
else
|
else
|
||||||
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
|
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
|
||||||
args+=" -s $PWD/tests/$sketch"
|
args+=("-s" "$test_folder/$sketch")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${BUILD_CMD} ${args} $*
|
${BUILD_CMD} "${args[@]}" "$@"
|
||||||
|
|
||||||
|
|
|
||||||
28
.github/scripts/tests_matrix.sh
vendored
Normal file
28
.github/scripts/tests_matrix.sh
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
build_types="'validation'"
|
||||||
|
hw_types="'validation'"
|
||||||
|
wokwi_types="'validation'"
|
||||||
|
qemu_types="'validation'"
|
||||||
|
|
||||||
|
if [[ $IS_PR != 'true' ]] || [[ $PERFORMANCE_ENABLED == 'true' ]]; then
|
||||||
|
build_types+=",'performance'"
|
||||||
|
hw_types+=",'performance'"
|
||||||
|
#wokwi_types+=",'performance'"
|
||||||
|
#qemu_types+=",'performance'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'"
|
||||||
|
|
||||||
|
mkdir -p info
|
||||||
|
|
||||||
|
echo "[$wokwi_types]" > info/wokwi_types.txt
|
||||||
|
echo "[$targets]" > info/targets.txt
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "build-types=[$build_types]"
|
||||||
|
echo "hw-types=[$hw_types]"
|
||||||
|
echo "wokwi-types=[$wokwi_types]"
|
||||||
|
echo "qemu-types=[$qemu_types]"
|
||||||
|
echo "targets=[$targets]"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
286
.github/scripts/tests_run.sh
vendored
286
.github/scripts/tests_run.sh
vendored
|
|
@ -1,58 +1,168 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
function run_test() {
|
function run_test {
|
||||||
local target=$1
|
local target=$1
|
||||||
local sketch=$2
|
local sketch=$2
|
||||||
local options=$3
|
local options=$3
|
||||||
local erase_flash=$4
|
local erase_flash=$4
|
||||||
local sketchdir=$(dirname $sketch)
|
local sketchdir
|
||||||
local sketchname=$(basename $sketchdir)
|
local sketchname
|
||||||
|
local result=0
|
||||||
|
local error=0
|
||||||
|
local sdkconfig_path
|
||||||
|
local extra_args
|
||||||
|
local test_type
|
||||||
|
|
||||||
if [ $options -eq 0 ] && [ -f $sketchdir/cfg.json ]; then
|
sketchdir=$(dirname "$sketch")
|
||||||
len=`jq -r --arg chip $target '.targets[] | select(.name==$chip) | .fqbn | length' $sketchdir/cfg.json`
|
sketchname=$(basename "$sketchdir")
|
||||||
|
test_type=$(basename "$(dirname "$sketchdir")")
|
||||||
|
|
||||||
|
if [ "$options" -eq 0 ] && [ -f "$sketchdir"/ci.json ]; then
|
||||||
|
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json)
|
||||||
|
if [ "$len" -eq 0 ]; then
|
||||||
|
len=1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
len=1
|
len=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $len -eq 1 ]; then
|
if [ "$len" -eq 1 ]; then
|
||||||
# build_dir="tests/$sketchname/build"
|
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build.tmp/sdkconfig"
|
||||||
build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
|
else
|
||||||
report_file="tests/$sketchname/$sketchname.xml"
|
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build0.tmp/sdkconfig"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in `seq 0 $(($len - 1))`
|
if [ -f "$sketchdir"/ci.json ]; then
|
||||||
do
|
# If the target or platform is listed as false, skip the sketch. Otherwise, include it.
|
||||||
echo "Running test: $sketchname -- Config: $i"
|
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
|
||||||
if [ $erase_flash -eq 1 ]; then
|
selected_platform=$(jq -r --arg platform "$platform" '.platforms[$platform]' "$sketchdir"/ci.json)
|
||||||
esptool.py -c $target erase_flash
|
|
||||||
|
if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then
|
||||||
|
printf "\033[93mSkipping %s test for %s, platform: %s\033[0m\n" "$sketchname" "$target" "$platform"
|
||||||
|
printf "\n\n\n"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$sdkconfig_path" ]; then
|
||||||
|
printf "\033[93mSketch %s build not found in %s\nMight be due to missing target requirements or build failure\033[0m\n" "$(dirname "$sdkconfig_path")" "$sketchname"
|
||||||
|
printf "\n\n\n"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local compiled_target
|
||||||
|
compiled_target=$(grep -E "CONFIG_IDF_TARGET=" "$sdkconfig_path" | cut -d'"' -f2)
|
||||||
|
if [ "$compiled_target" != "$target" ]; then
|
||||||
|
printf "\033[91mError: Sketch %s compiled for %s, expected %s\033[0m\n" "$sketchname" "$compiled_target" "$target"
|
||||||
|
printf "\n\n\n"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$len" -eq 1 ]; then
|
||||||
|
# build_dir="$sketchdir/build"
|
||||||
|
build_dir="$HOME/.arduino/tests/$target/$sketchname/build.tmp"
|
||||||
|
report_file="$sketchdir/$target/$sketchname.xml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in $(seq 0 $((len - 1))); do
|
||||||
|
fqbn="Default"
|
||||||
|
|
||||||
|
if [ "$len" -ne 1 ]; then
|
||||||
|
fqbn=$(jq -r --arg target "$target" --argjson i "$i" '.fqbn[$target] | sort | .[$i]' "$sketchdir"/ci.json)
|
||||||
|
elif [ -f "$sketchdir"/ci.json ]; then
|
||||||
|
has_fqbn=$(jq -r --arg target "$target" '.fqbn[$target]' "$sketchdir"/ci.json)
|
||||||
|
if [ "$has_fqbn" != "null" ]; then
|
||||||
|
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | .[0]' "$sketchdir"/ci.json)
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $len -ne 1 ]; then
|
printf "\033[95mRunning test: %s -- Config: %s\033[0m\n" "$sketchname" "$fqbn"
|
||||||
# build_dir="tests/$sketchname/build$i"
|
if [ "$erase_flash" -eq 1 ]; then
|
||||||
build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
|
esptool.py -c "$target" erase_flash
|
||||||
report_file="tests/$sketchname/$sketchname$i.xml"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file
|
if [ "$len" -ne 1 ]; then
|
||||||
result=$?
|
# build_dir="$sketchdir/build$i"
|
||||||
|
build_dir="$HOME/.arduino/tests/$target/$sketchname/build$i.tmp"
|
||||||
|
report_file="$sketchdir/$target/$sketchname$i.xml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $platform == "wokwi" ]; then
|
||||||
|
extra_args=("--target" "$target" "--embedded-services" "arduino,wokwi" "--wokwi-timeout=$wokwi_timeout")
|
||||||
|
if [[ -f "$sketchdir/scenario.yaml" ]]; then
|
||||||
|
extra_args+=("--wokwi-scenario" "$sketchdir/scenario.yaml")
|
||||||
|
fi
|
||||||
|
if [[ -f "$sketchdir/diagram.$target.json" ]]; then
|
||||||
|
extra_args+=("--wokwi-diagram" "$sketchdir/diagram.$target.json")
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ $platform == "qemu" ]; then
|
||||||
|
PATH=$HOME/qemu/bin:$PATH
|
||||||
|
extra_args=("--embedded-services" "qemu" "--qemu-image-path" "$build_dir/$sketchname.ino.merged.bin")
|
||||||
|
|
||||||
|
if [ "$target" == "esp32" ] || [ "$target" == "esp32s3" ]; then
|
||||||
|
extra_args+=("--qemu-prog-path" "qemu-system-xtensa" "--qemu-cli-args=\"-machine $target -m 4M -nographic\"")
|
||||||
|
elif [ "$target" == "esp32c3" ]; then
|
||||||
|
extra_args+=("--qemu-prog-path" "qemu-system-riscv32" "--qemu-cli-args=\"-machine $target -icount 3 -nographic\"")
|
||||||
|
else
|
||||||
|
printf "\033[91mUnsupported QEMU target: %s\033[0m\n" "$target"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
extra_args=("--embedded-services" "esp,arduino")
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm "$sketchdir"/diagram.json 2>/dev/null || true
|
||||||
|
|
||||||
|
result=0
|
||||||
|
printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}"
|
||||||
|
bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$?
|
||||||
|
printf "\n"
|
||||||
if [ $result -ne 0 ]; then
|
if [ $result -ne 0 ]; then
|
||||||
return $result
|
result=0
|
||||||
|
printf "\033[95mRetrying test: %s -- Config: %s\033[0m\n" "$sketchname" "$i"
|
||||||
|
printf "\033[95mpytest \"%s/test_%s.py\" --build-dir \"%s\" --junit-xml=\"%s\" -o junit_suite_name=%s_%s_%s_%s%s %s\033[0m\n" "$sketchdir" "$sketchname" "$build_dir" "$report_file" "$test_type" "$platform" "$target" "$sketchname" "$i" "${extra_args[*]@Q}"
|
||||||
|
bash -c "set +e; pytest \"$sketchdir/test_$sketchname.py\" --build-dir \"$build_dir\" --junit-xml=\"$report_file\" -o junit_suite_name=${test_type}_${platform}_${target}_${sketchname}${i} ${extra_args[*]@Q}; exit \$?" || result=$?
|
||||||
|
printf "\n"
|
||||||
|
if [ $result -ne 0 ]; then
|
||||||
|
printf "\033[91mFailed test: %s -- Config: %s\033[0m\n\n" "$sketchname" "$i"
|
||||||
|
error=$result
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
return $error
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPTS_DIR="./.github/scripts"
|
SCRIPTS_DIR="./.github/scripts"
|
||||||
COUNT_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh count"
|
COUNT_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh count"
|
||||||
|
|
||||||
|
platform="hardware"
|
||||||
|
wokwi_timeout=60000
|
||||||
chunk_run=0
|
chunk_run=0
|
||||||
options=0
|
options=0
|
||||||
erase=0
|
erase=0
|
||||||
|
|
||||||
while [ ! -z "$1" ]; do
|
while [ -n "$1" ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
-c )
|
-c )
|
||||||
chunk_run=1
|
chunk_run=1
|
||||||
;;
|
;;
|
||||||
|
-Q )
|
||||||
|
if [ ! -d "$QEMU_PATH" ]; then
|
||||||
|
echo "QEMU path $QEMU_PATH does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
platform="qemu"
|
||||||
|
;;
|
||||||
|
-W )
|
||||||
|
shift
|
||||||
|
wokwi_timeout=$1
|
||||||
|
if [[ -z $WOKWI_CLI_TOKEN ]]; then
|
||||||
|
echo "Wokwi CLI token is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
platform="wokwi"
|
||||||
|
;;
|
||||||
-o )
|
-o )
|
||||||
options=1
|
options=1
|
||||||
;;
|
;;
|
||||||
|
|
@ -79,72 +189,102 @@ while [ ! -z "$1" ]; do
|
||||||
echo "$USAGE"
|
echo "$USAGE"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
-type )
|
||||||
|
shift
|
||||||
|
test_type=$1
|
||||||
|
;;
|
||||||
* )
|
* )
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
source ${SCRIPTS_DIR}/install-arduino-ide.sh
|
if [ ! $platform == "qemu" ]; then
|
||||||
|
source "${SCRIPTS_DIR}/install-arduino-ide.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If sketch is provided and test type is not, test type is inferred from the sketch path
|
||||||
|
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
|
||||||
|
if [ -n "$sketch" ]; then
|
||||||
|
tmp_sketch_path=$(find tests -name "$sketch".ino)
|
||||||
|
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
|
||||||
|
echo "Sketch $sketch test type: $test_type"
|
||||||
|
test_folder="$PWD/tests/$test_type"
|
||||||
|
else
|
||||||
|
test_folder="$PWD/tests"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
test_folder="$PWD/tests/$test_type"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $chunk_run -eq 0 ]; then
|
if [ $chunk_run -eq 0 ]; then
|
||||||
run_test $target $PWD/tests/$sketch/$sketch.ino $options $erase
|
if [ -z "$sketch" ]; then
|
||||||
|
echo "ERROR: Sketch name is required for single test run"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
run_test "$target" "$test_folder"/"$sketch"/"$sketch".ino $options $erase
|
||||||
|
exit $?
|
||||||
else
|
else
|
||||||
if [ "$chunk_max" -le 0 ]; then
|
if [ "$chunk_max" -le 0 ]; then
|
||||||
echo "ERROR: Chunks count must be positive number"
|
echo "ERROR: Chunks count must be positive number"
|
||||||
return 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then
|
if [ "$chunk_index" -ge "$chunk_max" ] && [ "$chunk_max" -ge 2 ]; then
|
||||||
echo "ERROR: Chunk index must be less than chunks count"
|
echo "ERROR: Chunk index must be less than chunks count"
|
||||||
return 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
${COUNT_SKETCHES} $PWD/tests $target
|
# Ignore requirements as we don't have the libs. The requirements will be checked in the run_test function
|
||||||
sketchcount=$?
|
${COUNT_SKETCHES} "$test_folder" "$target" "1"
|
||||||
set -e
|
sketchcount=$?
|
||||||
sketches=$(cat sketches.txt)
|
set -e
|
||||||
rm -rf sketches.txt
|
sketches=$(cat sketches.txt)
|
||||||
|
rm -rf sketches.txt
|
||||||
|
|
||||||
chunk_size=$(( $sketchcount / $chunk_max ))
|
chunk_size=$(( sketchcount / chunk_max ))
|
||||||
all_chunks=$(( $chunk_max * $chunk_size ))
|
all_chunks=$(( chunk_max * chunk_size ))
|
||||||
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
if [ "$all_chunks" -lt "$sketchcount" ]; then
|
||||||
chunk_size=$(( $chunk_size + 1 ))
|
chunk_size=$(( chunk_size + 1 ))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
start_index=0
|
start_index=0
|
||||||
end_index=0
|
end_index=0
|
||||||
if [ "$chunk_index" -ge "$chunk_max" ]; then
|
if [ "$chunk_index" -ge "$chunk_max" ]; then
|
||||||
start_index=$chunk_index
|
start_index=$chunk_index
|
||||||
end_index=$sketchcount
|
end_index=$sketchcount
|
||||||
else
|
else
|
||||||
start_index=$(( $chunk_index * $chunk_size ))
|
start_index=$(( chunk_index * chunk_size ))
|
||||||
if [ "$sketchcount" -le "$start_index" ]; then
|
if [ "$sketchcount" -le "$start_index" ]; then
|
||||||
echo "Skipping job"
|
exit 0
|
||||||
return 0
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
end_index=$(( $(( $chunk_index + 1 )) * $chunk_size ))
|
end_index=$(( $(( chunk_index + 1 )) * chunk_size ))
|
||||||
if [ "$end_index" -gt "$sketchcount" ]; then
|
if [ "$end_index" -gt "$sketchcount" ]; then
|
||||||
end_index=$sketchcount
|
end_index=$sketchcount
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
start_num=$(( $start_index + 1 ))
|
sketchnum=0
|
||||||
sketchnum=0
|
error=0
|
||||||
|
|
||||||
for sketch in $sketches; do
|
for sketch in $sketches; do
|
||||||
|
|
||||||
sketchnum=$(($sketchnum + 1))
|
sketchnum=$((sketchnum + 1))
|
||||||
if [ "$sketchnum" -le "$start_index" ] \
|
if [ "$sketchnum" -le "$start_index" ] \
|
||||||
|| [ "$sketchnum" -gt "$end_index" ]; then
|
|| [ "$sketchnum" -gt "$end_index" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo ""
|
|
||||||
echo "Sketch Index $(($sketchnum - 1))"
|
|
||||||
|
|
||||||
run_test $target $sketch $options $erase
|
printf "\033[95mSketch Index %s\033[0m\n" "$((sketchnum - 1))"
|
||||||
done
|
|
||||||
|
exit_code=0
|
||||||
|
run_test "$target" "$sketch" $options $erase || exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
error=$exit_code
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $error
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
46
.github/scripts/update-version.sh
vendored
46
.github/scripts/update-version.sh
vendored
|
|
@ -1,20 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Disable shellcheck warning about using 'cat' to read a file.
|
||||||
|
# shellcheck disable=SC2002
|
||||||
|
|
||||||
# For reference: add tools for all boards by replacing one line in each board
|
# For reference: add tools for all boards by replacing one line in each board
|
||||||
# "[board].upload.tool=esptool_py" to "[board].upload.tool=esptool_py\n[board].upload.tool.default=esptool_py\n[board].upload.tool.network=esp_ota"
|
# "[board].upload.tool=esptool_py" to "[board].upload.tool=esptool_py\n[board].upload.tool.default=esptool_py\n[board].upload.tool.network=esp_ota"
|
||||||
#cat boards.txt | sed "s/\([a-zA-Z0-9_\-]*\)\.upload\.tool\=esptool_py/\1\.upload\.tool\=esptool_py\\n\1\.upload\.tool\.default\=esptool_py\\n\1\.upload\.tool\.network\=esp_ota/"
|
#cat boards.txt | sed "s/\([a-zA-Z0-9_\-]*\)\.upload\.tool\=esptool_py/\1\.upload\.tool\=esptool_py\\n\1\.upload\.tool\.default\=esptool_py\\n\1\.upload\.tool\.network\=esp_ota/"
|
||||||
|
|
||||||
if [ ! $# -eq 3 ]; then
|
if [ ! $# -eq 3 ]; then
|
||||||
echo "Bad number of arguments: $#" >&2
|
echo "Bad number of arguments: $#" >&2
|
||||||
echo "usage: $0 <major> <minor> <patch>" >&2
|
echo "usage: $0 <major> <minor> <patch>" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
re='^[0-9]+$'
|
re='^[0-9]+$'
|
||||||
if [[ ! $1 =~ $re ]] || [[ ! $2 =~ $re ]] || [[ ! $3 =~ $re ]] ; then
|
if [[ ! $1 =~ $re ]] || [[ ! $2 =~ $re ]] || [[ ! $3 =~ $re ]] ; then
|
||||||
echo "error: Not a valid version: $1.$2.$3" >&2
|
echo "error: Not a valid version: $1.$2.$3" >&2
|
||||||
echo "usage: $0 <major> <minor> <patch>" >&2
|
echo "usage: $0 <major> <minor> <patch>" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ESP_ARDUINO_VERSION_MAJOR="$1"
|
ESP_ARDUINO_VERSION_MAJOR="$1"
|
||||||
|
|
@ -22,7 +24,15 @@ ESP_ARDUINO_VERSION_MINOR="$2"
|
||||||
ESP_ARDUINO_VERSION_PATCH="$3"
|
ESP_ARDUINO_VERSION_PATCH="$3"
|
||||||
ESP_ARDUINO_VERSION="$ESP_ARDUINO_VERSION_MAJOR.$ESP_ARDUINO_VERSION_MINOR.$ESP_ARDUINO_VERSION_PATCH"
|
ESP_ARDUINO_VERSION="$ESP_ARDUINO_VERSION_MAJOR.$ESP_ARDUINO_VERSION_MINOR.$ESP_ARDUINO_VERSION_PATCH"
|
||||||
|
|
||||||
|
# Get ESP-IDF version from push.yml (this way we can ensure that the version is correct even if the local libs are not up to date)
|
||||||
|
ESP_IDF_VERSION=$(grep "idf_ver:" .github/workflows/push.yml | sed 's/.*release-v\([^"]*\).*/\1/')
|
||||||
|
if [ -z "$ESP_IDF_VERSION" ]; then
|
||||||
|
echo "Error: ESP-IDF version not found in push.yml" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "New Arduino Version: $ESP_ARDUINO_VERSION"
|
echo "New Arduino Version: $ESP_ARDUINO_VERSION"
|
||||||
|
echo "ESP-IDF Version: $ESP_IDF_VERSION"
|
||||||
|
|
||||||
echo "Updating platform.txt..."
|
echo "Updating platform.txt..."
|
||||||
cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt
|
cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platform.txt && mv __platform.txt platform.txt
|
||||||
|
|
@ -30,10 +40,28 @@ cat platform.txt | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > __platfor
|
||||||
echo "Updating package.json..."
|
echo "Updating package.json..."
|
||||||
cat package.json | sed "s/.*\"version\":.*/ \"version\": \"$ESP_ARDUINO_VERSION\",/g" > __package.json && mv __package.json package.json
|
cat package.json | sed "s/.*\"version\":.*/ \"version\": \"$ESP_ARDUINO_VERSION\",/g" > __package.json && mv __package.json package.json
|
||||||
|
|
||||||
|
echo "Updating docs/conf_common.py..."
|
||||||
|
cat docs/conf_common.py | \
|
||||||
|
sed "s/.. |version| replace:: .*/.. |version| replace:: $ESP_ARDUINO_VERSION/g" | \
|
||||||
|
sed "s/.. |idf_version| replace:: .*/.. |idf_version| replace:: $ESP_IDF_VERSION/g" > docs/__conf_common.py && mv docs/__conf_common.py docs/conf_common.py
|
||||||
|
|
||||||
|
echo "Updating .gitlab/workflows/common.yml..."
|
||||||
|
cat .gitlab/workflows/common.yml | \
|
||||||
|
sed "s/ESP_IDF_VERSION:.*/ESP_IDF_VERSION: \"$ESP_IDF_VERSION\"/g" | \
|
||||||
|
sed "s/ESP_ARDUINO_VERSION:.*/ESP_ARDUINO_VERSION: \"$ESP_ARDUINO_VERSION\"/g" > .gitlab/workflows/__common.yml && mv .gitlab/workflows/__common.yml .gitlab/workflows/common.yml
|
||||||
|
|
||||||
echo "Updating cores/esp32/esp_arduino_version.h..."
|
echo "Updating cores/esp32/esp_arduino_version.h..."
|
||||||
cat cores/esp32/esp_arduino_version.h | \
|
cat cores/esp32/esp_arduino_version.h | \
|
||||||
sed "s/#define ESP_ARDUINO_VERSION_MAJOR.*/#define ESP_ARDUINO_VERSION_MAJOR $ESP_ARDUINO_VERSION_MAJOR/g" | \
|
sed "s/#define ESP_ARDUINO_VERSION_MAJOR.*/#define ESP_ARDUINO_VERSION_MAJOR $ESP_ARDUINO_VERSION_MAJOR/g" | \
|
||||||
sed "s/#define ESP_ARDUINO_VERSION_MINOR.*/#define ESP_ARDUINO_VERSION_MINOR $ESP_ARDUINO_VERSION_MINOR/g" | \
|
sed "s/#define ESP_ARDUINO_VERSION_MINOR.*/#define ESP_ARDUINO_VERSION_MINOR $ESP_ARDUINO_VERSION_MINOR/g" | \
|
||||||
sed "s/#define ESP_ARDUINO_VERSION_PATCH.*/#define ESP_ARDUINO_VERSION_PATCH $ESP_ARDUINO_VERSION_PATCH/g" > __esp_arduino_version.h && mv __esp_arduino_version.h cores/esp32/esp_arduino_version.h
|
sed "s/#define ESP_ARDUINO_VERSION_PATCH.*/#define ESP_ARDUINO_VERSION_PATCH $ESP_ARDUINO_VERSION_PATCH/g" > __esp_arduino_version.h && mv __esp_arduino_version.h cores/esp32/esp_arduino_version.h
|
||||||
|
|
||||||
|
libraries=$(find libraries -maxdepth 1 -mindepth 1 -type d -exec basename {} \;)
|
||||||
|
for lib in $libraries; do
|
||||||
|
if [ -f "libraries/$lib/library.properties" ]; then
|
||||||
|
echo "Updating Library $lib..."
|
||||||
|
cat "libraries/$lib/library.properties" | sed "s/version=.*/version=$ESP_ARDUINO_VERSION/g" > "libraries/$lib/__library.properties" && mv "libraries/$lib/__library.properties" "libraries/$lib/library.properties"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
236
.github/scripts/update_esptool.py
vendored
Normal file
236
.github/scripts/update_esptool.py
vendored
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# This script is used to re-package the esptool if needed and update the JSON file
|
||||||
|
# for the Arduino ESP32 platform.
|
||||||
|
#
|
||||||
|
# The script has only been tested on macOS.
|
||||||
|
#
|
||||||
|
# For regular esptool releases, the generated packages already contain the correct permissions,
|
||||||
|
# extensions and are uploaded to the GitHub release assets. In this case, the script will only
|
||||||
|
# update the JSON file with the information from the GitHub release.
|
||||||
|
#
|
||||||
|
# The script can be used in two modes:
|
||||||
|
# 1. Local build: The build artifacts must be already downloaded and extracted in the base_folder.
|
||||||
|
# This is useful for esptool versions that are not yet released and that are grabbed from the
|
||||||
|
# GitHub build artifacts.
|
||||||
|
# 2. Release build: The script will get the release information from GitHub and update the JSON file.
|
||||||
|
# This is useful for esptool versions that are already released and that are uploaded to the
|
||||||
|
# GitHub release assets.
|
||||||
|
#
|
||||||
|
# For local build, the artifacts must be already downloaded and extracted in the base_folder
|
||||||
|
# set with the -l option.
|
||||||
|
# For example, a base folder "esptool" should contain the following folders extracted directly
|
||||||
|
# from the GitHub build artifacts:
|
||||||
|
# esptool/esptool-linux-aarch64
|
||||||
|
# esptool/esptool-linux-amd64
|
||||||
|
# esptool/esptool-linux-armv7
|
||||||
|
# esptool/esptool-macos-amd64
|
||||||
|
# esptool/esptool-macos-arm64
|
||||||
|
# esptool/esptool-windows-amd64
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import tarfile
|
||||||
|
import zipfile
|
||||||
|
import hashlib
|
||||||
|
import requests
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def compute_sha256(filepath):
|
||||||
|
sha256 = hashlib.sha256()
|
||||||
|
with open(filepath, "rb") as f:
|
||||||
|
for block in iter(lambda: f.read(4096), b""):
|
||||||
|
sha256.update(block)
|
||||||
|
return f"SHA-256:{sha256.hexdigest()}"
|
||||||
|
|
||||||
|
def get_file_size(filepath):
|
||||||
|
return os.path.getsize(filepath)
|
||||||
|
|
||||||
|
def update_json_for_host(tmp_json_path, version, host, url, archiveFileName, checksum, size):
|
||||||
|
with open(tmp_json_path) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
for pkg in data.get("packages", []):
|
||||||
|
for tool in pkg.get("tools", []):
|
||||||
|
if tool.get("name") == "esptool_py":
|
||||||
|
tool["version"] = version
|
||||||
|
|
||||||
|
if url is None:
|
||||||
|
# If the URL is not set, we need to find the old URL and update it
|
||||||
|
for system in tool.get("systems", []):
|
||||||
|
if system.get("host") == host:
|
||||||
|
url = system.get("url").replace(system.get("archiveFileName"), archiveFileName)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print(f"No old URL found for host {host}. Using empty URL.")
|
||||||
|
url = ""
|
||||||
|
|
||||||
|
# Preserve existing systems order and update or append the new system
|
||||||
|
systems = tool.get("systems", [])
|
||||||
|
system_updated = False
|
||||||
|
for i, system in enumerate(systems):
|
||||||
|
if system.get("host") == host:
|
||||||
|
systems[i] = {
|
||||||
|
"host": host,
|
||||||
|
"url": url,
|
||||||
|
"archiveFileName": archiveFileName,
|
||||||
|
"checksum": checksum,
|
||||||
|
"size": str(size),
|
||||||
|
}
|
||||||
|
system_updated = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not system_updated:
|
||||||
|
systems.append({
|
||||||
|
"host": host,
|
||||||
|
"url": url,
|
||||||
|
"archiveFileName": archiveFileName,
|
||||||
|
"checksum": checksum,
|
||||||
|
"size": str(size),
|
||||||
|
})
|
||||||
|
tool["systems"] = systems
|
||||||
|
|
||||||
|
with open(tmp_json_path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
def update_tools_dependencies(tmp_json_path, version):
|
||||||
|
with open(tmp_json_path) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
for pkg in data.get("packages", []):
|
||||||
|
for platform in pkg.get("platforms", []):
|
||||||
|
for dep in platform.get("toolsDependencies", []):
|
||||||
|
if dep.get("name") == "esptool_py":
|
||||||
|
dep["version"] = version
|
||||||
|
|
||||||
|
with open(tmp_json_path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2, sort_keys=False, ensure_ascii=False)
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
def create_archives(version, base_folder):
|
||||||
|
archive_files = []
|
||||||
|
|
||||||
|
for dirpath in Path(base_folder).glob("esptool-*"):
|
||||||
|
if not dirpath.is_dir():
|
||||||
|
continue
|
||||||
|
|
||||||
|
base = dirpath.name[len("esptool-"):]
|
||||||
|
|
||||||
|
if "windows" in dirpath.name:
|
||||||
|
zipfile_name = f"esptool-v{version}-{base}.zip"
|
||||||
|
print(f"Creating {zipfile_name} from {dirpath} ...")
|
||||||
|
with zipfile.ZipFile(zipfile_name, "w", zipfile.ZIP_DEFLATED) as zipf:
|
||||||
|
for root, _, files in os.walk(dirpath):
|
||||||
|
for file in files:
|
||||||
|
full_path = os.path.join(root, file)
|
||||||
|
zipf.write(full_path, os.path.relpath(full_path, start=dirpath))
|
||||||
|
archive_files.append(zipfile_name)
|
||||||
|
else:
|
||||||
|
tarfile_name = f"esptool-v{version}-{base}.tar.gz"
|
||||||
|
print(f"Creating {tarfile_name} from {dirpath} ...")
|
||||||
|
for root, dirs, files in os.walk(dirpath):
|
||||||
|
for name in dirs + files:
|
||||||
|
os.chmod(os.path.join(root, name), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
|
||||||
|
stat.S_IRGRP | stat.S_IXGRP |
|
||||||
|
stat.S_IROTH | stat.S_IXOTH)
|
||||||
|
with tarfile.open(tarfile_name, "w:gz") as tar:
|
||||||
|
tar.add(dirpath, arcname=dirpath.name)
|
||||||
|
archive_files.append(tarfile_name)
|
||||||
|
|
||||||
|
return archive_files
|
||||||
|
|
||||||
|
def determine_hosts(archive_name):
|
||||||
|
if "linux-amd64" in archive_name:
|
||||||
|
return ["x86_64-pc-linux-gnu"]
|
||||||
|
elif "linux-armv7" in archive_name:
|
||||||
|
return ["arm-linux-gnueabihf"]
|
||||||
|
elif "linux-aarch64" in archive_name:
|
||||||
|
return ["aarch64-linux-gnu"]
|
||||||
|
elif "macos-amd64" in archive_name:
|
||||||
|
return ["x86_64-apple-darwin"]
|
||||||
|
elif "macos-arm64" in archive_name:
|
||||||
|
return ["arm64-apple-darwin"]
|
||||||
|
elif "windows-amd64" in archive_name:
|
||||||
|
return ["x86_64-mingw32", "i686-mingw32"]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def update_json_from_local_build(tmp_json_path, version, base_folder, archive_files):
|
||||||
|
for archive in archive_files:
|
||||||
|
print(f"Processing archive: {archive}")
|
||||||
|
hosts = determine_hosts(archive)
|
||||||
|
if not hosts:
|
||||||
|
print(f"Skipping unknown archive type: {archive}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
archive_path = Path(archive)
|
||||||
|
checksum = compute_sha256(archive_path)
|
||||||
|
size = get_file_size(archive_path)
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
|
update_json_for_host(tmp_json_path, version, host, None, archive_path.name, checksum, size)
|
||||||
|
|
||||||
|
def update_json_from_release(tmp_json_path, version, release_info):
|
||||||
|
assets = release_info.get("assets", [])
|
||||||
|
for asset in assets:
|
||||||
|
if (asset.get("name").endswith(".tar.gz") or asset.get("name").endswith(".zip")) and "esptool" in asset.get("name"):
|
||||||
|
asset_fname = asset.get("name")
|
||||||
|
print(f"Processing asset: {asset_fname}")
|
||||||
|
hosts = determine_hosts(asset_fname)
|
||||||
|
if not hosts:
|
||||||
|
print(f"Skipping unknown archive type: {asset_fname}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
asset_url = asset.get("browser_download_url")
|
||||||
|
asset_checksum = asset.get("digest").replace("sha256:", "SHA-256:")
|
||||||
|
asset_size = asset.get("size")
|
||||||
|
if asset_checksum is None:
|
||||||
|
asset_checksum = ""
|
||||||
|
print(f"Asset {asset_fname} has no checksum. Please set the checksum in the JSON file.")
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
|
update_json_for_host(tmp_json_path, version, host, asset_url, asset_fname, asset_checksum, asset_size)
|
||||||
|
|
||||||
|
def get_release_info(version):
|
||||||
|
url = f"https://api.github.com/repos/espressif/esptool/releases/tags/v{version}"
|
||||||
|
response = requests.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Repack esptool and update JSON metadata.")
|
||||||
|
parser.add_argument("version", help="Version of the esptool (e.g. 5.0.dev1)")
|
||||||
|
parser.add_argument("-l", "--local", dest="base_folder", help="Enable local build mode and set the base folder with unpacked artifacts")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
script_dir = Path(__file__).resolve().parent
|
||||||
|
json_path = (script_dir / "../../package/package_esp32_index.template.json").resolve()
|
||||||
|
tmp_json_path = Path(str(json_path) + ".tmp")
|
||||||
|
shutil.copy(json_path, tmp_json_path)
|
||||||
|
|
||||||
|
local_build = args.base_folder is not None
|
||||||
|
|
||||||
|
if local_build:
|
||||||
|
os.chdir(args.base_folder)
|
||||||
|
os.environ['COPYFILE_DISABLE'] = 'true' # this disables including resource forks in tar files on macOS
|
||||||
|
# Clear any existing archive files
|
||||||
|
for file in Path(args.base_folder).glob("esptool-*.*"):
|
||||||
|
file.unlink()
|
||||||
|
archive_files = create_archives(args.version, args.base_folder)
|
||||||
|
update_json_from_local_build(tmp_json_path, args.version, args.base_folder, archive_files)
|
||||||
|
else:
|
||||||
|
release_info = get_release_info(args.version)
|
||||||
|
update_json_from_release(tmp_json_path, args.version, release_info)
|
||||||
|
|
||||||
|
print(f"Updating esptool version fields to {args.version}")
|
||||||
|
update_tools_dependencies(tmp_json_path, args.version)
|
||||||
|
|
||||||
|
shutil.move(tmp_json_path, json_path)
|
||||||
|
print(f"Done. JSON updated at {json_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
13
.github/scripts/upload_py_tools.sh
vendored
13
.github/scripts/upload_py_tools.sh
vendored
|
|
@ -1,11 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
CHANGED_FILES=$1
|
CHANGED_FILES=$1
|
||||||
echo "Pushing '$CHANGED_FILES' as $GITHUB_ACTOR"
|
echo "Pushing '$CHANGED_FILES' as github-actions[bot]"
|
||||||
git config --global github.user "$GITHUB_ACTOR"
|
git config --global github.user "github-actions[bot]"
|
||||||
git config --global user.name "$GITHUB_ACTOR"
|
git config --global user.name "github-actions[bot]"
|
||||||
git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
for tool in $CHANGED_FILES; do
|
for tool in $CHANGED_FILES; do
|
||||||
git add tools/$tool.exe
|
git add tools/"$tool".exe
|
||||||
done
|
done
|
||||||
git commit -m "Push binary to tools"
|
git commit -m "change(tools): Push generated binaries to PR"
|
||||||
git push
|
git push
|
||||||
|
|
|
||||||
24
.github/workflows/allboards.yml
vendored
24
.github/workflows/allboards.yml
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
name: Boards Test - Remote trigger
|
name: Boards Test - Remote trigger
|
||||||
|
|
||||||
# The workflow will run on remote dispath with event-type set to "test-boards"
|
# The workflow will run on remote dispatch with event-type set to "test-boards"
|
||||||
on:
|
on:
|
||||||
repository_dispatch:
|
repository_dispatch:
|
||||||
types: [test-boards]
|
types: [test-boards]
|
||||||
|
|
@ -15,13 +15,12 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.client_payload.branch }}
|
ref: ${{ github.event.client_payload.branch }}
|
||||||
|
|
||||||
- name: Get boards fqbns
|
- name: Get boards fqbns
|
||||||
run:
|
run: bash .github/scripts/find_all_boards.sh
|
||||||
bash .github/scripts/find_all_boards.sh
|
|
||||||
|
|
||||||
setup-chunks:
|
setup-chunks:
|
||||||
needs: find-boards
|
needs: find-boards
|
||||||
|
|
@ -33,18 +32,17 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.client_payload.branch }}
|
ref: ${{ github.event.client_payload.branch }}
|
||||||
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- name: Setup jq
|
- name: Setup jq
|
||||||
uses: dcarbone/install-jq-action@v1.0.1
|
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
|
||||||
|
|
||||||
- id: set-test-chunks
|
- id: set-test-chunks
|
||||||
name: Set Chunks
|
name: Set Chunks
|
||||||
run:
|
run: echo "test-chunks<<EOF" >> $GITHUB_OUTPUT
|
||||||
echo "test-chunks<<EOF" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
echo "$( jq -nc '${{ needs.find-boards.outputs.fqbns }} | [_nwise( ${{ needs.find-boards.outputs.board-count }}/15 | ceil)]')" >> $GITHUB_OUTPUT
|
echo "$( jq -nc '${{ needs.find-boards.outputs.fqbns }} | [_nwise( ${{ needs.find-boards.outputs.board-count }}/15 | ceil)]')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
|
@ -66,18 +64,17 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.client_payload.branch }}
|
ref: ${{ github.event.client_payload.branch }}
|
||||||
|
|
||||||
- name: Echo FQBNS to file
|
- name: Echo FQBNS to file
|
||||||
run:
|
run: echo "$FQBN" > fqbns.json
|
||||||
echo "$FQBN" > fqbns.json
|
|
||||||
env:
|
env:
|
||||||
FQBN: ${{ toJSON(matrix.chunk) }}
|
FQBN: ${{ toJSON(matrix.chunk) }}
|
||||||
|
|
||||||
- name: Compile sketch
|
- name: Compile sketch
|
||||||
uses: P-R-O-C-H-Y/compile-sketches@main
|
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main
|
||||||
with:
|
with:
|
||||||
platforms: |
|
platforms: |
|
||||||
${{ env.REPOSITORY }}
|
${{ env.REPOSITORY }}
|
||||||
|
|
@ -88,5 +85,4 @@ jobs:
|
||||||
enable-warnings-report: false
|
enable-warnings-report: false
|
||||||
cli-compile-flags: |
|
cli-compile-flags: |
|
||||||
- --warnings="all"
|
- --warnings="all"
|
||||||
sketch-paths:
|
sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
|
||||||
"- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
|
|
||||||
|
|
|
||||||
33
.github/workflows/boards.yml
vendored
33
.github/workflows/boards.yml
vendored
|
|
@ -3,6 +3,10 @@ name: Boards Test
|
||||||
# The workflow will run on schedule and labeled pull requests
|
# The workflow will run on schedule and labeled pull requests
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "boards.txt"
|
||||||
|
- "libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
|
||||||
|
- ".github/workflows/boards.yml"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# It's convenient to set variables for values used multiple times in the workflow
|
# It's convenient to set variables for values used multiple times in the workflow
|
||||||
|
|
@ -18,14 +22,13 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# This step makes the contents of the repository available to the workflow
|
# This step makes the contents of the repository available to the workflow
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Setup jq
|
- name: Setup jq
|
||||||
uses: dcarbone/install-jq-action@v1.0.1
|
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
|
||||||
|
|
||||||
- name: Get board name
|
- name: Get board name
|
||||||
run:
|
run: bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.base_ref}}
|
||||||
bash .github/scripts/find_new_boards.sh ${{ github.repository }} ${{github.event.number}}
|
|
||||||
|
|
||||||
test-boards:
|
test-boards:
|
||||||
needs: find-boards
|
needs: find-boards
|
||||||
|
|
@ -38,12 +41,13 @@ jobs:
|
||||||
name: "espressif:esp32"
|
name: "espressif:esp32"
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }}
|
matrix: ${{ fromJson(needs.find-boards.outputs.fqbns) }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# This step makes the contents of the repository available to the workflow
|
# This step makes the contents of the repository available to the workflow
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Check if build.board is uppercase
|
- name: Check if build.board is uppercase
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -55,8 +59,21 @@ jobs:
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Get libs cache
|
||||||
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
with:
|
||||||
|
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
|
||||||
|
path: |
|
||||||
|
./tools/dist
|
||||||
|
./tools/esp32-arduino-libs
|
||||||
|
./tools/esptool
|
||||||
|
./tools/mk*
|
||||||
|
./tools/openocd-esp32
|
||||||
|
./tools/riscv32-*
|
||||||
|
./tools/xtensa-*
|
||||||
|
|
||||||
- name: Compile sketch
|
- name: Compile sketch
|
||||||
uses: P-R-O-C-H-Y/compile-sketches@main
|
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main
|
||||||
with:
|
with:
|
||||||
platforms: |
|
platforms: |
|
||||||
${{ env.REPOSITORY }}
|
${{ env.REPOSITORY }}
|
||||||
|
|
@ -67,5 +84,5 @@ jobs:
|
||||||
cli-compile-flags: |
|
cli-compile-flags: |
|
||||||
- --warnings="all"
|
- --warnings="all"
|
||||||
exit-on-fail: true
|
exit-on-fail: true
|
||||||
sketch-paths:
|
sketch-paths: "- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
|
||||||
"- ./libraries/ESP32/examples/CI/CIBoardsTest/CIBoardsTest.ino"
|
verbose: true
|
||||||
|
|
|
||||||
78
.github/workflows/build_py_tools.yml
vendored
78
.github/workflows/build_py_tools.yml
vendored
|
|
@ -3,35 +3,44 @@ name: Build Python Tools
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'tools/get.py'
|
- ".github/workflows/build_py_tools.yml"
|
||||||
- 'tools/espota.py'
|
- "tools/get.py"
|
||||||
- 'tools/gen_esp32part.py'
|
- "tools/espota.py"
|
||||||
- 'tools/gen_insights_package.py'
|
- "tools/gen_esp32part.py"
|
||||||
|
- "tools/gen_insights_package.py"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
find-changed-tools:
|
find-changed-tools:
|
||||||
name: Check if tools have been changed
|
name: Check if tools have been changed
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
any_changed: ${{ steps.verify-changed-files.outputs.any_changed }}
|
any_changed: ${{ steps.verify-changed-files.outputs.any_changed }}
|
||||||
all_changed_files: ${{ steps.verify-changed-files.outputs.all_changed_files }}
|
all_changed_files: ${{ steps.verify-changed-files.outputs.all_changed_files }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
|
|
||||||
|
- name: Check if checkout failed
|
||||||
|
if: failure()
|
||||||
|
run: |
|
||||||
|
echo "Checkout failed."
|
||||||
|
echo "Make sure you are using a branch inside the repository and not a fork."
|
||||||
|
|
||||||
- name: Verify Python Tools Changed
|
- name: Verify Python Tools Changed
|
||||||
uses: tj-actions/changed-files@v41
|
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
fetch_depth: '2'
|
fetch_depth: "2"
|
||||||
since_last_remote_commit: 'true'
|
since_last_remote_commit: "true"
|
||||||
files: |
|
files: |
|
||||||
tools/get.py
|
tools/get.py
|
||||||
tools/espota.py
|
tools/espota.py
|
||||||
tools/gen_esp32part.py
|
tools/gen_esp32part.py
|
||||||
tools/gen_insights_package.py
|
tools/gen_insights_package.py
|
||||||
|
|
||||||
- name: List all changed files
|
- name: List all changed files
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -47,27 +56,21 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, macos-latest, ubuntu-20.04, ARM, ARM64]
|
os: [windows-latest, macos-latest, ubuntu-latest, ubuntu-24.04-arm]
|
||||||
include:
|
include:
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
TARGET: win64
|
TARGET: win64
|
||||||
EXTEN: .exe
|
EXTEN: .exe
|
||||||
SEPARATOR: ';'
|
SEPARATOR: ";"
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
TARGET: macos
|
TARGET: macos
|
||||||
SEPARATOR: ':'
|
SEPARATOR: ":"
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-latest
|
||||||
TARGET: linux-amd64
|
TARGET: linux-amd64
|
||||||
SEPARATOR: ':'
|
SEPARATOR: ":"
|
||||||
- os: ARM
|
- os: ubuntu-24.04-arm
|
||||||
CONTAINER: python:3.8-bullseye
|
TARGET: arm
|
||||||
TARGET: arm
|
SEPARATOR: ":"
|
||||||
SEPARATOR: ':'
|
|
||||||
- os: ARM64
|
|
||||||
CONTAINER: python:3.8-bullseye
|
|
||||||
TARGET: arm64
|
|
||||||
SEPARATOR: ':'
|
|
||||||
container: ${{ matrix.CONTAINER }} # use python container on ARM
|
|
||||||
env:
|
env:
|
||||||
DISTPATH: pytools-${{ matrix.TARGET }}
|
DISTPATH: pytools-${{ matrix.TARGET }}
|
||||||
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi"
|
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi"
|
||||||
|
|
@ -86,26 +89,30 @@ jobs:
|
||||||
for tool in ${{ env.CHANGED_TOOLS }}; do
|
for tool in ${{ env.CHANGED_TOOLS }}; do
|
||||||
echo "tool $tool was changed"
|
echo "tool $tool was changed"
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
|
token: ${{ secrets.TOOLS_UPLOAD_PAT }}
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
|
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
# Skip setting python on ARM because of missing compatibility: https://github.com/actions/setup-python/issues/108
|
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
if: matrix.os != 'ARM' && matrix.os != 'ARM64'
|
|
||||||
uses: actions/setup-python@master
|
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install pyinstaller requests
|
pip install pyinstaller requests
|
||||||
|
|
||||||
- name: Build with PyInstaller
|
- name: Build with PyInstaller
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
for tool in ${{ env.CHANGED_TOOLS }}; do
|
for tool in ${{ env.CHANGED_TOOLS }}; do
|
||||||
pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=.github/pytools/espressif.ico tools/$tool.py
|
pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=.github/pytools/espressif.ico tools/$tool.py
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Sign binaries
|
- name: Sign binaries
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
env:
|
env:
|
||||||
|
|
@ -118,12 +125,14 @@ jobs:
|
||||||
{
|
{
|
||||||
./.github/pytools/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/$node.exe
|
./.github/pytools/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/$node.exe
|
||||||
}
|
}
|
||||||
|
|
||||||
- name: Test binaries
|
- name: Test binaries
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
for tool in ${{ env.CHANGED_TOOLS }}; do
|
for tool in ${{ env.CHANGED_TOOLS }}; do
|
||||||
./${{ env.DISTPATH }}/$tool${{ matrix.EXTEN }} -h
|
./${{ env.DISTPATH }}/$tool${{ matrix.EXTEN }} -h
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Push binary to tools
|
- name: Push binary to tools
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
env:
|
env:
|
||||||
|
|
@ -134,8 +143,9 @@ jobs:
|
||||||
cp -f ./${{ env.DISTPATH }}/$tool.exe tools/$tool.exe
|
cp -f ./${{ env.DISTPATH }}/$tool.exe tools/$tool.exe
|
||||||
done
|
done
|
||||||
bash .github/scripts/upload_py_tools.sh "${{ env.CHANGED_TOOLS }}"
|
bash .github/scripts/upload_py_tools.sh "${{ env.CHANGED_TOOLS }}"
|
||||||
|
|
||||||
- name: Archive artifact
|
- name: Archive artifact
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.DISTPATH }}
|
name: ${{ env.DISTPATH }}
|
||||||
path: ${{ env.DISTPATH }}
|
path: ${{ env.DISTPATH }}
|
||||||
|
|
|
||||||
31
.github/workflows/codeql_actions.yml
vendored
Normal file
31
.github/workflows/codeql_actions.yml
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: CodeQL Actions Analysis
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/*.yml"
|
||||||
|
- ".github/workflows/*.yaml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codeql-analysis:
|
||||||
|
name: CodeQL Actions Analysis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
|
with:
|
||||||
|
languages: actions
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
|
||||||
|
- name: Run CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
|
with:
|
||||||
|
category: "Analysis: Actions"
|
||||||
30
.github/workflows/codeql_python.yml
vendored
Normal file
30
.github/workflows/codeql_python.yml
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: CodeQL Python Analysis
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "**/*.py"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codeql-analysis:
|
||||||
|
name: CodeQL Python Analysis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
|
with:
|
||||||
|
languages: python
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
|
||||||
|
- name: Run CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||||
|
with:
|
||||||
|
category: "Analysis: Python"
|
||||||
22
.github/workflows/dangerjs.yml
vendored
22
.github/workflows/dangerjs.yml
vendored
|
|
@ -11,12 +11,18 @@ jobs:
|
||||||
pull-request-style-linter:
|
pull-request-style-linter:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out PR head
|
- name: Check out PR head
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: DangerJS pull request linter
|
- name: DangerJS pull request linter
|
||||||
uses: espressif/shared-github-dangerjs@v1
|
uses: espressif/shared-github-dangerjs@fb17367fd3e8ff7412603b8e946d9b19ffdb2d7f # v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
instructions-cla-link: "https://cla-assistant.io/espressif/arduino-esp32"
|
||||||
|
instructions-contributions-file: "docs/en/contributing.rst"
|
||||||
|
rule-max-commits: "false"
|
||||||
|
rule-target-branch: "false"
|
||||||
|
commit-messages-min-summary-length: "10"
|
||||||
|
|
|
||||||
58
.github/workflows/docs_build.yml
vendored
58
.github/workflows/docs_build.yml
vendored
|
|
@ -3,18 +3,17 @@ name: Documentation Build and Deploy CI
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- release/*
|
- release/v2.x
|
||||||
paths:
|
paths:
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '.github/workflows/docs_build.yml'
|
- ".github/workflows/docs_build.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '.github/workflows/docs_build.yml'
|
- ".github/workflows/docs_build.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build-docs:
|
build-docs:
|
||||||
name: Build ESP-Docs
|
name: Build ESP-Docs
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
@ -22,23 +21,28 @@ jobs:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
python-version: '3.10'
|
with:
|
||||||
- name: Build
|
cache-dependency-path: docs/requirements.txt
|
||||||
run: |
|
cache: "pip"
|
||||||
sudo apt update
|
python-version: "3.10"
|
||||||
sudo apt install python3-pip python3-setuptools
|
|
||||||
# GitHub CI installs pip3 and setuptools outside the path.
|
- name: Build
|
||||||
# Update the path to include them and run.
|
run: |
|
||||||
cd ./docs
|
sudo apt update
|
||||||
PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary
|
sudo apt install python3-pip python3-setuptools
|
||||||
PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en
|
# GitHub CI installs pip3 and setuptools outside the path.
|
||||||
- name: Archive Docs
|
# Update the path to include them and run.
|
||||||
uses: actions/upload-artifact@v2
|
cd ./docs
|
||||||
with:
|
PATH=/home/runner/.local/bin:$PATH pip3 install -r requirements.txt --prefer-binary
|
||||||
name: docs
|
PATH=/home/runner/.local/bin:$PATH SPHINXOPTS="-W" build-docs -l en
|
||||||
path: docs
|
|
||||||
|
- name: Archive Docs
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: docs
|
||||||
|
path: docs
|
||||||
|
|
|
||||||
83
.github/workflows/docs_deploy.yml
vendored
83
.github/workflows/docs_deploy.yml
vendored
|
|
@ -1,18 +1,19 @@
|
||||||
name: Documentation Build and Production Deploy CI
|
name: Documentation Build and Production Deploy CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
workflow_run:
|
||||||
types: [published]
|
workflows: ["ESP32 Arduino Release"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- release/*
|
- release/v2.x
|
||||||
- master
|
- master
|
||||||
paths:
|
paths:
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '.github/workflows/docs_deploy.yml'
|
- ".github/workflows/docs_deploy.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
deploy-prod-docs:
|
deploy-prod-docs:
|
||||||
name: Deploy Documentation on Production
|
name: Deploy Documentation on Production
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
@ -20,32 +21,42 @@ jobs:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Check if release workflow is successful
|
||||||
with:
|
if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion != 'success' }}
|
||||||
submodules: true
|
run: |
|
||||||
- uses: actions/setup-python@v5
|
echo "Release workflow failed. Exiting..."
|
||||||
with:
|
exit 1
|
||||||
python-version: '3.10'
|
|
||||||
- name: Deploy Documentation
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
env:
|
with:
|
||||||
# Deploy to production server
|
submodules: true
|
||||||
# DOCS_BUILD_DIR: "./docs/_build/"
|
|
||||||
DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }}
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }}
|
with:
|
||||||
DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }}
|
cache-dependency-path: docs/requirements.txt
|
||||||
DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }}
|
cache: "pip"
|
||||||
DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }}
|
python-version: "3.10"
|
||||||
run: |
|
|
||||||
sudo apt update
|
- name: Deploy Documentation
|
||||||
sudo apt install python3-pip python3-setuptools
|
env:
|
||||||
source ./docs/utils.sh
|
# Deploy to production server
|
||||||
add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
# DOCS_BUILD_DIR: "./docs/_build/"
|
||||||
export GIT_VER=$(git describe --always)
|
DOCS_DEPLOY_PRIVATEKEY: ${{ secrets.DOCS_KEY }}
|
||||||
echo "PIP install requirements..."
|
DOCS_DEPLOY_PATH: ${{ secrets.DOCS_PATH }}
|
||||||
pip3 install --user -r ./docs/requirements.txt
|
DOCS_DEPLOY_SERVER: ${{ secrets.DOCS_SERVER }}
|
||||||
echo "Building the Docs..."
|
DOCS_DEPLOY_SERVER_USER: ${{ secrets.DOCS_USER }}
|
||||||
cd ./docs && build-docs -l en
|
DOCS_DEPLOY_URL_BASE: ${{ secrets.DOCS_URL }}
|
||||||
echo "Deploy the Docs..."
|
run: |
|
||||||
export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/
|
sudo apt update
|
||||||
cd $GITHUB_WORKSPACE/docs
|
sudo apt install python3-pip python3-setuptools
|
||||||
deploy-docs
|
source ./docs/utils.sh
|
||||||
|
add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||||
|
export GIT_VER=$(git describe --always)
|
||||||
|
echo "PIP install requirements..."
|
||||||
|
pip3 install --user -r ./docs/requirements.txt
|
||||||
|
echo "Building the Docs..."
|
||||||
|
cd ./docs && build-docs -l en
|
||||||
|
echo "Deploy the Docs..."
|
||||||
|
export DOCS_BUILD_DIR=$GITHUB_WORKSPACE/docs/
|
||||||
|
cd $GITHUB_WORKSPACE/docs
|
||||||
|
deploy-docs
|
||||||
|
|
|
||||||
23
.github/workflows/gh-pages.yml
vendored
23
.github/workflows/gh-pages.yml
vendored
|
|
@ -3,21 +3,22 @@ name: GitHub Pages CI
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- pages
|
- pages
|
||||||
paths:
|
paths:
|
||||||
- 'README.md'
|
- "README.md"
|
||||||
- '.github/scripts/on-pages.sh'
|
- ".github/scripts/on-pages.sh"
|
||||||
- '.github/workflows/gh-pages.yml'
|
- ".github/workflows/gh-pages.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build-pages:
|
build-pages:
|
||||||
name: Build GitHub Pages
|
name: Build GitHub Pages
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout repository
|
||||||
- name: Copy Files
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
- name: Copy Files
|
||||||
run: bash ./.github/scripts/on-pages.sh
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: bash ./.github/scripts/on-pages.sh
|
||||||
|
|
|
||||||
118
.github/workflows/hil.yml
vendored
118
.github/workflows/hil.yml
vendored
|
|
@ -1,118 +0,0 @@
|
||||||
name: Run tests in hardware
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, reopened, synchronize, labeled]
|
|
||||||
|
|
||||||
schedule:
|
|
||||||
- cron: '0 2 * * *'
|
|
||||||
|
|
||||||
env:
|
|
||||||
MAX_CHUNKS: 15
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: hil-${{github.event.pull_request.number || github.ref}}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
gen_chunks:
|
|
||||||
if: |
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
|
|
||||||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
|
|
||||||
name: Generate Chunks matrix
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
chunks: ${{ steps.gen-chunks.outputs.chunks }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Generate Chunks matrix
|
|
||||||
id: gen-chunks
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
.github/scripts/sketch_utils.sh count tests
|
|
||||||
sketches=$?
|
|
||||||
if [[ $sketches -ge ${{env.MAX_CHUNKS}} ]]; then
|
|
||||||
$sketches=${{env.MAX_CHUNKS}}
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
rm sketches.txt
|
|
||||||
CHUNKS=$(jq -c -n '$ARGS.positional' --args `seq 0 1 $((sketches - 1))`)
|
|
||||||
echo "chunks=${CHUNKS}" >>$GITHUB_OUTPUT
|
|
||||||
|
|
||||||
Build:
|
|
||||||
needs: gen_chunks
|
|
||||||
name: ${{matrix.chip}}-Build#${{matrix.chunks}}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
|
|
||||||
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Build sketches
|
|
||||||
run: |
|
|
||||||
bash .github/scripts/tests_build.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}}
|
|
||||||
- name: Upload ${{matrix.chip}}-${{matrix.chunks}} artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
|
|
||||||
path: |
|
|
||||||
~/.arduino/tests/*/build*.tmp/*.bin
|
|
||||||
~/.arduino/tests/*/build*.tmp/*.json
|
|
||||||
if-no-files-found: error
|
|
||||||
Test:
|
|
||||||
needs: [gen_chunks, Build]
|
|
||||||
name: ${{matrix.chip}}-Test#${{matrix.chunks}}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
|
|
||||||
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
|
|
||||||
runs-on: [arduino, "${{matrix.chip}}"]
|
|
||||||
container:
|
|
||||||
image: python:3.10.1-bullseye
|
|
||||||
options: --privileged
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download ${{matrix.chip}}-${{matrix.chunks}} artifacts
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
|
|
||||||
path: ~/.arduino/tests/
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
pip install -U pip
|
|
||||||
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
|
|
||||||
apt update && apt install -y -qq jq
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: |
|
|
||||||
bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -e
|
|
||||||
|
|
||||||
- name: Upload test result artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: test_results-${{matrix.chip}}-${{matrix.chunks}}
|
|
||||||
path: tests/*/*.xml
|
|
||||||
|
|
||||||
event_file:
|
|
||||||
name: "Event File"
|
|
||||||
if: |
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
|
|
||||||
github.event_name == 'schedule'
|
|
||||||
needs: Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Upload
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: Event File
|
|
||||||
path: ${{github.event_path}}
|
|
||||||
57
.github/workflows/lib.json
vendored
57
.github/workflows/lib.json
vendored
|
|
@ -9,7 +9,8 @@
|
||||||
{
|
{
|
||||||
"name": "ArduinoBLE",
|
"name": "ArduinoBLE",
|
||||||
"exclude_targets": [
|
"exclude_targets": [
|
||||||
"esp32s2"
|
"esp32s2",
|
||||||
|
"esp32p4"
|
||||||
],
|
],
|
||||||
"sketch_path": [
|
"sketch_path": [
|
||||||
"~/Arduino/libraries/ArduinoBLE/examples/Central/Scan/Scan.ino"
|
"~/Arduino/libraries/ArduinoBLE/examples/Central/Scan/Scan.ino"
|
||||||
|
|
@ -23,16 +24,52 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source-url": "https://github.com/me-no-dev/ESPAsyncWebServer.git",
|
"source-url": "https://github.com/ESP32Async/ESPAsyncWebServer.git",
|
||||||
"required-libs": [
|
"required-libs": [
|
||||||
{"source-url": "https://github.com/me-no-dev/AsyncTCP.git"}
|
{"source-url": "https://github.com/ESP32Async/AsyncTCP.git"}
|
||||||
],
|
],
|
||||||
"exclude_targets": [],
|
"exclude_targets": [],
|
||||||
"sketch_path": [
|
"sketch_path": [
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Auth/Auth.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/CORS/CORS.ino",
|
||||||
"~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino",
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino",
|
||||||
"~/Arduino/libraries/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino",
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/CatchAllHandler/CatchAllHandler.ino",
|
||||||
"~/Arduino/libraries/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino",
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkResponse/ChunkResponse.ino",
|
||||||
"~/Arduino/libraries/ESPAsyncWebServer/examples/simple_server/simple_server.ino"
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/ChunkRetryResponse/ChunkRetryResponse.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/EndBegin/EndBegin.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Filters/Filters.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/FlashResponse/FlashResponse.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/HeaderManipulation/HeaderManipulation.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Headers/Headers.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Json/Json.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Logging/Logging.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/MessagePack/MessagePack.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Middleware/Middleware.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Params/Params.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/PartitionDownloader/PartitionDownloader.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/PerfTests/PerfTests.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/RateLimit/RateLimit.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Redirect/Redirect.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuation/RequestContinuation.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/RequestContinuationComplete/RequestContinuationComplete.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/ResumableDownload/ResumableDownload.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Rewrite/Rewrite.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/ServerSentEvents/ServerSentEvents.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/ServerState/ServerState.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/SkipServerMiddleware/SkipServerMiddleware.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/SlowChunkResponse/SlowChunkResponse.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/StaticFile/StaticFile.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Templates/Templates.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/Upload/Upload.ino",
|
||||||
|
"~/Arduino/libraries/ESPAsyncWebServer/examples/WebSocket/WebSocket.ino"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EthernetESP32",
|
||||||
|
"exclude_targets": [],
|
||||||
|
"sketch_path": [
|
||||||
|
"~/Arduino/libraries/EthernetESP32/examples/LegacyEthernetTest/LegacyEthernetTest.ino",
|
||||||
|
"~/Arduino/libraries/EthernetESP32/examples/TwoEthernets/TwoEthernets.ino"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -62,5 +99,13 @@
|
||||||
"sketch_path": [
|
"sketch_path": [
|
||||||
"~/Arduino/libraries/WS2812FX/examples/ws2812fx_spi/ws2812fx_spi.ino"
|
"~/Arduino/libraries/WS2812FX/examples/ws2812fx_spi/ws2812fx_spi.ino"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ZACwire for TSic",
|
||||||
|
"exclude_targets": [],
|
||||||
|
"sketch_path": [
|
||||||
|
"~/Arduino/libraries/ZACwire_for_TSic/examples/ReadingTwoTSICs/ReadingTwoTSICs.ino",
|
||||||
|
"~/Arduino/libraries/ZACwire_for_TSic/examples/ReadSingleTSIC206/ReadSingleTSIC206.ino"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
68
.github/workflows/lib.yml
vendored
68
.github/workflows/lib.yml
vendored
|
|
@ -7,7 +7,11 @@ on:
|
||||||
|
|
||||||
# Schedule weekly builds on every Sunday at 4 am
|
# Schedule weekly builds on every Sunday at 4 am
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 4 * * SUN'
|
- cron: "0 4 * * SUN"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: libs-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# It's convenient to set variables for values used multiple times in the workflow
|
# It's convenient to set variables for values used multiple times in the workflow
|
||||||
|
|
@ -23,7 +27,6 @@ jobs:
|
||||||
contains(github.event.pull_request.labels.*.name, 'lib_test') ||
|
contains(github.event.pull_request.labels.*.name, 'lib_test') ||
|
||||||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
|
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REPOSITORY: |
|
REPOSITORY: |
|
||||||
- source-path: '.'
|
- source-path: '.'
|
||||||
|
|
@ -38,6 +41,7 @@ jobs:
|
||||||
- esp32s3
|
- esp32s3
|
||||||
- esp32c6
|
- esp32c6
|
||||||
- esp32h2
|
- esp32h2
|
||||||
|
- esp32p4
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- target: esp32
|
- target: esp32
|
||||||
|
|
@ -52,15 +56,16 @@ jobs:
|
||||||
fqbn: espressif:esp32:esp32c6
|
fqbn: espressif:esp32:esp32c6
|
||||||
- target: esp32h2
|
- target: esp32h2
|
||||||
fqbn: espressif:esp32:esp32h2
|
fqbn: espressif:esp32:esp32h2
|
||||||
|
- target: esp32p4
|
||||||
|
fqbn: espressif:esp32:esp32p4
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# This step makes the contents of the repository available to the workflow
|
# This step makes the contents of the repository available to the workflow
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Compile sketch
|
- name: Compile sketch
|
||||||
uses: P-R-O-C-H-Y/compile-sketches@main
|
uses: P-R-O-C-H-Y/compile-sketches@a62f069b92dc8f5053da4ac439ea6d1950cf6379 # main
|
||||||
with:
|
with:
|
||||||
platforms: |
|
platforms: |
|
||||||
${{ env.REPOSITORY }}
|
${{ env.REPOSITORY }}
|
||||||
|
|
@ -75,61 +80,66 @@ jobs:
|
||||||
- --warnings="all"
|
- --warnings="all"
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
|
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-${{ matrix.target }}
|
||||||
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
|
|
||||||
report-to-file:
|
report-to-file:
|
||||||
needs: compile-sketch # Wait for the compile job to finish to get the data for the report
|
needs: compile-sketch # Wait for the compile job to finish to get the data for the report
|
||||||
if: github.event_name == 'schedule' # Only run the job when the workflow is triggered by a schedule
|
if: github.event_name == 'schedule' # Only run the job when the workflow is triggered by a schedule
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
# Check out repository
|
# Check out repository
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
token: ${{ env.GITHUB_TOKEN }}
|
token: ${{ env.GITHUB_TOKEN }}
|
||||||
fetch-depth: '0'
|
fetch-depth: "0"
|
||||||
|
|
||||||
- name: Switch branch
|
- name: Switch branch
|
||||||
run:
|
run: git checkout remotes/origin/gh-pages
|
||||||
git checkout remotes/origin/gh-pages
|
|
||||||
|
|
||||||
# This step is needed to get the size data produced by the compile jobs
|
# This step is needed to get the size data produced by the compile jobs
|
||||||
- name: Download sketches reports artifact
|
- name: Download sketches reports artifact
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
with:
|
with:
|
||||||
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
|
pattern: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}-*
|
||||||
|
merge-multiple: true
|
||||||
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
|
|
||||||
- name: Report results
|
- name: Report results
|
||||||
uses: P-R-O-C-H-Y/report-size-deltas@main
|
uses: P-R-O-C-H-Y/report-size-deltas@4a79caa6dcc3579024293638b97156106edc588e # main
|
||||||
with:
|
with:
|
||||||
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
destination-file: ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
||||||
|
|
||||||
- name: Append file with action URL
|
- name: Append file with action URL
|
||||||
run:
|
run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
||||||
echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
|
||||||
|
|
||||||
- name: Push to github repo
|
- name: Push to github repo
|
||||||
run: |
|
run: |
|
||||||
git config user.name github-actions
|
git config user.name "github-actions[bot]"
|
||||||
git config user.email github-actions@github.com
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
git add ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
git add ${{ env.RESULT_LIBRARY_TEST_FILE }}
|
||||||
git commit -m "Generated External Libraries Test Results"
|
git commit -m "Generated External Libraries Test Results"
|
||||||
git push origin HEAD:gh-pages
|
git push origin HEAD:gh-pages
|
||||||
|
|
||||||
event_file:
|
#Upload PR number as artifact
|
||||||
name: "Event File"
|
upload-pr-number:
|
||||||
if: |
|
name: Upload PR number
|
||||||
contains(github.event.pull_request.labels.*.name, 'lib_test')
|
if: (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'lib_test'))
|
||||||
needs: compile-sketch
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Upload
|
- name: Save the PR number in an artifact
|
||||||
uses: actions/upload-artifact@v2
|
shell: bash
|
||||||
with:
|
env:
|
||||||
name: Event File
|
PR_NUM: ${{ github.event.number }}
|
||||||
path: ${{github.event_path}}
|
run: echo $PR_NUM > pr_num.txt
|
||||||
|
|
||||||
|
- name: Upload PR number
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: pr_number
|
||||||
|
path: ./pr_num.txt
|
||||||
|
overwrite: true
|
||||||
|
|
|
||||||
64
.github/workflows/pre-commit-status.yml
vendored
Normal file
64
.github/workflows/pre-commit-status.yml
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# This needs to be in a separate workflow because it requires higher permissions than the calling workflow
|
||||||
|
name: Report Pre-commit Check Status
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [Pre-commit hooks]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
statuses: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
report-success:
|
||||||
|
name: Report pre-commit success
|
||||||
|
if: github.event.workflow_run.conclusion == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Report success
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Pre-commit checks',
|
||||||
|
description: 'Pre-commit checks successful',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: 'success',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
|
|
||||||
|
report-pending:
|
||||||
|
name: Report pre-commit pending
|
||||||
|
if: github.event.workflow_run.conclusion != 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Report pending
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Pre-commit checks',
|
||||||
|
description: 'The pre-commit checks need to be successful before merging',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: 'pending',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
80
.github/workflows/pre-commit.yml
vendored
Normal file
80
.github/workflows/pre-commit.yml
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
name: Pre-commit hooks
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
types: [opened, reopened, synchronize, labeled]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: pre-commit-${{github.event.pull_request.number || github.ref}}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
if: |
|
||||||
|
github.event_name != 'pull_request' ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'Status: Pending Merge') ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks')
|
||||||
|
|
||||||
|
name: Check if fixes are needed
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout latest commit
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- name: Remove Label
|
||||||
|
if: contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks')
|
||||||
|
run: gh pr edit ${{ github.event.number }} --remove-label 'Re-trigger Pre-commit Hooks'
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Set up Python 3
|
||||||
|
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
|
with:
|
||||||
|
cache-dependency-path: tools/pre-commit/requirements.txt
|
||||||
|
cache: "pip"
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Get Python version hash
|
||||||
|
run: |
|
||||||
|
echo "Using $(python -VV)"
|
||||||
|
echo "PY_HASH=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Restore pre-commit cache
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
id: restore-cache
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/pre-commit
|
||||||
|
key: pre-commit-${{ env.PY_HASH }}-${{ hashFiles('.pre-commit-config.yaml', '.github/workflows/pre-commit.yml', 'tools/pre-commit/requirements.txt') }}
|
||||||
|
|
||||||
|
- name: Install python dependencies
|
||||||
|
run: python -m pip install -r tools/pre-commit/requirements.txt
|
||||||
|
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
|
||||||
|
|
||||||
|
- name: Run pre-commit hooks in changed files
|
||||||
|
run: pre-commit run --color=always --show-diff-on-failure --files ${{ steps.changed-files.outputs.all_changed_files }}
|
||||||
|
|
||||||
|
- name: Save pre-commit cache
|
||||||
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: ${{ always() && steps.restore-cache.outputs.cache-hit != 'true' }}
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/pre-commit
|
||||||
|
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||||
|
|
||||||
|
- name: Push changes using pre-commit-ci-lite
|
||||||
|
uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
||||||
|
# Only push changes in PRs
|
||||||
|
if: ${{ always() && github.event_name == 'pull_request' }}
|
||||||
|
with:
|
||||||
|
msg: "ci(pre-commit): Apply automatic fixes"
|
||||||
38
.github/workflows/publish.yml
vendored
38
.github/workflows/publish.yml
vendored
|
|
@ -1,38 +0,0 @@
|
||||||
name: Unit Test Results
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: [Run tests in hardware]
|
|
||||||
branches-ignore: [master]
|
|
||||||
|
|
||||||
types:
|
|
||||||
- completed
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
unit-test-results:
|
|
||||||
name: Unit Test Results
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: |
|
|
||||||
github.event.workflow_run.event == 'pull_request' &&
|
|
||||||
(github.event.workflow_run.conclusion == 'success' ||
|
|
||||||
github.event.workflow_run.conclusion == 'failure')
|
|
||||||
steps:
|
|
||||||
- name: Download and Extract Artifacts
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
||||||
run: |
|
|
||||||
mkdir -p artifacts && cd artifacts
|
|
||||||
artifacts_url=${{ github.event.workflow_run.artifacts_url }}
|
|
||||||
gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
|
|
||||||
do
|
|
||||||
IFS=$'\t' read name url <<< "$artifact"
|
|
||||||
gh api $url > "$name.zip"
|
|
||||||
unzip -d "$name" "$name.zip"
|
|
||||||
done
|
|
||||||
- name: Publish Unit Test Results
|
|
||||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
|
||||||
with:
|
|
||||||
commit: ${{ github.event.workflow_run.head_sha }}
|
|
||||||
event_file: artifacts/Event File/event.json
|
|
||||||
event_name: ${{ github.event.workflow_run.event }}
|
|
||||||
files: "artifacts/**/*.xml"
|
|
||||||
23
.github/workflows/publishlib.yml
vendored
23
.github/workflows/publishlib.yml
vendored
|
|
@ -11,7 +11,6 @@ env:
|
||||||
# It's convenient to set variables for values used multiple times in the workflow
|
# It's convenient to set variables for values used multiple times in the workflow
|
||||||
SKETCHES_REPORTS_PATH: artifacts/libraries-report
|
SKETCHES_REPORTS_PATH: artifacts/libraries-report
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
PR_EVENT_PATH: artifacts/Event File/event.json
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lib-test-results:
|
lib-test-results:
|
||||||
|
|
@ -25,17 +24,33 @@ jobs:
|
||||||
- name: Download and Extract Artifacts
|
- name: Download and Extract Artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir -p artifacts && cd artifacts
|
mkdir -p artifacts && cd artifacts
|
||||||
|
mkdir -p libraries-report
|
||||||
|
mkdir -p workflows
|
||||||
artifacts_url=${{ github.event.workflow_run.artifacts_url }}
|
artifacts_url=${{ github.event.workflow_run.artifacts_url }}
|
||||||
gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
|
gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
|
||||||
do
|
do
|
||||||
IFS=$'\t' read name url <<< "$artifact"
|
IFS=$'\t' read name url <<< "$artifact"
|
||||||
gh api $url > "$name.zip"
|
gh api $url > "$name.zip"
|
||||||
unzip -d "$name" "$name.zip"
|
unzip -j "$name.zip" -d "temp_$name"
|
||||||
|
if [[ "$name" == "pr_number" ]]; then
|
||||||
|
mv "temp_$name"/* workflows
|
||||||
|
else
|
||||||
|
mv "temp_$name"/* libraries-report
|
||||||
|
fi
|
||||||
|
rm -r "temp_$name"
|
||||||
done
|
done
|
||||||
|
echo "Contents of parent directory:"
|
||||||
|
ls -R ..
|
||||||
|
|
||||||
|
- name: Read the pr_num file
|
||||||
|
id: pr_num_reader
|
||||||
|
uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7
|
||||||
|
with:
|
||||||
|
path: ./artifacts/workflows/pr_num.txt
|
||||||
|
|
||||||
- name: Report results
|
- name: Report results
|
||||||
uses: P-R-O-C-H-Y/report-size-deltas@main
|
uses: P-R-O-C-H-Y/report-size-deltas@256d1f13e4195cd7fd436d2f959e6dc4d5e4b406 # libs
|
||||||
with:
|
with:
|
||||||
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
github-token: ${{ env.GITHUB_TOKEN }}
|
github-token: ${{ env.GITHUB_TOKEN }}
|
||||||
pr-event-path: ${{ env.PR_EVENT_PATH }}
|
pr-number: "${{ steps.pr_num_reader.outputs.content }}"
|
||||||
|
|
|
||||||
52
.github/workflows/publishsizes-2.x.yml
vendored
Normal file
52
.github/workflows/publishsizes-2.x.yml
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
name: Sizes Results (master-v2.x)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
# It's convenient to set variables for values used multiple times in the workflow
|
||||||
|
SKETCHES_REPORTS_PATH: artifacts/sizes-report
|
||||||
|
RESULT_SIZES_TEST_FILE: SIZES_TEST.md
|
||||||
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sizes-test-results:
|
||||||
|
name: Sizes Comparison Results
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout gh-pages branch
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
ref: gh-pages
|
||||||
|
|
||||||
|
- name: Create folder structure
|
||||||
|
run: |
|
||||||
|
mkdir -p artifacts && cd artifacts
|
||||||
|
mkdir -p sizes-report
|
||||||
|
mkdir -p sizes-report/master
|
||||||
|
mkdir -p sizes-report/pr
|
||||||
|
|
||||||
|
# master folder is a base for comparison
|
||||||
|
# pr folder is for comparison with master
|
||||||
|
- name: Download JSON file
|
||||||
|
run: |
|
||||||
|
mv master_cli_compile/*.json artifacts/sizes-report/pr/
|
||||||
|
mv v2.x_cli_compile/*.json artifacts/sizes-report/master/
|
||||||
|
|
||||||
|
- name: Report results
|
||||||
|
uses: P-R-O-C-H-Y/report-size-deltas@2043188c68f483a7b50527c4eacf609d05bb67a5 # sizes_v2
|
||||||
|
with:
|
||||||
|
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
|
github-token: ${{ env.GITHUB_TOKEN }}
|
||||||
|
destination-file: ${{ env.RESULT_SIZES_TEST_FILE }}
|
||||||
|
|
||||||
|
- name: Append file with action URL
|
||||||
|
run: echo "/ [GitHub Action Link](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})" >> ${{ env.RESULT_SIZES_TEST_FILE }}
|
||||||
|
|
||||||
|
- name: Push to github repo
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add ${{ env.RESULT_SIZES_TEST_FILE }}
|
||||||
|
git commit -m "Generated Sizes Results (master-v2.x)"
|
||||||
|
git push origin HEAD:gh-pages
|
||||||
73
.github/workflows/publishsizes.yml
vendored
Normal file
73
.github/workflows/publishsizes.yml
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
name: Sizes Results
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [Compilation Tests]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
# It's convenient to set variables for values used multiple times in the workflow
|
||||||
|
SKETCHES_REPORTS_PATH: artifacts/sizes-report
|
||||||
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sizes-test-results:
|
||||||
|
name: Sizes Comparison Results
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: |
|
||||||
|
github.event.workflow_run.event == 'pull_request' &&
|
||||||
|
github.event.workflow_run.conclusion == 'success'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout gh-pages branch
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
ref: gh-pages
|
||||||
|
|
||||||
|
- name: Create folder structure
|
||||||
|
run: |
|
||||||
|
mkdir -p artifacts && cd artifacts
|
||||||
|
mkdir -p sizes-report
|
||||||
|
mkdir -p sizes-report/master
|
||||||
|
mkdir -p sizes-report/pr
|
||||||
|
|
||||||
|
- name: Download JSON file
|
||||||
|
run: |
|
||||||
|
mv master_cli_compile/*.json artifacts/sizes-report/master/
|
||||||
|
|
||||||
|
- name: Download and Extract Artifacts
|
||||||
|
run: |
|
||||||
|
cd artifacts
|
||||||
|
artifacts_url=${{ github.event.workflow_run.artifacts_url }}
|
||||||
|
gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
|
||||||
|
do
|
||||||
|
IFS=$'\t' read name url <<< "$artifact"
|
||||||
|
# Only process pr_number and pr_cli_compile artifacts
|
||||||
|
if [[ "$name" == "pr_number" || "$name" =~ ^pr_cli_compile_[0-9]+$ ]]; then
|
||||||
|
gh api $url > "$name.zip"
|
||||||
|
unzip -o -j "$name.zip" -d "temp_$name"
|
||||||
|
if [[ "$name" == "pr_number" ]]; then
|
||||||
|
mv "temp_$name"/* sizes-report
|
||||||
|
elif [[ "$name" =~ ^pr_cli_compile_[0-9]+$ ]]; then
|
||||||
|
mv "temp_$name"/* sizes-report/pr
|
||||||
|
fi
|
||||||
|
rm -r "temp_$name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "Contents of parent directory:"
|
||||||
|
ls -R ..
|
||||||
|
|
||||||
|
- name: Read the pr_num file
|
||||||
|
id: pr_num_reader
|
||||||
|
uses: juliangruber/read-file-action@b549046febe0fe86f8cb4f93c24e284433f9ab58 # v1.1.7
|
||||||
|
with:
|
||||||
|
path: ./artifacts/sizes-report/pr_num.txt
|
||||||
|
|
||||||
|
- name: Report results
|
||||||
|
uses: P-R-O-C-H-Y/report-size-deltas@bea91d2c99ca80c88a883b39b1c4012f00ec3d09 # sizes_v2
|
||||||
|
with:
|
||||||
|
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||||
|
github-token: ${{ env.GITHUB_TOKEN }}
|
||||||
|
pr-number: "${{ steps.pr_num_reader.outputs.content }}"
|
||||||
339
.github/workflows/push.yml
vendored
339
.github/workflows/push.yml
vendored
|
|
@ -1,56 +1,224 @@
|
||||||
name: ESP32 Arduino CI
|
name: Compilation Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
log_level:
|
||||||
|
description: "Log level"
|
||||||
|
default: "none"
|
||||||
|
type: "choice"
|
||||||
|
required: true
|
||||||
|
options:
|
||||||
|
- "none"
|
||||||
|
- "error"
|
||||||
|
- "warn"
|
||||||
|
- "info"
|
||||||
|
- "debug"
|
||||||
|
- "verbose"
|
||||||
|
schedule:
|
||||||
|
# Every Sunday at 2:00 UTC run a build with verbose log level
|
||||||
|
- cron: "0 2 * * SUN"
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- release/*
|
- release/*
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "cores/**"
|
||||||
|
- "libraries/**"
|
||||||
|
- "!libraries/**.md"
|
||||||
|
- "!libraries/**.txt"
|
||||||
|
- "!libraries/**.properties"
|
||||||
|
- "!libraries/**.py"
|
||||||
|
- "package/**"
|
||||||
|
- "idf_component_examples/**"
|
||||||
|
- "tools/**.py"
|
||||||
|
- "platform.txt"
|
||||||
|
- "programmers.txt"
|
||||||
|
- "idf_component.yml"
|
||||||
|
- "Kconfig.projbuild"
|
||||||
|
- "package.json"
|
||||||
|
- "CMakeLists.txt"
|
||||||
|
- ".github/workflows/push.yml"
|
||||||
|
- ".github/scripts/**"
|
||||||
|
- "!.github/scripts/find_*"
|
||||||
|
- "!.github/scripts/on-release.sh"
|
||||||
|
- "!.github/scripts/tests_*"
|
||||||
|
- "!.github/scripts/upload_*"
|
||||||
|
- "variants/esp32/**/*"
|
||||||
|
- "variants/esp32c3/**/*"
|
||||||
|
- "variants/esp32c5/**/*"
|
||||||
|
- "variants/esp32c6/**/*"
|
||||||
|
- "variants/esp32h2/**/*"
|
||||||
|
- "variants/esp32p4/**/*"
|
||||||
|
- "variants/esp32s2/**/*"
|
||||||
|
- "variants/esp32s3/**/*"
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: build-${{github.event.pull_request.number || github.ref}}
|
group: build-${{github.event.pull_request.number || github.ref}}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
env:
|
||||||
|
MAX_CHUNKS: 15
|
||||||
|
|
||||||
|
jobs:
|
||||||
cmake-check:
|
cmake-check:
|
||||||
name: Check cmake file
|
name: Check cmake file
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: bash ./.github/scripts/check-cmakelists.sh
|
- run: bash ./.github/scripts/check-cmakelists.sh
|
||||||
|
|
||||||
|
gen-chunks:
|
||||||
|
name: Generate chunks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) }}
|
||||||
|
outputs:
|
||||||
|
build_all: ${{ steps.set-chunks.outputs.build_all }}
|
||||||
|
build_libraries: ${{ steps.set-chunks.outputs.build_libraries }}
|
||||||
|
build_static_sketches: ${{ steps.set-chunks.outputs.build_static_sketches }}
|
||||||
|
build_idf: ${{ steps.set-chunks.outputs.build_idf }}
|
||||||
|
chunk_count: ${{ steps.set-chunks.outputs.chunk_count }}
|
||||||
|
chunks: ${{ steps.set-chunks.outputs.chunks }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- name: Get changed files
|
||||||
|
id: changed-files
|
||||||
|
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
|
||||||
|
with:
|
||||||
|
files_yaml: |
|
||||||
|
core:
|
||||||
|
- '.github/**'
|
||||||
|
- 'cores/**'
|
||||||
|
- 'package/**'
|
||||||
|
- 'tools/**'
|
||||||
|
- 'platform.txt'
|
||||||
|
- 'programmers.txt'
|
||||||
|
- "variants/esp32/**/*"
|
||||||
|
- "variants/esp32c3/**/*"
|
||||||
|
- "variants/esp32c6/**/*"
|
||||||
|
- "variants/esp32h2/**/*"
|
||||||
|
- "variants/esp32p4/**/*"
|
||||||
|
- "variants/esp32s2/**/*"
|
||||||
|
- "variants/esp32s3/**/*"
|
||||||
|
libraries:
|
||||||
|
- 'libraries/**/examples/**'
|
||||||
|
- 'libraries/**/src/**'
|
||||||
|
networking:
|
||||||
|
- 'libraries/Network/src/**'
|
||||||
|
fs:
|
||||||
|
- 'libraries/FS/src/**'
|
||||||
|
static_sketeches:
|
||||||
|
- 'libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino'
|
||||||
|
- 'libraries/BLE/examples/Server/Server.ino'
|
||||||
|
- 'libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino'
|
||||||
|
- 'libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino'
|
||||||
|
- 'libraries/NetworkClientSecure/src/**'
|
||||||
|
- 'libraries/BLE/src/**'
|
||||||
|
- 'libraries/Insights/src/**'
|
||||||
|
idf:
|
||||||
|
- 'idf_component.yml'
|
||||||
|
- 'Kconfig.projbuild'
|
||||||
|
- 'CMakeLists.txt'
|
||||||
|
- "idf_component_examples/**"
|
||||||
|
|
||||||
|
- name: Set chunks
|
||||||
|
id: set-chunks
|
||||||
|
env:
|
||||||
|
LIB_FILES: ${{ steps.changed-files.outputs.libraries_all_changed_files }}
|
||||||
|
IS_PR: ${{ github.event_name == 'pull_request' }}
|
||||||
|
MAX_CHUNKS: ${{ env.MAX_CHUNKS }}
|
||||||
|
BUILD_IDF: ${{ steps.changed-files.outputs.idf_any_changed == 'true' }}
|
||||||
|
BUILD_LIBRARIES: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }}
|
||||||
|
BUILD_STATIC_SKETCHES: ${{ steps.changed-files.outputs.static_sketeches_any_changed == 'true' }}
|
||||||
|
FS_CHANGED: ${{ steps.changed-files.outputs.fs_any_changed == 'true' }}
|
||||||
|
NETWORKING_CHANGED: ${{ steps.changed-files.outputs.networking_any_changed == 'true' }}
|
||||||
|
CORE_CHANGED: ${{ steps.changed-files.outputs.core_any_changed == 'true' }}
|
||||||
|
LIB_CHANGED: ${{ steps.changed-files.outputs.libraries_any_changed == 'true' }}
|
||||||
|
run: |
|
||||||
|
bash ./.github/scripts/set_push_chunks.sh
|
||||||
|
|
||||||
|
- name: Upload sketches found
|
||||||
|
if: ${{ steps.set-chunks.outputs.build_all == 'false' && steps.set-chunks.outputs.build_libraries == 'true' }}
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: sketches_found
|
||||||
|
path: sketches_found.txt
|
||||||
|
overwrite: true
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
# Ubuntu
|
# Ubuntu
|
||||||
build-arduino-linux:
|
build-arduino-linux:
|
||||||
name: Arduino ${{ matrix.chunk }} on ubuntu-latest
|
name: Arduino ${{ matrix.chunk }} on ubuntu-latest
|
||||||
|
if: ${{ needs.gen-chunks.outputs.build_all == 'true' || needs.gen-chunks.outputs.build_libraries == 'true' }}
|
||||||
|
needs: gen-chunks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
chunk: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
chunk: ${{ fromJson(needs.gen-chunks.outputs.chunks) }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: "3.x"
|
||||||
- name: Cache tools
|
|
||||||
id: cache-linux
|
- name: Get libs cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
with:
|
with:
|
||||||
path: |
|
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
|
||||||
./tools/dist
|
path: |
|
||||||
~/arduino_ide
|
./tools/dist
|
||||||
key: ${{ runner.os }}-${{ hashFiles('package/package_esp32_index.template.json',
|
./tools/esp32-arduino-libs
|
||||||
'tools/get.py',
|
./tools/esptool
|
||||||
'.github/scripts/install-arduino-ide.sh') }}
|
./tools/mk*
|
||||||
- name: Build Sketches
|
./tools/openocd-esp32
|
||||||
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} 15
|
./tools/riscv32-*
|
||||||
|
./tools/xtensa-*
|
||||||
|
|
||||||
|
- name: Set Log Level
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||||
|
echo "LOG_LEVEL=${{ github.event.inputs.log_level }}" >> $GITHUB_ENV
|
||||||
|
elif [ "${{ github.event_name }}" == "schedule" ]; then
|
||||||
|
echo "LOG_LEVEL=verbose" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "LOG_LEVEL=none" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build all sketches
|
||||||
|
if: ${{ needs.gen-chunks.outputs.build_all == 'true' }}
|
||||||
|
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 ${{ env.LOG_LEVEL }}
|
||||||
|
|
||||||
|
- name: Download sketches found
|
||||||
|
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
name: sketches_found
|
||||||
|
|
||||||
|
- name: Build selected sketches
|
||||||
|
if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }}
|
||||||
|
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 ${{ env.LOG_LEVEL }} sketches_found.txt
|
||||||
|
|
||||||
|
#Upload cli compile json as artifact
|
||||||
|
- name: Upload cli compile json
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: pr_cli_compile_${{ matrix.chunk }}
|
||||||
|
path: cli_compile_${{ matrix.chunk }}.json
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
# Windows and MacOS
|
# Windows and MacOS
|
||||||
build-arduino-win-mac:
|
build-arduino-win-mac:
|
||||||
name: Arduino on ${{ matrix.os }}
|
name: Arduino on ${{ matrix.os }}
|
||||||
|
needs: gen-chunks
|
||||||
|
if: ${{ needs.gen-chunks.outputs.build_all == 'true' || needs.gen-chunks.outputs.build_static_sketches == 'true' }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
@ -58,33 +226,21 @@ jobs:
|
||||||
os: [windows-latest, macOS-latest]
|
os: [windows-latest, macOS-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: "3.x"
|
||||||
- name: Build Sketches
|
- name: Build Sketches
|
||||||
run: bash ./.github/scripts/on-push.sh
|
run: bash ./.github/scripts/on-push.sh
|
||||||
|
|
||||||
# PlatformIO on Windows, Ubuntu and Mac
|
|
||||||
build-platformio:
|
|
||||||
name: PlatformIO on ${{ matrix.os }}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
|
||||||
- name: Build Sketches
|
|
||||||
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO
|
|
||||||
|
|
||||||
build-esp-idf-component:
|
build-esp-idf-component:
|
||||||
name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||||
runs-on: ubuntu-20.04
|
needs: gen-chunks
|
||||||
|
if: |
|
||||||
|
needs.gen-chunks.outputs.build_all == 'true' ||
|
||||||
|
needs.gen-chunks.outputs.build_libraries == 'true' ||
|
||||||
|
needs.gen-chunks.outputs.build_idf == 'true'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -92,21 +248,96 @@ jobs:
|
||||||
# See https://hub.docker.com/r/espressif/idf/tags and
|
# See https://hub.docker.com/r/espressif/idf/tags and
|
||||||
# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html
|
# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-docker-image.html
|
||||||
# for details.
|
# for details.
|
||||||
idf_ver: ["release-v5.1"]
|
idf_ver: ["release-v5.3","release-v5.4","release-v5.5"]
|
||||||
idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"]
|
idf_target:
|
||||||
|
[
|
||||||
|
"esp32",
|
||||||
|
"esp32s2",
|
||||||
|
"esp32s3",
|
||||||
|
"esp32c2",
|
||||||
|
"esp32c3",
|
||||||
|
"esp32c6",
|
||||||
|
"esp32h2",
|
||||||
|
"esp32p4"
|
||||||
|
]
|
||||||
container: espressif/idf:${{ matrix.idf_ver }}
|
container: espressif/idf:${{ matrix.idf_ver }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out arduino-esp32 as a component
|
- name: Check out arduino-esp32 as a component
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
path: components/arduino-esp32
|
path: components/arduino-esp32
|
||||||
|
|
||||||
|
- name: Setup jq
|
||||||
|
uses: dcarbone/install-jq-action@e397bd87438d72198f81efd21f876461183d383a # v3.0.1
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
IDF_TARGET: ${{ matrix.idf_target }}
|
IDF_TARGET: ${{ matrix.idf_target }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
. ${IDF_PATH}/export.sh
|
chmod a+x ./components/arduino-esp32/.github/scripts/*
|
||||||
idf.py create-project test
|
./components/arduino-esp32/.github/scripts/on-push-idf.sh
|
||||||
echo CONFIG_FREERTOS_HZ=1000 > test/sdkconfig.defaults
|
|
||||||
idf.py -C test -DEXTRA_COMPONENT_DIRS=$PWD/components build
|
- name: Upload generated sdkconfig files for debugging
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: sdkconfig-${{ matrix.idf_ver }}-${{ matrix.idf_target }}
|
||||||
|
path: ./components/arduino-esp32/idf_component_examples/**/sdkconfig
|
||||||
|
|
||||||
|
# Save artifacts to gh-pages
|
||||||
|
save-master-artifacts:
|
||||||
|
name: Save master artifacts
|
||||||
|
needs: build-arduino-linux
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Check out repository
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
fetch-depth: "0"
|
||||||
|
|
||||||
|
- name: Switch branch
|
||||||
|
run: git checkout remotes/origin/gh-pages
|
||||||
|
|
||||||
|
- name: Download sketches reports artifact
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
pattern: pr_cli_compile_*
|
||||||
|
merge-multiple: true
|
||||||
|
path: master_cli_compile
|
||||||
|
|
||||||
|
- name: List files in the directory
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: Commit json files to gh-pages if on master
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add --all
|
||||||
|
git commit -m "Updated cli compile json files"
|
||||||
|
git push origin HEAD:gh-pages
|
||||||
|
|
||||||
|
#Upload PR number as artifact
|
||||||
|
upload-pr-number:
|
||||||
|
name: Upload PR number
|
||||||
|
if: ${{ github.event_name == 'pull_request' && !startsWith(github.head_ref, 'release/') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Save the PR number in an artifact
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
PR_NUM: ${{ github.event.number }}
|
||||||
|
run: echo $PR_NUM > pr_num.txt
|
||||||
|
|
||||||
|
- name: Upload PR number
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: pr_number
|
||||||
|
path: ./pr_num.txt
|
||||||
|
overwrite: true
|
||||||
|
|
|
||||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
|
|
@ -10,13 +10,23 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout repository
|
||||||
with:
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
fetch-depth: 0
|
with:
|
||||||
- uses: actions/setup-python@v5
|
fetch-depth: 0
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
- name: Set up Python
|
||||||
- name: Build Release
|
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
env:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
python-version: "3.x"
|
||||||
run: bash ./.github/scripts/on-release.sh
|
|
||||||
|
- name: Install packaging
|
||||||
|
run: pip install packaging
|
||||||
|
|
||||||
|
- name: Install pyserial
|
||||||
|
run: pip install pyserial
|
||||||
|
|
||||||
|
- name: Build Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: bash ./.github/scripts/on-release.sh
|
||||||
|
|
|
||||||
123
.github/workflows/tests.yml
vendored
Normal file
123
.github/workflows/tests.yml
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
# This file is used to run the runtime tests for the Arduino core for ESP32.
|
||||||
|
# The tests are run on the hardware, Wokwi and QEMU emulators.
|
||||||
|
# The QEMU tests are disabled for now as they are redundant with most of the Wokwi tests.
|
||||||
|
# As the Wokwi tests require access to secrets, they are run in a separate workflow.
|
||||||
|
# We need to ensure that the artifacts from previous tests in the chain are propagated for publishing the results.
|
||||||
|
# This is the current trigger sequence for the tests:
|
||||||
|
# tests.yml -> tests_wokwi.yml -> tests_results.yml
|
||||||
|
# ⌙> tests_build.yml
|
||||||
|
# ⌙> tests_hw.yml
|
||||||
|
# ⌙> tests_qemu.yml
|
||||||
|
|
||||||
|
name: Runtime Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, reopened, closed, synchronize, labeled, unlabeled]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/tests*"
|
||||||
|
- ".github/scripts/*.sh"
|
||||||
|
- "!.github/scripts/check-cmakelists.sh"
|
||||||
|
- "!.github/scripts/find_*"
|
||||||
|
- "!.github/scripts/on-*.sh"
|
||||||
|
- "!.github/scripts/set_push_chunks.sh"
|
||||||
|
- "!.github/scripts/update-version.sh"
|
||||||
|
- "!.github/scripts/upload_py_tools.sh"
|
||||||
|
- "tests/**"
|
||||||
|
- "cores/**"
|
||||||
|
- "libraries/*/src/**.cpp"
|
||||||
|
- "libraries/*/src/**.h"
|
||||||
|
- "libraries/*/src/**.c"
|
||||||
|
- "package/**"
|
||||||
|
schedule:
|
||||||
|
- cron: "0 2 * * *"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: tests-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push-event-file:
|
||||||
|
name: Push event file
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: event_file
|
||||||
|
path: ${{ github.event_path }}
|
||||||
|
|
||||||
|
gen-matrix:
|
||||||
|
name: Generate matrix
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
build-types: ${{ steps.set-matrix.outputs.build-types }}
|
||||||
|
hw-types: ${{ steps.set-matrix.outputs.hw-types }}
|
||||||
|
wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }}
|
||||||
|
qemu-types: ${{ steps.set-matrix.outputs.qemu-types }}
|
||||||
|
targets: ${{ steps.set-matrix.outputs.targets }}
|
||||||
|
env:
|
||||||
|
IS_PR: ${{ github.event.pull_request.number != null }}
|
||||||
|
PERFORMANCE_ENABLED: ${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
sparse-checkout: .github/scripts/tests_matrix.sh
|
||||||
|
|
||||||
|
- name: Set matrix
|
||||||
|
id: set-matrix
|
||||||
|
run: bash .github/scripts/tests_matrix.sh
|
||||||
|
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: matrix_info
|
||||||
|
path: info/*
|
||||||
|
|
||||||
|
call-build-tests:
|
||||||
|
name: Build
|
||||||
|
uses: ./.github/workflows/tests_build.yml
|
||||||
|
needs: gen-matrix
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }}
|
||||||
|
chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }}
|
||||||
|
with:
|
||||||
|
type: ${{ matrix.type }}
|
||||||
|
chip: ${{ matrix.chip }}
|
||||||
|
|
||||||
|
call-hardware-tests:
|
||||||
|
name: Hardware
|
||||||
|
uses: ./.github/workflows/tests_hw.yml
|
||||||
|
needs: [gen-matrix, call-build-tests]
|
||||||
|
if: |
|
||||||
|
github.repository == 'espressif/arduino-esp32' &&
|
||||||
|
(github.event_name != 'pull_request' ||
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'hil_test'))
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
type: ${{ fromJson(needs.gen-matrix.outputs.hw-types) }}
|
||||||
|
chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }}
|
||||||
|
with:
|
||||||
|
type: ${{ matrix.type }}
|
||||||
|
chip: ${{ matrix.chip }}
|
||||||
|
|
||||||
|
# This job is disabled for now
|
||||||
|
call-qemu-tests:
|
||||||
|
name: QEMU
|
||||||
|
uses: ./.github/workflows/tests_qemu.yml
|
||||||
|
needs: [gen-matrix, call-build-tests]
|
||||||
|
if: false
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
type: ${{ fromJson(needs.gen-matrix.outputs.qemu-types) }}
|
||||||
|
chip: ["esp32", "esp32c3"]
|
||||||
|
with:
|
||||||
|
type: ${{ matrix.type }}
|
||||||
|
chip: ${{ matrix.chip }}
|
||||||
|
|
||||||
|
# Wokwi tests are run after this workflow as it needs access to secrets
|
||||||
90
.github/workflows/tests_build.yml
vendored
Normal file
90
.github/workflows/tests_build.yml
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
name: Build tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: "Type of tests to build"
|
||||||
|
required: true
|
||||||
|
chip:
|
||||||
|
type: string
|
||||||
|
description: "Chip to build tests for"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-tests:
|
||||||
|
name: Build ${{ inputs.type }} tests for ${{ inputs.chip }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
steps:
|
||||||
|
- name: Check if already built
|
||||||
|
id: cache-build-binaries
|
||||||
|
if: github.event.pull_request.number != null
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-bin
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
|
||||||
|
|
||||||
|
- name: Evaluate if tests should be built
|
||||||
|
id: check-build
|
||||||
|
run: |
|
||||||
|
cache_exists=${{ steps.cache-build-binaries.outputs.cache-hit == 'true' }}
|
||||||
|
enabled=true
|
||||||
|
|
||||||
|
if [[ $cache_exists == 'true' ]]; then
|
||||||
|
echo "Already built, skipping"
|
||||||
|
enabled=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "enabled=$enabled" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Checkout user repository
|
||||||
|
if: ${{ steps.check-build.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Get libs cache
|
||||||
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: ${{ steps.check-build.outputs.enabled == 'true' }}
|
||||||
|
with:
|
||||||
|
key: libs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package/package_esp32_index.template.json', 'tools/get.py') }}
|
||||||
|
path: |
|
||||||
|
./tools/dist
|
||||||
|
./tools/esp32-arduino-libs
|
||||||
|
./tools/esptool
|
||||||
|
./tools/mk*
|
||||||
|
./tools/openocd-esp32
|
||||||
|
./tools/riscv32-*
|
||||||
|
./tools/xtensa-*
|
||||||
|
|
||||||
|
- name: Build sketches
|
||||||
|
if: ${{ steps.check-build.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/tests_build.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }}
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as cache
|
||||||
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: steps.check-build.outputs.enabled == 'true' && github.event.pull_request.number != null
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-bin
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.bin
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.elf
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/*.json
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}/**/build*.tmp/sdkconfig
|
||||||
118
.github/workflows/tests_hw.yml
vendored
Normal file
118
.github/workflows/tests_hw.yml
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
name: Hardware tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: "Type of tests to run"
|
||||||
|
required: true
|
||||||
|
chip:
|
||||||
|
type: string
|
||||||
|
description: "Chip to run tests for"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
hardware-test:
|
||||||
|
name: Hardware ${{ inputs.chip }} ${{ inputs.type }} tests
|
||||||
|
runs-on: ["arduino", "${{ inputs.chip }}"]
|
||||||
|
env:
|
||||||
|
id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
container:
|
||||||
|
image: python:3.10.1-bullseye
|
||||||
|
options: --privileged --device-cgroup-rule="c 188:* rmw" --device-cgroup-rule="c 166:* rmw"
|
||||||
|
steps:
|
||||||
|
- name: Clean workspace
|
||||||
|
run: |
|
||||||
|
rm -rf ./*
|
||||||
|
rm -rf ~/.arduino/tests
|
||||||
|
|
||||||
|
- name: Check if already passed
|
||||||
|
id: cache-results
|
||||||
|
if: github.event.pull_request.number != null
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-hw
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Evaluate if tests should be run
|
||||||
|
id: check-tests
|
||||||
|
run: |
|
||||||
|
cache_exists=${{ steps.cache-results.outputs.cache-hit == 'true' }}
|
||||||
|
enabled=true
|
||||||
|
|
||||||
|
if [[ $cache_exists == 'true' ]]; then
|
||||||
|
echo "Already ran, skipping"
|
||||||
|
enabled=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "enabled=$enabled" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Checkout user repository
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
sparse-checkout: |
|
||||||
|
*
|
||||||
|
|
||||||
|
# setup-python currently only works on ubuntu images
|
||||||
|
# - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
|
# if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
# with:
|
||||||
|
# cache-dependency-path: tests/requirements.txt
|
||||||
|
# cache: 'pip'
|
||||||
|
# python-version: '3.10.1'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
pip install -U pip
|
||||||
|
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
|
||||||
|
apt update
|
||||||
|
apt install -y jq
|
||||||
|
|
||||||
|
- name: Get binaries
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}
|
||||||
|
|
||||||
|
- name: List binaries
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
ls -laR ~/.arduino/tests
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/tests_run.sh -c -type ${{ inputs.type }} -t ${{ inputs.chip }} -i 0 -m 1 -e
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as cache
|
||||||
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-hw
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: tests-results-hw-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
143
.github/workflows/tests_qemu.yml
vendored
Normal file
143
.github/workflows/tests_qemu.yml
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
name: QEMU tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
chip:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
qemu-test:
|
||||||
|
name: QEMU ${{ inputs.chip }} ${{ inputs.type }} tests
|
||||||
|
env:
|
||||||
|
id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
QEMU_INSTALL_PATH: "$HOME"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if already passed
|
||||||
|
id: get-cache-results
|
||||||
|
if: github.event.pull_request.number != null
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-qemu
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Evaluate if tests should be run
|
||||||
|
id: check-tests
|
||||||
|
run: |
|
||||||
|
cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }}
|
||||||
|
enabled=true
|
||||||
|
|
||||||
|
if [[ $cache_exists == 'true' ]]; then
|
||||||
|
echo "Already ran, skipping"
|
||||||
|
enabled=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "enabled=$enabled" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Checkout user repository
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
persist-credentials: false
|
||||||
|
sparse-checkout-cone-mode: false
|
||||||
|
sparse-checkout: |
|
||||||
|
/*
|
||||||
|
!.github
|
||||||
|
|
||||||
|
# To avoid giving unknown scripts elevated permissions, download them from the master branch
|
||||||
|
- name: Get CI scripts from master
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
mkdir -p .github
|
||||||
|
cd .github
|
||||||
|
curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github
|
||||||
|
|
||||||
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
with:
|
||||||
|
cache-dependency-path: tests/requirements.txt
|
||||||
|
cache: "pip"
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
pip install -U pip
|
||||||
|
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
|
||||||
|
|
||||||
|
- name: Install APT dependencies
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@5902b33ae29014e6ca012c5d8025d4346556bd40 # v1.4.3
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
with:
|
||||||
|
packages: libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
- name: Get QEMU version
|
||||||
|
uses: pozetroninc/github-action-get-latest-release@2a61c339ea7ef0a336d1daa35ef0cb1418e7676c # v0.8.0
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
id: get-qemu-version
|
||||||
|
with:
|
||||||
|
token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
owner: espressif
|
||||||
|
repo: qemu
|
||||||
|
excludes: prerelease, draft
|
||||||
|
|
||||||
|
- name: Cache QEMU
|
||||||
|
id: cache-qemu
|
||||||
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/qemu
|
||||||
|
key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/tests_qemu.yml') }}
|
||||||
|
|
||||||
|
- name: Download QEMU
|
||||||
|
if: ${{ steps.cache-qemu.outputs.cache-hit != 'true' && steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
cd ${{ env.QEMU_INSTALL_PATH }}
|
||||||
|
underscore_release=$(echo ${{ steps.get-qemu-version.outputs.release }} | sed 's/\-/_/g')
|
||||||
|
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-riscv32-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-riscv32.tar.xz
|
||||||
|
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-xtensa-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-xtensa.tar.xz
|
||||||
|
tar -xf qemu-riscv32.tar.xz
|
||||||
|
tar -xf qemu-xtensa.tar.xz
|
||||||
|
rm qemu-*
|
||||||
|
echo "QEMU_PATH=${{ env.QEMU_INSTALL_PATH }}/qemu" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Get binaries
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
name: tests-bin-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ inputs.chip }}
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: QEMU_PATH="${{ env.QEMU_INSTALL_PATH }}" bash .github/scripts/tests_run.sh -c -type ${{inputs.type}} -t ${{inputs.chip}} -i 0 -m 1 -Q
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as cache
|
||||||
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-qemu
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: tests-results-qemu-${{ inputs.chip }}-${{ inputs.type }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
195
.github/workflows/tests_results.yml
vendored
Normal file
195
.github/workflows/tests_results.yml
vendored
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
name: Publish and clean test results
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Wokwi tests"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
# No permissions by default
|
||||||
|
permissions: { contents: read }
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-test-results:
|
||||||
|
name: Unit Test Results
|
||||||
|
if: |
|
||||||
|
github.event.workflow_run.conclusion == 'success' ||
|
||||||
|
github.event.workflow_run.conclusion == 'failure' ||
|
||||||
|
github.event.workflow_run.conclusion == 'timed_out'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
statuses: write
|
||||||
|
checks: write
|
||||||
|
pull-requests: write
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
ref: gh-pages
|
||||||
|
|
||||||
|
- name: Download and Extract Artifacts
|
||||||
|
uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9
|
||||||
|
with:
|
||||||
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
|
path: ./artifacts
|
||||||
|
|
||||||
|
- name: Get original info
|
||||||
|
run: |
|
||||||
|
original_event=$(cat ./artifacts/parent-artifacts/event.txt)
|
||||||
|
original_action=$(cat ./artifacts/parent-artifacts/action.txt)
|
||||||
|
original_sha=$(cat ./artifacts/parent-artifacts/sha.txt)
|
||||||
|
original_ref=$(cat ./artifacts/parent-artifacts/ref.txt)
|
||||||
|
original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt)
|
||||||
|
original_run_id=$(cat ./artifacts/parent-artifacts/run_id.txt)
|
||||||
|
|
||||||
|
# Sanitize the values to avoid security issues
|
||||||
|
|
||||||
|
# Event: Allow alphabetical characters and underscores
|
||||||
|
original_event=$(echo "$original_event" | tr -cd '[:alpha:]_')
|
||||||
|
|
||||||
|
# Action: Allow alphabetical characters and underscores
|
||||||
|
original_action=$(echo "$original_action" | tr -cd '[:alpha:]_')
|
||||||
|
|
||||||
|
# SHA: Allow alphanumeric characters
|
||||||
|
original_sha=$(echo "$original_sha" | tr -cd '[:alnum:]')
|
||||||
|
|
||||||
|
# Ref: Allow alphanumeric characters, slashes, underscores, dots, and dashes
|
||||||
|
original_ref=$(echo "$original_ref" | tr -cd '[:alnum:]/_.-')
|
||||||
|
|
||||||
|
# Conclusion: Allow alphabetical characters and underscores
|
||||||
|
original_conclusion=$(echo "$original_conclusion" | tr -cd '[:alpha:]_')
|
||||||
|
|
||||||
|
# Run ID: Allow numeric characters
|
||||||
|
original_run_id=$(echo "$original_run_id" | tr -cd '[:digit:]')
|
||||||
|
|
||||||
|
echo "original_event=$original_event" >> $GITHUB_ENV
|
||||||
|
echo "original_action=$original_action" >> $GITHUB_ENV
|
||||||
|
echo "original_sha=$original_sha" >> $GITHUB_ENV
|
||||||
|
echo "original_ref=$original_ref" >> $GITHUB_ENV
|
||||||
|
echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV
|
||||||
|
echo "original_run_id=$original_run_id" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "original_event = $original_event"
|
||||||
|
echo "original_action = $original_action"
|
||||||
|
echo "original_sha = $original_sha"
|
||||||
|
echo "original_ref = $original_ref"
|
||||||
|
echo "original_conclusion = $original_conclusion"
|
||||||
|
echo "original_run_id = $original_run_id"
|
||||||
|
|
||||||
|
- name: Print links to other runs
|
||||||
|
run: |
|
||||||
|
echo "Build, Hardware and QEMU tests: https://github.com/${{ github.repository }}/actions/runs/${{ env.original_run_id }}"
|
||||||
|
echo "Wokwi tests: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}"
|
||||||
|
|
||||||
|
- name: Publish Unit Test Results
|
||||||
|
uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b # v2.18.0
|
||||||
|
with:
|
||||||
|
commit: ${{ env.original_sha }}
|
||||||
|
event_file: ./artifacts/parent-artifacts/event_file/event.json
|
||||||
|
event_name: ${{ env.original_event }}
|
||||||
|
files: ./artifacts/**/*.xml
|
||||||
|
action_fail: true
|
||||||
|
compare_to_earlier_commit: false
|
||||||
|
json_file: ./unity_results.json
|
||||||
|
json_suite_details: true
|
||||||
|
|
||||||
|
- name: Upload JSON
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
if: ${{ always() }}
|
||||||
|
with:
|
||||||
|
name: unity_results
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./unity_results.json
|
||||||
|
|
||||||
|
- name: Fail if tests failed
|
||||||
|
if: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' }}
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
|
- name: Clean up caches
|
||||||
|
if: always()
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const ref = process.env.original_ref;
|
||||||
|
const key_prefix = 'tests-' + ref + '-';
|
||||||
|
|
||||||
|
if (process.env.original_event == 'pull_request' && process.env.original_action != 'closed') {
|
||||||
|
console.log('Skipping cache cleanup for open PR');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await github.paginate(github.rest.actions.getActionsCacheList, {
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
per_page: 100,
|
||||||
|
key: key_prefix
|
||||||
|
}).then(caches => {
|
||||||
|
if (caches) {
|
||||||
|
for (const cache of caches) {
|
||||||
|
console.log(`Deleting cache: ${cache.key}`);
|
||||||
|
github.rest.actions.deleteActionsCacheById({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
cache_id: cache.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
- name: Report conclusion
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = process.env.original_sha;
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: `Runtime Tests / Report results (${process.env.original_event} -> workflow_run -> workflow_run)`,
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: '${{ job.status }}',
|
||||||
|
description: '${{ job.status }}' == 'success' ? 'Runtime tests successful' : 'Runtime tests failed',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
|
|
||||||
|
- name: Generate report
|
||||||
|
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled
|
||||||
|
env:
|
||||||
|
REPORT_FILE: ./runtime-tests-results/RUNTIME_TESTS_REPORT.md
|
||||||
|
WOKWI_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||||
|
BUILD_RUN_ID: ${{ env.original_run_id }}
|
||||||
|
IS_FAILING: ${{ env.original_conclusion == 'failure' || env.original_conclusion == 'timed_out' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' || job.status == 'failure' }}
|
||||||
|
run: |
|
||||||
|
rm -rf artifacts $REPORT_FILE
|
||||||
|
mv -f ./unity_results.json ./runtime-tests-results/unity_results.json
|
||||||
|
touch $REPORT_FILE
|
||||||
|
python3 ./runtime-tests-results/table_generator.py ./runtime-tests-results/unity_results.json >> $REPORT_FILE
|
||||||
|
|
||||||
|
- name: Generate badge
|
||||||
|
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled
|
||||||
|
uses: jaywcjlove/generated-badges@0e078ae4d4bab3777ea4f137de496ab44688f5ad # v1.0.13
|
||||||
|
with:
|
||||||
|
label: Runtime Tests
|
||||||
|
status: ${{ job.status == 'success' && 'passing' || 'failing' }}
|
||||||
|
output: runtime-tests-results/badge.svg
|
||||||
|
color: ${{ job.status == 'success' && 'green' || 'red' }}
|
||||||
|
style: flat
|
||||||
|
|
||||||
|
- name: Push badge
|
||||||
|
if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
if [[ `git status --porcelain` ]]; then
|
||||||
|
git add --all
|
||||||
|
git commit -m "Updated runtime tests report"
|
||||||
|
git push origin HEAD:gh-pages
|
||||||
|
fi
|
||||||
326
.github/workflows/tests_wokwi.yml
vendored
Normal file
326
.github/workflows/tests_wokwi.yml
vendored
Normal file
|
|
@ -0,0 +1,326 @@
|
||||||
|
name: Wokwi tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Runtime Tests"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
# No permissions by default
|
||||||
|
permissions: { contents: read }
|
||||||
|
|
||||||
|
env:
|
||||||
|
WOKWI_TIMEOUT: 600000 # Milliseconds
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
get-artifacts:
|
||||||
|
name: Get required artifacts
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
statuses: write
|
||||||
|
outputs:
|
||||||
|
pr_num: ${{ steps.set-ref.outputs.pr_num }}
|
||||||
|
ref: ${{ steps.set-ref.outputs.ref }}
|
||||||
|
base: ${{ steps.set-ref.outputs.base }}
|
||||||
|
targets: ${{ steps.set-ref.outputs.targets }}
|
||||||
|
types: ${{ steps.set-ref.outputs.types }}
|
||||||
|
steps:
|
||||||
|
- name: Report pending
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: 'pending',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
|
|
||||||
|
- name: Download and extract event file
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
name: event_file
|
||||||
|
path: artifacts/event_file
|
||||||
|
|
||||||
|
- name: Download and extract matrix info
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
name: matrix_info
|
||||||
|
path: artifacts/matrix_info
|
||||||
|
|
||||||
|
- name: Try to read PR number
|
||||||
|
id: set-ref
|
||||||
|
run: |
|
||||||
|
pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]")
|
||||||
|
if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then
|
||||||
|
pr_num=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
ref=$pr_num
|
||||||
|
if [ -z "$ref" ] || [ "$ref" == "null" ]; then
|
||||||
|
ref=${{ github.ref }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
action=$(jq -r '.action' artifacts/event_file/event.json | tr -cd "[:alpha:]_")
|
||||||
|
if [ "$action" == "null" ]; then
|
||||||
|
action=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
base=$(jq -r '.pull_request.base.ref' artifacts/event_file/event.json | tr -cd "[:alnum:]/_.-")
|
||||||
|
if [ -z "$base" ] || [ "$base" == "null" ]; then
|
||||||
|
base=${{ github.ref }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'")
|
||||||
|
targets=$(cat artifacts/matrix_info/targets.txt | tr -cd "[:alnum:],[]'")
|
||||||
|
|
||||||
|
echo "base = $base"
|
||||||
|
echo "targets = $targets"
|
||||||
|
echo "types = $types"
|
||||||
|
echo "pr_num = $pr_num"
|
||||||
|
|
||||||
|
printf "$ref" >> artifacts/ref.txt
|
||||||
|
printf "Ref = "
|
||||||
|
cat artifacts/ref.txt
|
||||||
|
|
||||||
|
printf "${{ github.event.workflow_run.event }}" >> artifacts/event.txt
|
||||||
|
printf "\nEvent name = "
|
||||||
|
cat artifacts/event.txt
|
||||||
|
|
||||||
|
printf "${{ github.event.workflow_run.head_sha || github.sha }}" >> artifacts/sha.txt
|
||||||
|
printf "\nHead SHA = "
|
||||||
|
cat artifacts/sha.txt
|
||||||
|
|
||||||
|
printf "$action" >> artifacts/action.txt
|
||||||
|
printf "\nAction = "
|
||||||
|
cat artifacts/action.txt
|
||||||
|
|
||||||
|
printf "${{ github.event.workflow_run.id }}" >> artifacts/run_id.txt
|
||||||
|
printf "\nRun ID = "
|
||||||
|
cat artifacts/run_id.txt
|
||||||
|
|
||||||
|
if [ -z "$ref" ] || [ "$ref" == "null" ]; then
|
||||||
|
echo "Failed to get PR number or ref"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
conclusion="${{ github.event.workflow_run.conclusion }}"
|
||||||
|
printf "$conclusion" >> artifacts/conclusion.txt
|
||||||
|
printf "\nConclusion = "
|
||||||
|
cat artifacts/conclusion.txt
|
||||||
|
|
||||||
|
echo "pr_num=$pr_num" >> $GITHUB_OUTPUT
|
||||||
|
echo "base=$base" >> $GITHUB_OUTPUT
|
||||||
|
echo "targets=$targets" >> $GITHUB_OUTPUT
|
||||||
|
echo "types=$types" >> $GITHUB_OUTPUT
|
||||||
|
echo "ref=$ref" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Download and extract parent hardware results
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
pattern: tests-results-hw-*
|
||||||
|
merge-multiple: true
|
||||||
|
path: artifacts/results/hw
|
||||||
|
|
||||||
|
- name: Download and extract parent QEMU results
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
pattern: tests-results-qemu-*
|
||||||
|
merge-multiple: true
|
||||||
|
path: artifacts/results/qemu
|
||||||
|
|
||||||
|
- name: Upload parent artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: parent-artifacts
|
||||||
|
path: artifacts
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Report conclusion
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: '${{ job.status }}',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
|
|
||||||
|
wokwi-test:
|
||||||
|
name: Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests
|
||||||
|
if: |
|
||||||
|
github.event.workflow_run.conclusion == 'success' ||
|
||||||
|
github.event.workflow_run.conclusion == 'failure' ||
|
||||||
|
github.event.workflow_run.conclusion == 'timed_out'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: get-artifacts
|
||||||
|
env:
|
||||||
|
id: ${{ needs.get-artifacts.outputs.ref }}-${{ github.event.workflow_run.head_sha || github.sha }}-${{ matrix.chip }}-${{ matrix.type }}
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
statuses: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
type: ${{ fromJson(needs.get-artifacts.outputs.types) }}
|
||||||
|
chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }}
|
||||||
|
steps:
|
||||||
|
- name: Report pending
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: 'pending',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
|
|
||||||
|
- name: Check if already passed
|
||||||
|
id: get-cache-results
|
||||||
|
if: needs.get-artifacts.outputs.pr_num
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-wokwi
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Evaluate if tests should be run
|
||||||
|
id: check-tests
|
||||||
|
run: |
|
||||||
|
cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }}
|
||||||
|
enabled=true
|
||||||
|
|
||||||
|
if [[ $cache_exists == 'true' ]]; then
|
||||||
|
echo "Already ran, skipping"
|
||||||
|
enabled=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "enabled=$enabled" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Note that changes to the workflows and tests will only be picked up after the PR is merged
|
||||||
|
# DO NOT CHECKOUT THE USER'S REPOSITORY IN THIS WORKFLOW. IT HAS HIGH SECURITY RISKS.
|
||||||
|
- name: Checkout repository
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.get-artifacts.outputs.base || github.ref }}
|
||||||
|
|
||||||
|
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
with:
|
||||||
|
cache-dependency-path: tests/requirements.txt
|
||||||
|
cache: "pip"
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: |
|
||||||
|
pip install -U pip
|
||||||
|
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
|
||||||
|
|
||||||
|
- name: Install Wokwi CLI
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
run: curl -L https://wokwi.com/ci/install.sh | sh
|
||||||
|
|
||||||
|
- name: Wokwi CI Server
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: wokwi/wokwi-ci-server-action@a6fabb5a49e080158c7a1d121ea5b789536a82c3 # v1
|
||||||
|
|
||||||
|
- name: Get binaries
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
name: tests-bin-${{ matrix.chip }}-${{ matrix.type }}
|
||||||
|
path: |
|
||||||
|
~/.arduino/tests/${{ matrix.chip }}
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
if: ${{ steps.check-tests.outputs.enabled == 'true' }}
|
||||||
|
env:
|
||||||
|
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/tests_run.sh -c -type ${{ matrix.type }} -t ${{ matrix.chip }} -i 0 -m 1 -W ${{ env.WOKWI_TIMEOUT }}
|
||||||
|
|
||||||
|
- name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache
|
||||||
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
|
if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num
|
||||||
|
with:
|
||||||
|
key: tests-${{ env.id }}-results-wokwi
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }}
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
tests/**/*.xml
|
||||||
|
tests/**/result_*.json
|
||||||
|
|
||||||
|
- name: Report conclusion
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const owner = '${{ github.repository_owner }}';
|
||||||
|
const repo = '${{ github.repository }}'.split('/')[1];
|
||||||
|
const sha = '${{ github.event.workflow_run.head_sha }}';
|
||||||
|
core.debug(`owner: ${owner}`);
|
||||||
|
core.debug(`repo: ${repo}`);
|
||||||
|
core.debug(`sha: ${sha}`);
|
||||||
|
const { context: name, state } = (await github.rest.repos.createCommitStatus({
|
||||||
|
context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)',
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
sha: sha,
|
||||||
|
state: '${{ job.status }}',
|
||||||
|
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||||
|
})).data;
|
||||||
|
core.info(`${name} is ${state}`);
|
||||||
51
.github/workflows/upload-idf-component.yml
vendored
51
.github/workflows/upload-idf-component.yml
vendored
|
|
@ -1,20 +1,59 @@
|
||||||
name: Push components to https://components.espressif.com
|
name: Push components to https://components.espressif.com
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
tags:
|
inputs:
|
||||||
- '*'
|
tag:
|
||||||
|
description: 'Version to push to the component registry'
|
||||||
|
required: true
|
||||||
|
git_ref:
|
||||||
|
description: 'Git ref with the source to push to the component registry'
|
||||||
|
required: true
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["ESP32 Arduino Release"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
upload_components:
|
upload_components:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Get the release tag
|
||||||
|
env:
|
||||||
|
head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }}
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event.workflow_run.conclusion }}" != "success" ] && [ "${{ github.event_name }}" == "workflow_run" ]; then
|
||||||
|
echo "Release workflow failed. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read and sanitize the branch/tag name
|
||||||
|
branch=$(echo "$head_branch" | tr -cd '[:alnum:]/_.-')
|
||||||
|
|
||||||
|
if [[ $branch == refs/tags/* ]]; then
|
||||||
|
tag="${branch#refs/tags/}"
|
||||||
|
elif [[ $branch =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
|
||||||
|
tag=$branch
|
||||||
|
else
|
||||||
|
echo "Tag not found in $branch. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Tag: $tag"
|
||||||
|
echo "RELEASE_TAG=$tag" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
|
ref: ${{ inputs.git_ref || env.RELEASE_TAG }}
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
|
|
||||||
- name: Upload components to the component registry
|
- name: Upload components to the component registry
|
||||||
uses: espressif/upload-components-ci-action@v1
|
uses: espressif/upload-components-ci-action@b78a19fa5424714997596d3ecffa634aef8ae20b # v1.0.5
|
||||||
with:
|
with:
|
||||||
name: arduino-esp32
|
name: arduino-esp32
|
||||||
version: ${{ github.ref_name }}
|
version: ${{ env.RELEASE_TAG }}
|
||||||
namespace: espressif
|
namespace: espressif
|
||||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||||
|
|
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
||||||
tools/esp32-arduino-libs
|
tools/esp32-arduino-libs
|
||||||
|
tools/xtensa-esp-elf
|
||||||
tools/xtensa-esp32-elf
|
tools/xtensa-esp32-elf
|
||||||
tools/xtensa-esp32s2-elf
|
tools/xtensa-esp32s2-elf
|
||||||
tools/xtensa-esp32s3-elf
|
tools/xtensa-esp32s3-elf
|
||||||
|
|
@ -44,3 +45,13 @@ debug.cfg
|
||||||
debug.svd
|
debug.svd
|
||||||
debug_custom.json
|
debug_custom.json
|
||||||
libraries/Insights/examples/*/*.ino.zip
|
libraries/Insights/examples/*/*.ino.zip
|
||||||
|
|
||||||
|
# Vale Style
|
||||||
|
.vale/styles/*
|
||||||
|
!.vale/styles/Vocab/
|
||||||
|
.vale/styles/Vocab/*
|
||||||
|
!.vale/styles/Vocab/Espressif/
|
||||||
|
|
||||||
|
# Ignore Lib Builder Docker run scripts
|
||||||
|
/run.sh
|
||||||
|
/run.ps1
|
||||||
|
|
|
||||||
25
.gitlab-ci.yml
Normal file
25
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
# Disable those non-protected push triggered pipelines
|
||||||
|
- if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^\d+\.\d+(\.\d+)?($|-)/ && $CI_PIPELINE_SOURCE == "push"'
|
||||||
|
when: never
|
||||||
|
# when running merged result pipelines, CI_COMMIT_SHA represents the temp commit it created.
|
||||||
|
# Please use PIPELINE_COMMIT_SHA at all places that require a commit sha of the original commit.
|
||||||
|
- if: $CI_OPEN_MERGE_REQUESTS != null
|
||||||
|
variables:
|
||||||
|
PIPELINE_COMMIT_SHA: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
|
||||||
|
IS_MR_PIPELINE: 1
|
||||||
|
- if: $CI_OPEN_MERGE_REQUESTS == null
|
||||||
|
variables:
|
||||||
|
PIPELINE_COMMIT_SHA: $CI_COMMIT_SHA
|
||||||
|
IS_MR_PIPELINE: 0
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||||
|
variables:
|
||||||
|
IS_SCHEDULED_RUN: "true"
|
||||||
|
- when: always
|
||||||
|
|
||||||
|
# Place the default settings in `.gitlab/workflows/common.yml` instead
|
||||||
|
|
||||||
|
include:
|
||||||
|
- ".gitlab/workflows/common.yml"
|
||||||
|
- ".gitlab/workflows/sample.yml"
|
||||||
26
.gitlab/workflows/common.yml
Normal file
26
.gitlab/workflows/common.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#####################
|
||||||
|
# Default Variables #
|
||||||
|
#####################
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- pre_check
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- result
|
||||||
|
|
||||||
|
variables:
|
||||||
|
ESP_IDF_VERSION: "5.5"
|
||||||
|
ESP_ARDUINO_VERSION: "3.3.0"
|
||||||
|
|
||||||
|
#############
|
||||||
|
# `default` #
|
||||||
|
#############
|
||||||
|
|
||||||
|
default:
|
||||||
|
retry:
|
||||||
|
max: 2
|
||||||
|
when:
|
||||||
|
# In case of a runner failure we could hop to another one, or a network error could go away.
|
||||||
|
- runner_system_failure
|
||||||
|
# Job execution timeout may be caused by a network issue.
|
||||||
|
- job_execution_timeout
|
||||||
6
.gitlab/workflows/sample.yml
Normal file
6
.gitlab/workflows/sample.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
hello-world:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- echo "Hello, World from GitLab CI!"
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "push"
|
||||||
110
.pre-commit-config.yaml
Normal file
110
.pre-commit-config.yaml
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
exclude: |
|
||||||
|
(?x)(
|
||||||
|
^\.github\/|
|
||||||
|
^tests\/performance\/coremark\/.*\.[ch]$|
|
||||||
|
^tests\/performance\/superpi\/.*\.(cpp|h)$|
|
||||||
|
LICENSE\.md$
|
||||||
|
)
|
||||||
|
|
||||||
|
default_language_version:
|
||||||
|
# force all unspecified python hooks to run python3
|
||||||
|
python: python3
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: "cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b" # v5.0.0
|
||||||
|
hooks:
|
||||||
|
# Generic checks
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: debug-statements
|
||||||
|
- id: destroyed-symlinks
|
||||||
|
- id: detect-private-key
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
exclude: ^.*\.(bin|BIN)$
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args: [--fix=lf]
|
||||||
|
- id: trailing-whitespace
|
||||||
|
args: [--markdown-linebreak-ext=md]
|
||||||
|
|
||||||
|
# JSON formatting
|
||||||
|
- id: pretty-format-json
|
||||||
|
stages: [manual]
|
||||||
|
args: [--autofix]
|
||||||
|
types_or: [json]
|
||||||
|
exclude: |
|
||||||
|
(?x)(
|
||||||
|
diagram\..*\.json$|
|
||||||
|
package\.json$|
|
||||||
|
^package\/.*$
|
||||||
|
)
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
|
rev: "f6446549e5e97ec9665b9b03e75b87b445857f9a" # v18.1.3
|
||||||
|
hooks:
|
||||||
|
# C/C++ formatting
|
||||||
|
- id: clang-format
|
||||||
|
types_or: [c, c++]
|
||||||
|
exclude: ^.*\/build_opt\.h$
|
||||||
|
|
||||||
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
|
rev: "a4920527036bb9a3f3e6055d595849d67d0da066" # 25.1.0
|
||||||
|
hooks:
|
||||||
|
# Python formatting
|
||||||
|
- id: black
|
||||||
|
types_or: [python]
|
||||||
|
args: [--line-length=120] #From the arduino code style. Add as argument rather than creating a new config file.
|
||||||
|
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: "16f5f28a384f0781bebb37a08aa45e65b9526c50" # 7.2.0
|
||||||
|
hooks:
|
||||||
|
# Python linting
|
||||||
|
- id: flake8
|
||||||
|
types_or: [python]
|
||||||
|
additional_dependencies:
|
||||||
|
- flake8-bugbear
|
||||||
|
- flake8-comprehensions
|
||||||
|
- flake8-simplify
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
|
rev: "ffb6a759a979008c0e6dff86e39f4745a2d9eac4" # v3.1.0
|
||||||
|
hooks:
|
||||||
|
# YAML formatting
|
||||||
|
- id: prettier
|
||||||
|
types_or: [yaml]
|
||||||
|
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: "63c8f8312b7559622c0d82815639671ae42132ac" # v2.4.1
|
||||||
|
hooks:
|
||||||
|
# Spell checking
|
||||||
|
- id: codespell
|
||||||
|
exclude: ^.*\.(svd|SVD)$
|
||||||
|
|
||||||
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||||
|
rev: "a23f6b85d0fdd5bb9d564e2579e678033debbdff" # v0.10.0.1
|
||||||
|
hooks:
|
||||||
|
# Bash linting
|
||||||
|
- id: shellcheck
|
||||||
|
types: [shell]
|
||||||
|
|
||||||
|
- repo: https://github.com/openstack/bashate
|
||||||
|
rev: "fbd7c2534c2701351c603ff700ddf08202430a31" # 2.1.1
|
||||||
|
hooks:
|
||||||
|
# Bash formatting
|
||||||
|
- id: bashate
|
||||||
|
types: [shell]
|
||||||
|
args: ["-i", "E006"] # Ignore E006: Line too long
|
||||||
|
|
||||||
|
- repo: https://github.com/errata-ai/vale
|
||||||
|
rev: "dc4c47923788a413fb5677de6e3370d514aecb78" # v3.11.2
|
||||||
|
hooks:
|
||||||
|
# Sync vale styles and lint markdown and reStructuredText
|
||||||
|
- id: vale
|
||||||
|
name: vale-sync
|
||||||
|
language_version: "1.23.2"
|
||||||
|
pass_filenames: false
|
||||||
|
args: [sync]
|
||||||
|
types_or: [markdown, rst]
|
||||||
|
- id: vale
|
||||||
|
language_version: "1.23.2"
|
||||||
|
types_or: [markdown, rst]
|
||||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
__pycache__/
|
||||||
|
.clang-format
|
||||||
|
.licenses/
|
||||||
|
/.git/
|
||||||
11
.shellcheckrc
Normal file
11
.shellcheckrc
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Shellcheck configuration file for ESP32 Arduino core
|
||||||
|
|
||||||
|
# Optional checks. https://github.com/koalaman/shellcheck/wiki/optional
|
||||||
|
enable=add-default-case,deprecate-which,avoid-nullary-conditions
|
||||||
|
|
||||||
|
# Enable search for external sources
|
||||||
|
external-sources=true
|
||||||
|
|
||||||
|
# Search folder for sourced files.
|
||||||
|
# Set to the folder where the original script is located.
|
||||||
|
source-path=SCRIPTDIR
|
||||||
118
.vale.ini
Normal file
118
.vale.ini
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
###################
|
||||||
|
### Vale Config ###
|
||||||
|
###################
|
||||||
|
|
||||||
|
# This is a Vale linter configuration file.
|
||||||
|
# - Repo: arduino-esp32
|
||||||
|
# - Based on Default config: v0-1-1
|
||||||
|
# It lists all necessary parameters to configure Vale for your project.
|
||||||
|
# For official documentation on all config settings, see
|
||||||
|
# https://vale.sh/docs/topics/config
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
### Global ###
|
||||||
|
##############
|
||||||
|
|
||||||
|
# This section lists core settings applying to Vale itself.
|
||||||
|
|
||||||
|
|
||||||
|
# Specify path to external resources (e.g., styles and vocab files).
|
||||||
|
# The path value may be absolute or relative to this configuration file.
|
||||||
|
StylesPath = .vale/styles
|
||||||
|
|
||||||
|
|
||||||
|
# Specify the minimum alert severity that Vale will report.
|
||||||
|
MinAlertLevel = error # "suggestion", "warning", or "error"
|
||||||
|
|
||||||
|
|
||||||
|
# Specify vocabulary for special treatment.
|
||||||
|
# Create a folder in <StylesPath>/Vocab/<name>/and add its name here
|
||||||
|
# The folder should contain two files:
|
||||||
|
# - accept.txt -- lists words with accepted case-sensitive spelling
|
||||||
|
# - reject.txt -- lists words whose occurrences throw an error
|
||||||
|
# Vocab = Espressif
|
||||||
|
|
||||||
|
|
||||||
|
# Specify the packages to import into your project.
|
||||||
|
# A package is a zip file containing a number of rules (style) written in YAML.
|
||||||
|
# For a list of official packages, see Package Hub at https://vale.sh/hub/
|
||||||
|
# For official documentation on packages, see
|
||||||
|
# https://vale.sh/docs/topics/packages/
|
||||||
|
# Before linting, navigate to your project and run `vale sync` to download
|
||||||
|
# the official packages specified below.
|
||||||
|
# Packages = Package1, Package2, \
|
||||||
|
# https://example.com/path/to/package/Package.zip
|
||||||
|
Packages = Google, Microsoft, RedHat, \
|
||||||
|
https://dl.espressif.com/dl/esp-vale-config/Espressif-latest.zip
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
### Formats ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
# This section enables association of "unknown" formats with the ones
|
||||||
|
# supported by Vale. For official documentation on supported formats, see
|
||||||
|
# https://vale.sh/docs/topics/scoping/
|
||||||
|
[formats]
|
||||||
|
|
||||||
|
# For example, treat MDX files as Markdown files.
|
||||||
|
# mdx = md
|
||||||
|
|
||||||
|
|
||||||
|
################################
|
||||||
|
### Format-specific settings ###
|
||||||
|
################################
|
||||||
|
|
||||||
|
# This section lists the settings that apply to specific file formats
|
||||||
|
# based on their glob pattern.
|
||||||
|
# Settings provided under a more specific glob pattern,
|
||||||
|
# such as [*.{md,txt}] will override those in [*].
|
||||||
|
[*.{md,rst}]
|
||||||
|
|
||||||
|
|
||||||
|
# Enable styles to activate all rules included in them.
|
||||||
|
# BasedOnStyles = Style1, Style2
|
||||||
|
BasedOnStyles = Vale, Espressif-latest
|
||||||
|
|
||||||
|
|
||||||
|
### Deactivate individual rules ###
|
||||||
|
### in enabled styles.
|
||||||
|
# Style1.Rule1 = NO
|
||||||
|
Vale.Repetition = NO
|
||||||
|
Vale.Spelling = NO
|
||||||
|
Espressif-latest.Admonitions = NO
|
||||||
|
Espressif-latest.Contractions = NO
|
||||||
|
Espressif-latest.Monospace = NO
|
||||||
|
|
||||||
|
|
||||||
|
### Change default severity level ###
|
||||||
|
### of an activated rule.
|
||||||
|
# Choose between "suggestion", "warning", or "error".
|
||||||
|
# Style1.Rule2 = error
|
||||||
|
|
||||||
|
|
||||||
|
### Activate individual rules ###
|
||||||
|
### in non-enabled styles stored in <StylesPath>.
|
||||||
|
# Style1.Rule = YES
|
||||||
|
Google.Gender = YES
|
||||||
|
Google.GenderBias = YES
|
||||||
|
Google.Slang = YES
|
||||||
|
Google.Spacing = YES
|
||||||
|
Microsoft.DateNumbers = YES
|
||||||
|
Microsoft.Ellipses = YES
|
||||||
|
Microsoft.FirstPerson = YES
|
||||||
|
Microsoft.Hyphens = YES
|
||||||
|
Microsoft.Ordinal = YES
|
||||||
|
Microsoft.OxfordComma = YES
|
||||||
|
Microsoft.Percentages = YES
|
||||||
|
Microsoft.RangeTime = YES
|
||||||
|
Microsoft.Semicolon = YES
|
||||||
|
Microsoft.SentenceLength = YES
|
||||||
|
Microsoft.Suspended = YES
|
||||||
|
Microsoft.Units = YES
|
||||||
|
Microsoft.URLFormat = YES
|
||||||
|
Microsoft.We = YES
|
||||||
|
Microsoft.Wordiness = YES
|
||||||
|
RedHat.Contractions = YES
|
||||||
|
RedHat.RepeatedWords = YES
|
||||||
148
CMakeLists.txt
148
CMakeLists.txt
|
|
@ -5,8 +5,8 @@
|
||||||
# export ARDUINO_SKIP_IDF_VERSION_CHECK=1
|
# export ARDUINO_SKIP_IDF_VERSION_CHECK=1
|
||||||
# idf.py build
|
# idf.py build
|
||||||
|
|
||||||
set(min_supported_idf_version "5.1.0")
|
set(min_supported_idf_version "5.3.0")
|
||||||
set(max_supported_idf_version "5.1.99")
|
set(max_supported_idf_version "5.5.99")
|
||||||
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
|
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
|
||||||
|
|
||||||
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
|
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
|
||||||
|
|
@ -25,6 +25,7 @@ endif()
|
||||||
set(CORE_SRCS
|
set(CORE_SRCS
|
||||||
cores/esp32/base64.cpp
|
cores/esp32/base64.cpp
|
||||||
cores/esp32/cbuf.cpp
|
cores/esp32/cbuf.cpp
|
||||||
|
cores/esp32/ColorFormat.c
|
||||||
cores/esp32/chip-debug-report.cpp
|
cores/esp32/chip-debug-report.cpp
|
||||||
cores/esp32/esp32-hal-adc.c
|
cores/esp32/esp32-hal-adc.c
|
||||||
cores/esp32/esp32-hal-bt.c
|
cores/esp32/esp32-hal-bt.c
|
||||||
|
|
@ -32,6 +33,7 @@ set(CORE_SRCS
|
||||||
cores/esp32/esp32-hal-dac.c
|
cores/esp32/esp32-hal-dac.c
|
||||||
cores/esp32/esp32-hal-gpio.c
|
cores/esp32/esp32-hal-gpio.c
|
||||||
cores/esp32/esp32-hal-i2c.c
|
cores/esp32/esp32-hal-i2c.c
|
||||||
|
cores/esp32/esp32-hal-i2c-ng.c
|
||||||
cores/esp32/esp32-hal-i2c-slave.c
|
cores/esp32/esp32-hal-i2c-slave.c
|
||||||
cores/esp32/esp32-hal-ledc.c
|
cores/esp32/esp32-hal-ledc.c
|
||||||
cores/esp32/esp32-hal-matrix.c
|
cores/esp32/esp32-hal-matrix.c
|
||||||
|
|
@ -45,15 +47,18 @@ set(CORE_SRCS
|
||||||
cores/esp32/esp32-hal-timer.c
|
cores/esp32/esp32-hal-timer.c
|
||||||
cores/esp32/esp32-hal-tinyusb.c
|
cores/esp32/esp32-hal-tinyusb.c
|
||||||
cores/esp32/esp32-hal-touch.c
|
cores/esp32/esp32-hal-touch.c
|
||||||
|
cores/esp32/esp32-hal-touch-ng.c
|
||||||
cores/esp32/esp32-hal-uart.c
|
cores/esp32/esp32-hal-uart.c
|
||||||
cores/esp32/esp32-hal-rmt.c
|
cores/esp32/esp32-hal-rmt.c
|
||||||
cores/esp32/Esp.cpp
|
cores/esp32/Esp.cpp
|
||||||
|
cores/esp32/freertos_stats.cpp
|
||||||
cores/esp32/FunctionalInterrupt.cpp
|
cores/esp32/FunctionalInterrupt.cpp
|
||||||
cores/esp32/HardwareSerial.cpp
|
cores/esp32/HardwareSerial.cpp
|
||||||
cores/esp32/HEXBuilder.cpp
|
cores/esp32/HEXBuilder.cpp
|
||||||
cores/esp32/IPAddress.cpp
|
cores/esp32/IPAddress.cpp
|
||||||
cores/esp32/libb64/cdecode.c
|
cores/esp32/libb64/cdecode.c
|
||||||
cores/esp32/libb64/cencode.c
|
cores/esp32/libb64/cencode.c
|
||||||
|
cores/esp32/MacAddress.cpp
|
||||||
cores/esp32/main.cpp
|
cores/esp32/main.cpp
|
||||||
cores/esp32/MD5Builder.cpp
|
cores/esp32/MD5Builder.cpp
|
||||||
cores/esp32/Print.cpp
|
cores/esp32/Print.cpp
|
||||||
|
|
@ -82,6 +87,7 @@ set(ARDUINO_ALL_LIBRARIES
|
||||||
DNSServer
|
DNSServer
|
||||||
EEPROM
|
EEPROM
|
||||||
ESP_I2S
|
ESP_I2S
|
||||||
|
ESP_NOW
|
||||||
ESP_SR
|
ESP_SR
|
||||||
ESPmDNS
|
ESPmDNS
|
||||||
Ethernet
|
Ethernet
|
||||||
|
|
@ -91,7 +97,11 @@ set(ARDUINO_ALL_LIBRARIES
|
||||||
HTTPUpdate
|
HTTPUpdate
|
||||||
Insights
|
Insights
|
||||||
LittleFS
|
LittleFS
|
||||||
|
Matter
|
||||||
NetBIOS
|
NetBIOS
|
||||||
|
Network
|
||||||
|
OpenThread
|
||||||
|
PPP
|
||||||
Preferences
|
Preferences
|
||||||
RainMaker
|
RainMaker
|
||||||
SD_MMC
|
SD_MMC
|
||||||
|
|
@ -103,14 +113,14 @@ set(ARDUINO_ALL_LIBRARIES
|
||||||
Update
|
Update
|
||||||
USB
|
USB
|
||||||
WebServer
|
WebServer
|
||||||
WiFiClientSecure
|
NetworkClientSecure
|
||||||
WiFi
|
WiFi
|
||||||
WiFiProv
|
WiFiProv
|
||||||
Wire
|
Wire
|
||||||
|
Zigbee
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp)
|
set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp)
|
||||||
set(ARDUINO_LIBRARY_ArduinoOTA_REQUIRES esp_https_ota)
|
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_AsyncUDP_SRCS libraries/AsyncUDP/src/AsyncUDP.cpp)
|
set(ARDUINO_LIBRARY_AsyncUDP_SRCS libraries/AsyncUDP/src/AsyncUDP.cpp)
|
||||||
|
|
||||||
|
|
@ -126,6 +136,10 @@ set(ARDUINO_LIBRARY_EEPROM_SRCS libraries/EEPROM/src/EEPROM.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_ESP_I2S_SRCS libraries/ESP_I2S/src/ESP_I2S.cpp)
|
set(ARDUINO_LIBRARY_ESP_I2S_SRCS libraries/ESP_I2S/src/ESP_I2S.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_ESP_NOW_SRCS
|
||||||
|
libraries/ESP_NOW/src/ESP32_NOW.cpp
|
||||||
|
libraries/ESP_NOW/src/ESP32_NOW_Serial.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_ESP_SR_SRCS
|
set(ARDUINO_LIBRARY_ESP_SR_SRCS
|
||||||
libraries/ESP_SR/src/ESP_SR.cpp
|
libraries/ESP_SR/src/ESP_SR.cpp
|
||||||
libraries/ESP_SR/src/esp32-hal-sr.c)
|
libraries/ESP_SR/src/esp32-hal-sr.c)
|
||||||
|
|
@ -150,6 +164,33 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp)
|
set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_OpenThread_SRCS
|
||||||
|
libraries/OpenThread/src/OThread.cpp
|
||||||
|
libraries/OpenThread/src/OThreadCLI.cpp
|
||||||
|
libraries/OpenThread/src/OThreadCLI_Util.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_Matter_SRCS
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterThermostat.cpp
|
||||||
|
libraries/Matter/src/Matter.cpp
|
||||||
|
libraries/Matter/src/MatterEndPoint.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_PPP_SRCS
|
||||||
|
libraries/PPP/src/PPP.cpp
|
||||||
|
libraries/PPP/src/ppp.c)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_Preferences_SRCS libraries/Preferences/src/Preferences.cpp)
|
set(ARDUINO_LIBRARY_Preferences_SRCS libraries/Preferences/src/Preferences.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_RainMaker_SRCS
|
set(ARDUINO_LIBRARY_RainMaker_SRCS
|
||||||
|
|
@ -186,6 +227,16 @@ set(ARDUINO_LIBRARY_USB_SRCS
|
||||||
libraries/USB/src/USBMIDI.cpp
|
libraries/USB/src/USBMIDI.cpp
|
||||||
libraries/USB/src/USBHIDMouse.cpp
|
libraries/USB/src/USBHIDMouse.cpp
|
||||||
libraries/USB/src/USBHIDKeyboard.cpp
|
libraries/USB/src/USBHIDKeyboard.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp
|
||||||
|
libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp
|
||||||
libraries/USB/src/USBHIDGamepad.cpp
|
libraries/USB/src/USBHIDGamepad.cpp
|
||||||
libraries/USB/src/USBHIDConsumerControl.cpp
|
libraries/USB/src/USBHIDConsumerControl.cpp
|
||||||
libraries/USB/src/USBHIDSystemControl.cpp
|
libraries/USB/src/USBHIDSystemControl.cpp
|
||||||
|
|
@ -195,28 +246,71 @@ set(ARDUINO_LIBRARY_USB_SRCS
|
||||||
set(ARDUINO_LIBRARY_WebServer_SRCS
|
set(ARDUINO_LIBRARY_WebServer_SRCS
|
||||||
libraries/WebServer/src/WebServer.cpp
|
libraries/WebServer/src/WebServer.cpp
|
||||||
libraries/WebServer/src/Parsing.cpp
|
libraries/WebServer/src/Parsing.cpp
|
||||||
libraries/WebServer/src/detail/mimetable.cpp)
|
libraries/WebServer/src/detail/mimetable.cpp
|
||||||
|
libraries/WebServer/src/middleware/MiddlewareChain.cpp
|
||||||
|
libraries/WebServer/src/middleware/AuthenticationMiddleware.cpp
|
||||||
|
libraries/WebServer/src/middleware/CorsMiddleware.cpp
|
||||||
|
libraries/WebServer/src/middleware/LoggingMiddleware.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_WiFiClientSecure_SRCS
|
set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS
|
||||||
libraries/WiFiClientSecure/src/ssl_client.cpp
|
libraries/NetworkClientSecure/src/ssl_client.cpp
|
||||||
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp)
|
libraries/NetworkClientSecure/src/NetworkClientSecure.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_Network_SRCS
|
||||||
|
libraries/Network/src/NetworkInterface.cpp
|
||||||
|
libraries/Network/src/NetworkEvents.cpp
|
||||||
|
libraries/Network/src/NetworkManager.cpp
|
||||||
|
libraries/Network/src/NetworkClient.cpp
|
||||||
|
libraries/Network/src/NetworkServer.cpp
|
||||||
|
libraries/Network/src/NetworkUdp.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_WiFi_SRCS
|
set(ARDUINO_LIBRARY_WiFi_SRCS
|
||||||
libraries/WiFi/src/WiFiAP.cpp
|
libraries/WiFi/src/WiFiAP.cpp
|
||||||
libraries/WiFi/src/WiFiClient.cpp
|
|
||||||
libraries/WiFi/src/WiFi.cpp
|
libraries/WiFi/src/WiFi.cpp
|
||||||
libraries/WiFi/src/WiFiGeneric.cpp
|
libraries/WiFi/src/WiFiGeneric.cpp
|
||||||
libraries/WiFi/src/WiFiMulti.cpp
|
libraries/WiFi/src/WiFiMulti.cpp
|
||||||
libraries/WiFi/src/WiFiScan.cpp
|
libraries/WiFi/src/WiFiScan.cpp
|
||||||
libraries/WiFi/src/WiFiServer.cpp
|
|
||||||
libraries/WiFi/src/WiFiSTA.cpp
|
libraries/WiFi/src/WiFiSTA.cpp
|
||||||
libraries/WiFi/src/WiFiUdp.cpp)
|
libraries/WiFi/src/STA.cpp
|
||||||
|
libraries/WiFi/src/AP.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp)
|
set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp)
|
set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp)
|
||||||
|
|
||||||
|
set(ARDUINO_LIBRARY_Zigbee_SRCS
|
||||||
|
libraries/Zigbee/src/ZigbeeCore.cpp
|
||||||
|
libraries/Zigbee/src/ZigbeeEP.cpp
|
||||||
|
libraries/Zigbee/src/ZigbeeHandlers.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeLight.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeSwitch.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeAnalog.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeGateway.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeElectricalMeasurement.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeBinary.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
|
||||||
|
libraries/Zigbee/src/ep/ZigbeeFanControl.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_BLE_SRCS
|
set(ARDUINO_LIBRARY_BLE_SRCS
|
||||||
|
libraries/BLE/src/BLE2901.cpp
|
||||||
libraries/BLE/src/BLE2902.cpp
|
libraries/BLE/src/BLE2902.cpp
|
||||||
libraries/BLE/src/BLE2904.cpp
|
libraries/BLE/src/BLE2904.cpp
|
||||||
libraries/BLE/src/BLEAddress.cpp
|
libraries/BLE/src/BLEAddress.cpp
|
||||||
|
|
@ -268,8 +362,20 @@ endforeach()
|
||||||
set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS})
|
set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRARIES_INCLUDEDIRS})
|
||||||
set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS})
|
set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS})
|
||||||
set(priv_includes cores/esp32/libb64)
|
set(priv_includes cores/esp32/libb64)
|
||||||
set(requires spi_flash esp_partition mbedtls wifi_provisioning wpa_supplicant esp_adc esp_eth http_parser)
|
set(requires spi_flash esp_partition mbedtls wpa_supplicant esp_adc esp_eth http_parser esp_ringbuf esp_driver_gptimer esp_driver_usb_serial_jtag driver esp_http_client esp_https_ota)
|
||||||
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid ${ARDUINO_LIBRARIES_REQUIRES})
|
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb esp_psram ${ARDUINO_LIBRARIES_REQUIRES})
|
||||||
|
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThread)
|
||||||
|
#if(CONFIG_SOC_IEEE802154_SUPPORTED) # Does not work!
|
||||||
|
#if(CONFIG_OPENTHREAD_ENABLED) # Does not work!
|
||||||
|
if(IDF_TARGET STREQUAL "esp32c6" OR IDF_TARGET STREQUAL "esp32h2" OR IDF_TARGET STREQUAL "esp32c5") # Sadly only this works
|
||||||
|
list(APPEND requires openthread)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(IDF_TARGET STREQUAL "esp32p4")
|
||||||
|
list(APPEND requires esp_driver_touch_sens)
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
|
||||||
|
|
||||||
|
|
@ -287,7 +393,7 @@ target_compile_options(${COMPONENT_TARGET} PUBLIC
|
||||||
-DARDUINO_ARCH_ESP32
|
-DARDUINO_ARCH_ESP32
|
||||||
-DARDUINO_BOARD="${idf_target_caps}_DEV"
|
-DARDUINO_BOARD="${idf_target_caps}_DEV"
|
||||||
-DARDUINO_VARIANT="${CONFIG_ARDUINO_VARIANT}"
|
-DARDUINO_VARIANT="${CONFIG_ARDUINO_VARIANT}"
|
||||||
-DESP32)
|
-DESP32=ESP32)
|
||||||
|
|
||||||
if(CONFIG_AUTOSTART_ARDUINO)
|
if(CONFIG_AUTOSTART_ARDUINO)
|
||||||
# in autostart mode, arduino-esp32 contains app_main() function and needs to
|
# in autostart mode, arduino-esp32 contains app_main() function and needs to
|
||||||
|
|
@ -310,9 +416,21 @@ function(maybe_add_component component_name)
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if(IDF_TARGET MATCHES "esp32s2|esp32s3" AND CONFIG_TINYUSB_ENABLED)
|
if(IDF_TARGET MATCHES "esp32s2|esp32s3|esp32p4" AND CONFIG_TINYUSB_ENABLED)
|
||||||
maybe_add_component(arduino_tinyusb)
|
maybe_add_component(arduino_tinyusb)
|
||||||
endif()
|
endif()
|
||||||
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
|
||||||
maybe_add_component(esp_https_ota)
|
maybe_add_component(esp_https_ota)
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ESP_SR)
|
||||||
|
maybe_add_component(espressif__esp_sr)
|
||||||
|
endif()
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_Matter)
|
||||||
|
maybe_add_component(espressif__esp_matter)
|
||||||
|
endif()
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LittleFS)
|
||||||
|
maybe_add_component(joltwallet__littlefs)
|
||||||
|
endif()
|
||||||
|
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_WiFiProv)
|
||||||
|
maybe_add_component(espressif__network_provisioning)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
identity and expression, level of experience, education, socioeconomic status,
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
and orientation.
|
and orientation.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ config ARDUHAL_ESP_LOG
|
||||||
default "n"
|
default "n"
|
||||||
help
|
help
|
||||||
This option will redefine the ESP_LOGx macros to Arduino's log_x macros.
|
This option will redefine the ESP_LOGx macros to Arduino's log_x macros.
|
||||||
To enable for your application, add the follwing after your includes:
|
To enable for your application, add the following after your includes:
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#include "esp32-hal-log.h"
|
#include "esp32-hal-log.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -256,119 +256,31 @@ config ARDUINO_SELECTIVE_COMPILATION
|
||||||
bool "Include only specific Arduino libraries"
|
bool "Include only specific Arduino libraries"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_ArduinoOTA
|
config ARDUINO_SELECTIVE_SPI
|
||||||
bool "Enable ArduinoOTA"
|
bool "Enable SPI"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
select ARDUINO_SELECTIVE_ESPmDNS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_AsyncUDP
|
|
||||||
bool "Enable AsyncUDP"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_AzureIoT
|
config ARDUINO_SELECTIVE_Wire
|
||||||
bool "Enable AzureIoT"
|
bool "Enable Wire"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_HTTPClient
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_BLE
|
|
||||||
bool "Enable BLE"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_BluetoothSerial
|
config ARDUINO_SELECTIVE_ESP_SR
|
||||||
bool "Enable BluetoothSerial"
|
bool "Enable ESP-SR"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_DNSServer
|
|
||||||
bool "Enable DNSServer"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_EEPROM
|
config ARDUINO_SELECTIVE_EEPROM
|
||||||
bool "Enable EEPROM"
|
bool "Enable EEPROM"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_ESP32
|
|
||||||
bool "Enable ESP32"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_ESPmDNS
|
|
||||||
bool "Enable ESPmDNS"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_FFat
|
|
||||||
bool "Enable FFat"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_FS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_FS
|
|
||||||
bool "Enable FS"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_HTTPClient
|
|
||||||
bool "Enable HTTPClient"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
select ARDUINO_SELECTIVE_WiFiClientSecure
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_LITTLEFS
|
|
||||||
bool "Enable LITTLEFS"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_FS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_NetBIOS
|
|
||||||
bool "Enable NetBIOS"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_Preferences
|
config ARDUINO_SELECTIVE_Preferences
|
||||||
bool "Enable Preferences"
|
bool "Enable Preferences"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SD
|
|
||||||
bool "Enable SD"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_FS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SD_MMC
|
|
||||||
bool "Enable SD_MMC"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_FS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SimpleBLE
|
|
||||||
bool "Enable SimpleBLE"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SPI
|
|
||||||
bool "Enable SPI"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_SPIFFS
|
|
||||||
bool "Enable SPIFFS"
|
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
|
||||||
select ARDUINO_SELECTIVE_FS
|
|
||||||
default y
|
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_Ticker
|
config ARDUINO_SELECTIVE_Ticker
|
||||||
bool "Enable Ticker"
|
bool "Enable Ticker"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
|
@ -379,34 +291,142 @@ config ARDUINO_SELECTIVE_Update
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Zigbee
|
||||||
|
bool "Enable Zigbee"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_FS
|
||||||
|
bool "Enable FS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SD
|
||||||
|
bool "Enable SD"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SD_MMC
|
||||||
|
bool "Enable SD_MMC"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SPIFFS
|
||||||
|
bool "Enable SPIFFS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_FFat
|
||||||
|
bool "Enable FFat"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_LittleFS
|
||||||
|
bool "Enable LittleFS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Network
|
||||||
|
bool "Enable Networking"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Ethernet
|
||||||
|
bool "Enable Ethernet"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_PPP
|
||||||
|
bool "Enable PPP"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_ArduinoOTA
|
||||||
|
bool "Enable ArduinoOTA"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
select ARDUINO_SELECTIVE_ESPmDNS
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_AsyncUDP
|
||||||
|
bool "Enable AsyncUDP"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_DNSServer
|
||||||
|
bool "Enable DNSServer"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_ESPmDNS
|
||||||
|
bool "Enable ESPmDNS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_HTTPClient
|
||||||
|
bool "Enable HTTPClient"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
select ARDUINO_SELECTIVE_NetworkClientSecure
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Matter
|
||||||
|
bool "Enable Matter"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_NetBIOS
|
||||||
|
bool "Enable NetBIOS"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_WebServer
|
config ARDUINO_SELECTIVE_WebServer
|
||||||
bool "Enable WebServer"
|
bool "Enable WebServer"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
default y
|
default y
|
||||||
select ARDUINO_SELECTIVE_FS
|
select ARDUINO_SELECTIVE_FS
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_WiFi
|
config ARDUINO_SELECTIVE_WiFi
|
||||||
bool "Enable WiFi"
|
bool "Enable WiFi"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_WiFiClientSecure
|
config ARDUINO_SELECTIVE_NetworkClientSecure
|
||||||
bool "Enable WiFiClientSecure"
|
bool "Enable NetworkClientSecure"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_WiFiProv
|
config ARDUINO_SELECTIVE_WiFiProv
|
||||||
bool "Enable WiFiProv"
|
bool "Enable WiFiProv"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Network && ARDUINO_SELECTIVE_WiFi
|
||||||
select ARDUINO_SELECTIVE_WiFi
|
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config ARDUINO_SELECTIVE_Wire
|
config ARDUINO_SELECTIVE_BLE
|
||||||
bool "Enable Wire"
|
bool "Enable BLE"
|
||||||
depends on ARDUINO_SELECTIVE_COMPILATION
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_BluetoothSerial
|
||||||
|
bool "Enable BluetoothSerial"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_SimpleBLE
|
||||||
|
bool "Enable SimpleBLE"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_RainMaker
|
||||||
|
bool "Enable RainMaker"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_OpenThread
|
||||||
|
bool "Enable OpenThread"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ARDUINO_SELECTIVE_Insights
|
||||||
|
bool "Enable Insights"
|
||||||
|
depends on ARDUINO_SELECTIVE_COMPILATION
|
||||||
|
default y
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
|
||||||
37
README.md
37
README.md
|
|
@ -1,8 +1,13 @@
|
||||||
# Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2
|
# Arduino core for the ESP32, ESP32-C3, ESP32-C6, ESP32-H2, ESP32-P4, ESP32-S2 and ESP32-S3.
|
||||||
|
|
||||||
 [](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml?link=http://https://github.com/espressif/arduino-esp32/blob/master/LIBRARIES_TEST.md)
|
[](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Apush)
|
||||||
|
[)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Aschedule)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/RUNTIME_TESTS_REPORT.md)
|
||||||
|
|
||||||
### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions)
|
### Need help or have a question? Join the chat at [Discord](https://discord.gg/8xY6e9crwv) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions)
|
||||||
|
|
||||||
|
[](https://discord.gg/8xY6e9crwv)
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
|
|
@ -16,9 +21,17 @@
|
||||||
|
|
||||||
### Development Status
|
### Development Status
|
||||||
|
|
||||||
Latest Stable Release [](https://github.com/espressif/arduino-esp32/releases/latest/) [](https://github.com/espressif/arduino-esp32/releases/latest/) [](https://github.com/espressif/arduino-esp32/releases/latest/)
|
#### Latest Stable Release
|
||||||
|
|
||||||
Latest Development Release [](https://github.com/espressif/arduino-esp32/releases/) [](https://github.com/espressif/arduino-esp32/releases/) [](https://github.com/espressif/arduino-esp32/releases/)
|
[](https://github.com/espressif/arduino-esp32/releases/latest/)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/releases/latest/)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/releases/latest/)
|
||||||
|
|
||||||
|
#### Latest Development Release
|
||||||
|
|
||||||
|
[](https://github.com/espressif/arduino-esp32/releases/)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/releases/)
|
||||||
|
[](https://github.com/espressif/arduino-esp32/releases/)
|
||||||
|
|
||||||
### Development Planning
|
### Development Planning
|
||||||
|
|
||||||
|
|
@ -54,11 +67,17 @@ Here are the ESP32 series supported by the Arduino-ESP32 project:
|
||||||
| **SoC** | **Stable** | **Development** | **Datasheet** |
|
| **SoC** | **Stable** | **Development** | **Datasheet** |
|
||||||
|----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:|
|
|----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:|
|
||||||
| ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) |
|
| ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) |
|
||||||
| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) |
|
|
||||||
| ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) |
|
| ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) |
|
||||||
|
| ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) |
|
||||||
|
| ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) |
|
||||||
|
| ESP32-P4 | Yes | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) |
|
||||||
|
| ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) |
|
||||||
| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) |
|
| ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) |
|
||||||
| ESP32-C6 | No | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) |
|
|
||||||
| ESP32-H2 | No | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) |
|
> [!NOTE]
|
||||||
|
> ESP32-C2 is also supported by Arduino-ESP32 but requires using Arduino as an ESP-IDF component or rebuilding the static libraries.
|
||||||
|
> For more information, see the [Arduino as an ESP-IDF component documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html) or the
|
||||||
|
> [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html), respectively.
|
||||||
|
|
||||||
For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page.
|
For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page.
|
||||||
|
|
||||||
|
|
@ -68,7 +87,7 @@ You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecod
|
||||||
|
|
||||||
### Issue/Bug report template
|
### Issue/Bug report template
|
||||||
|
|
||||||
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [Type: For reference](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue+label%3A%22Type%3A+For+reference%22+).
|
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labeled as [Type: For reference](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue+label%3A%22Type%3A+For+reference%22+).
|
||||||
|
|
||||||
Finally, if you are sure no one else had the issue, follow the **Issue template** or **Feature request template** while reporting any [new Issue](https://github.com/espressif/arduino-esp32/issues/new/choose).
|
Finally, if you are sure no one else had the issue, follow the **Issue template** or **Feature request template** while reporting any [new Issue](https://github.com/espressif/arduino-esp32/issues/new/choose).
|
||||||
|
|
||||||
|
|
|
||||||
19277
boards.txt
19277
boards.txt
File diff suppressed because it is too large
Load diff
|
|
@ -33,7 +33,6 @@
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "esp8266-compat.h"
|
#include "esp8266-compat.h"
|
||||||
#include "soc/gpio_reg.h"
|
#include "soc/gpio_reg.h"
|
||||||
|
|
||||||
|
|
@ -41,12 +40,15 @@
|
||||||
#include "binary.h"
|
#include "binary.h"
|
||||||
#include "extra_attr.h"
|
#include "extra_attr.h"
|
||||||
|
|
||||||
#define PI 3.1415926535897932384626433832795
|
#include "pins_arduino.h"
|
||||||
#define HALF_PI 1.5707963267948966192313216916398
|
#include "esp32-hal.h"
|
||||||
#define TWO_PI 6.283185307179586476925286766559
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
#define EULER 2.718281828459045235360287471352
|
#define EULER 2.718281828459045235360287471352
|
||||||
|
|
||||||
#define SERIAL 0x0
|
#define SERIAL 0x0
|
||||||
#define DISPLAY 0x1
|
#define DISPLAY 0x1
|
||||||
|
|
@ -63,7 +65,7 @@
|
||||||
#define ONLOW_WE 0x0C
|
#define ONLOW_WE 0x0C
|
||||||
#define ONHIGH_WE 0x0D
|
#define ONHIGH_WE 0x0D
|
||||||
|
|
||||||
#define DEFAULT 1
|
#define DEFAULT 1
|
||||||
#define EXTERNAL 0
|
#define EXTERNAL 0
|
||||||
|
|
||||||
#ifndef __STRINGIFY
|
#ifndef __STRINGIFY
|
||||||
|
|
@ -71,76 +73,79 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// can't define max() / min() because of conflicts with C++
|
// can't define max() / min() because of conflicts with C++
|
||||||
#define _min(a,b) ((a)<(b)?(a):(b))
|
#define _min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define _max(a,b) ((a)>(b)?(a):(b))
|
#define _max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define _abs(x) ((x)>0?(x):-(x)) // abs() comes from STL
|
#define _abs(x) ((x) > 0 ? (x) : -(x)) // abs() comes from STL
|
||||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
|
||||||
#define _round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) // round() comes from STL
|
#define _round(x) ((x) >= 0 ? (long)((x) + 0.5) : (long)((x) - 0.5)) // round() comes from STL
|
||||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
#define radians(deg) ((deg) * DEG_TO_RAD)
|
||||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
#define degrees(rad) ((rad) * RAD_TO_DEG)
|
||||||
#define sq(x) ((x)*(x))
|
#define sq(x) ((x) * (x))
|
||||||
|
|
||||||
// ESP32xx runs FreeRTOS... disabling interrupts can lead to issues, such as Watchdog Timeout
|
// ESP32xx runs FreeRTOS... disabling interrupts can lead to issues, such as Watchdog Timeout
|
||||||
#define sei() portENABLE_INTERRUPTS()
|
#define sei() portENABLE_INTERRUPTS()
|
||||||
#define cli() portDISABLE_INTERRUPTS()
|
#define cli() portDISABLE_INTERRUPTS()
|
||||||
#define interrupts() sei()
|
#define interrupts() sei()
|
||||||
#define noInterrupts() cli()
|
#define noInterrupts() cli()
|
||||||
|
|
||||||
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
|
#define clockCyclesPerMicrosecond() ((long int)getCpuFrequencyMhz())
|
||||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
#define clockCyclesToMicroseconds(a) ((a) / clockCyclesPerMicrosecond())
|
||||||
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
#define microsecondsToClockCycles(a) ((a) * clockCyclesPerMicrosecond())
|
||||||
|
|
||||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
#define lowByte(w) ((uint8_t)((w) & 0xff))
|
||||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
#define highByte(w) ((uint8_t)((w) >> 8))
|
||||||
|
|
||||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||||
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
|
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
|
||||||
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
|
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
|
||||||
|
|
||||||
// avr-libc defines _NOP() since 1.6.2
|
// avr-libc defines _NOP() since 1.6.2
|
||||||
#ifndef _NOP
|
#ifndef _NOP
|
||||||
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
|
#define _NOP() \
|
||||||
|
do { \
|
||||||
|
__asm__ volatile("nop"); \
|
||||||
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define bit(b) (1UL << (b))
|
#define bit(b) (1UL << (b))
|
||||||
#define _BV(b) (1UL << (b))
|
#define _BV(b) (1UL << (b))
|
||||||
|
|
||||||
#define digitalPinToTimer(pin) (0)
|
#define digitalPinToTimer(pin) (0)
|
||||||
#define analogInPinToBit(P) (P)
|
#define analogInPinToBit(P) (P)
|
||||||
#if SOC_GPIO_PIN_COUNT <= 32
|
#if SOC_GPIO_PIN_COUNT <= 32
|
||||||
#define digitalPinToPort(pin) (0)
|
#define digitalPinToPort(pin) (0)
|
||||||
#define digitalPinToBitMask(pin) (1UL << digitalPinToGPIONumber(pin))
|
#define digitalPinToBitMask(pin) (1UL << digitalPinToGPIONumber(pin))
|
||||||
#define portOutputRegister(port) ((volatile uint32_t*)GPIO_OUT_REG)
|
#define portOutputRegister(port) ((volatile uint32_t *)GPIO_OUT_REG)
|
||||||
#define portInputRegister(port) ((volatile uint32_t*)GPIO_IN_REG)
|
#define portInputRegister(port) ((volatile uint32_t *)GPIO_IN_REG)
|
||||||
#define portModeRegister(port) ((volatile uint32_t*)GPIO_ENABLE_REG)
|
#define portModeRegister(port) ((volatile uint32_t *)GPIO_ENABLE_REG)
|
||||||
#elif SOC_GPIO_PIN_COUNT <= 64
|
#elif SOC_GPIO_PIN_COUNT <= 64
|
||||||
#define digitalPinToPort(pin) ((digitalPinToGPIONumber(pin)>31)?1:0)
|
#define digitalPinToPort(pin) ((digitalPinToGPIONumber(pin) > 31) ? 1 : 0)
|
||||||
#define digitalPinToBitMask(pin) (1UL << (digitalPinToGPIONumber(pin)&31))
|
#define digitalPinToBitMask(pin) (1UL << (digitalPinToGPIONumber(pin) & 31))
|
||||||
#define portOutputRegister(port) ((volatile uint32_t*)((port)?GPIO_OUT1_REG:GPIO_OUT_REG))
|
#define portOutputRegister(port) ((volatile uint32_t *)((port) ? GPIO_OUT1_REG : GPIO_OUT_REG))
|
||||||
#define portInputRegister(port) ((volatile uint32_t*)((port)?GPIO_IN1_REG:GPIO_IN_REG))
|
#define portInputRegister(port) ((volatile uint32_t *)((port) ? GPIO_IN1_REG : GPIO_IN_REG))
|
||||||
#define portModeRegister(port) ((volatile uint32_t*)((port)?GPIO_ENABLE1_REG:GPIO_ENABLE_REG))
|
#define portModeRegister(port) ((volatile uint32_t *)((port) ? GPIO_ENABLE1_REG : GPIO_ENABLE_REG))
|
||||||
#else
|
#else
|
||||||
#error SOC_GPIO_PIN_COUNT > 64 not implemented
|
#error SOC_GPIO_PIN_COUNT > 64 not implemented
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NOT_A_PIN -1
|
#define NOT_A_PIN -1
|
||||||
#define NOT_A_PORT -1
|
#define NOT_A_PORT -1
|
||||||
#define NOT_AN_INTERRUPT -1
|
#define NOT_AN_INTERRUPT -1
|
||||||
#define NOT_ON_TIMER 0
|
#define NOT_ON_TIMER 0
|
||||||
|
|
||||||
// some defines generic for all SoC moved from variants/board_name/pins_arduino.h
|
// some defines generic for all SoC moved from variants/board_name/pins_arduino.h
|
||||||
#define NUM_DIGITAL_PINS SOC_GPIO_PIN_COUNT // All GPIOs
|
#define NUM_DIGITAL_PINS SOC_GPIO_PIN_COUNT // All GPIOs
|
||||||
#if SOC_ADC_PERIPH_NUM == 1
|
#if SOC_ADC_PERIPH_NUM == 1
|
||||||
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0)) // Depends on the SoC (ESP32C6, ESP32H2, ESP32C2, ESP32P4)
|
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0)) // Depends on the SoC (ESP32C6, ESP32H2, ESP32C2, ESP32P4)
|
||||||
#elif SOC_ADC_PERIPH_NUM == 2
|
#elif SOC_ADC_PERIPH_NUM == 2
|
||||||
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0)+SOC_ADC_CHANNEL_NUM(1)) // Depends on the SoC (ESP32, ESP32S2, ESP32S3, ESP32C3)
|
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0) + SOC_ADC_CHANNEL_NUM(1)) // Depends on the SoC (ESP32, ESP32S2, ESP32S3, ESP32C3)
|
||||||
#endif
|
#endif
|
||||||
#define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs
|
#define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs
|
||||||
#define analogInputToDigitalPin(p) (((p)<NUM_ANALOG_INPUTS)?(analogChannelToDigitalPin(p)):-1)
|
#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1)
|
||||||
#define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p))<NUM_DIGITAL_PINS)?digitalPinToGPIONumber(p):NOT_AN_INTERRUPT)
|
#define digitalPinToInterrupt(p) ((((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS) ? (p) : NOT_AN_INTERRUPT)
|
||||||
#define digitalPinHasPWM(p) (((uint8_t)digitalPinToGPIONumber(p))<NUM_DIGITAL_PINS)
|
#define digitalPinHasPWM(p) (((uint8_t)digitalPinToGPIONumber(p)) < NUM_DIGITAL_PINS)
|
||||||
|
|
||||||
typedef bool boolean;
|
typedef bool boolean;
|
||||||
typedef uint8_t byte;
|
typedef uint8_t byte;
|
||||||
|
|
@ -176,7 +181,7 @@ void initArduino(void);
|
||||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||||
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
|
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||||
|
|
||||||
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); // codespell:ignore shiftin
|
||||||
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -196,6 +201,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
#include "Udp.h"
|
#include "Udp.h"
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "Esp.h"
|
#include "Esp.h"
|
||||||
|
#include "freertos_stats.h"
|
||||||
|
|
||||||
// Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries
|
// Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries
|
||||||
using std::abs;
|
using std::abs;
|
||||||
|
|
@ -211,23 +217,33 @@ uint16_t makeWord(uint8_t h, uint8_t l);
|
||||||
#define word(...) makeWord(__VA_ARGS__)
|
#define word(...) makeWord(__VA_ARGS__)
|
||||||
|
|
||||||
size_t getArduinoLoopTaskStackSize(void);
|
size_t getArduinoLoopTaskStackSize(void);
|
||||||
#define SET_LOOP_TASK_STACK_SIZE(sz) size_t getArduinoLoopTaskStackSize() { return sz;}
|
#define SET_LOOP_TASK_STACK_SIZE(sz) \
|
||||||
|
size_t getArduinoLoopTaskStackSize() { \
|
||||||
|
return sz; \
|
||||||
|
}
|
||||||
|
|
||||||
bool shouldPrintChipDebugReport(void);
|
bool shouldPrintChipDebugReport(void);
|
||||||
#define ENABLE_CHIP_DEBUG_REPORT bool shouldPrintChipDebugReport(void){return true;}
|
#define ENABLE_CHIP_DEBUG_REPORT \
|
||||||
|
bool shouldPrintChipDebugReport(void) { \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
// allows user to bypass esp_spiram_test()
|
// allows user to bypass esp_spiram_test()
|
||||||
bool esp_psram_extram_test(void);
|
bool esp_psram_extram_test(void);
|
||||||
#define BYPASS_SPIRAM_TEST(bypass) bool testSPIRAM(void) { if (bypass) return true; else return esp_psram_extram_test(); }
|
#define BYPASS_SPIRAM_TEST(bypass) \
|
||||||
|
bool testSPIRAM(void) { \
|
||||||
|
if (bypass) \
|
||||||
|
return true; \
|
||||||
|
else \
|
||||||
|
return esp_psram_extram_test(); \
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
|
||||||
extern "C" bool getLocalTime(struct tm * info, uint32_t ms = 5000);
|
extern "C" bool getLocalTime(struct tm *info, uint32_t ms = 5000);
|
||||||
extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec,
|
extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, const char *server2 = nullptr, const char *server3 = nullptr);
|
||||||
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
extern "C" void configTzTime(const char *tz, const char *server1, const char *server2 = nullptr, const char *server3 = nullptr);
|
||||||
extern "C" void configTzTime(const char* tz,
|
|
||||||
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
|
||||||
|
|
||||||
void setToneChannel(uint8_t channel = 0);
|
void setToneChannel(uint8_t channel = 0);
|
||||||
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||||
|
|
@ -235,7 +251,7 @@ void noTone(uint8_t _pin);
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#include "pins_arduino.h"
|
// must be applied last as it overrides some of the above
|
||||||
#include "io_pin_remap.h"
|
#include "io_pin_remap.h"
|
||||||
|
|
||||||
#endif /* _ESP32_CORE_ARDUINO_H_ */
|
#endif /* _ESP32_CORE_ARDUINO_H_ */
|
||||||
|
|
|
||||||
|
|
@ -23,26 +23,25 @@
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "IPAddress.h"
|
#include "IPAddress.h"
|
||||||
|
|
||||||
class Client: public Stream
|
class Client : public Stream {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
virtual int connect(IPAddress ip, uint16_t port) = 0;
|
||||||
virtual int connect(const char *host, uint16_t port) =0;
|
virtual int connect(const char *host, uint16_t port) = 0;
|
||||||
virtual size_t write(uint8_t) =0;
|
virtual size_t write(uint8_t) = 0;
|
||||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||||
virtual int available() = 0;
|
virtual int available() = 0;
|
||||||
virtual int read() = 0;
|
virtual int read() = 0;
|
||||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||||
virtual int peek() = 0;
|
virtual int peek() = 0;
|
||||||
virtual void flush() = 0;
|
virtual void flush() = 0;
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
virtual uint8_t connected() = 0;
|
virtual uint8_t connected() = 0;
|
||||||
virtual operator bool() = 0;
|
virtual operator bool() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t* rawIPAddress(IPAddress& addr)
|
uint8_t *rawIPAddress(IPAddress &addr) {
|
||||||
{
|
return addr.raw_address();
|
||||||
return addr.raw_address();
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
281
cores/esp32/ColorFormat.c
Normal file
281
cores/esp32/ColorFormat.c
Normal file
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Project CHIP Authors
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ColorFormat.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
|
||||||
|
#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
|
||||||
|
|
||||||
|
const espHsvColor_t HSV_BLACK = {0, 0, 0};
|
||||||
|
const espHsvColor_t HSV_WHITE = {0, 0, 254};
|
||||||
|
const espHsvColor_t HSV_RED = {0, 254, 254};
|
||||||
|
const espHsvColor_t HSV_YELLOW = {42, 254, 254};
|
||||||
|
const espHsvColor_t HSV_GREEN = {84, 254, 254};
|
||||||
|
const espHsvColor_t HSV_CYAN = {127, 254, 254};
|
||||||
|
const espHsvColor_t HSV_BLUE = {169, 254, 254};
|
||||||
|
const espHsvColor_t HSV_MAGENTA = {211, 254, 254};
|
||||||
|
|
||||||
|
const espRgbColor_t RGB_BLACK = {0, 0, 0};
|
||||||
|
const espRgbColor_t RGB_WHITE = {255, 255, 255};
|
||||||
|
const espRgbColor_t RGB_RED = {255, 0, 0};
|
||||||
|
const espRgbColor_t RGB_YELLOW = {255, 255, 0};
|
||||||
|
const espRgbColor_t RGB_GREEN = {0, 255, 0};
|
||||||
|
const espRgbColor_t RGB_CYAN = {0, 255, 255};
|
||||||
|
const espRgbColor_t RGB_BLUE = {0, 0, 255};
|
||||||
|
const espRgbColor_t RGB_MAGENTA = {255, 0, 255};
|
||||||
|
|
||||||
|
// main color temperature values
|
||||||
|
const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE = {142};
|
||||||
|
const espCtColor_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = {181};
|
||||||
|
const espCtColor_t WHITE_COLOR_TEMPERATURE = {250};
|
||||||
|
const espCtColor_t SOFT_WHITE_COLOR_TEMPERATURE = {370};
|
||||||
|
const espCtColor_t WARM_WHITE_COLOR_TEMPERATURE = {454};
|
||||||
|
|
||||||
|
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v) {
|
||||||
|
espHsvColor_t hsv = {h, s, v};
|
||||||
|
return espHsvColorToRgbColor(hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv) {
|
||||||
|
espRgbColor_t rgb;
|
||||||
|
|
||||||
|
uint8_t region, p, q, t;
|
||||||
|
uint32_t h, s, v, remainder;
|
||||||
|
|
||||||
|
if (hsv.s == 0) {
|
||||||
|
rgb.r = rgb.g = rgb.b = hsv.v;
|
||||||
|
} else {
|
||||||
|
h = hsv.h;
|
||||||
|
s = hsv.s;
|
||||||
|
v = hsv.v;
|
||||||
|
|
||||||
|
region = h / 43;
|
||||||
|
remainder = (h - (region * 43)) * 6;
|
||||||
|
p = (v * (255 - s)) >> 8;
|
||||||
|
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||||
|
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||||
|
switch (region) {
|
||||||
|
case 0: rgb.r = v, rgb.g = t, rgb.b = p; break;
|
||||||
|
case 1: rgb.r = q, rgb.g = v, rgb.b = p; break;
|
||||||
|
case 2: rgb.r = p, rgb.g = v, rgb.b = t; break;
|
||||||
|
case 3: rgb.r = p, rgb.g = q, rgb.b = v; break;
|
||||||
|
case 4: rgb.r = t, rgb.g = p, rgb.b = v; break;
|
||||||
|
case 5:
|
||||||
|
default: rgb.r = v, rgb.g = p, rgb.b = q; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
espRgbColor_t rgb = {r, g, b};
|
||||||
|
return espRgbColorToHsvColor(rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb) {
|
||||||
|
espHsvColor_t hsv;
|
||||||
|
uint8_t rgbMin, rgbMax;
|
||||||
|
|
||||||
|
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
|
||||||
|
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
|
||||||
|
|
||||||
|
hsv.v = rgbMax;
|
||||||
|
if (hsv.v == 0) {
|
||||||
|
hsv.h = 0;
|
||||||
|
hsv.s = 0;
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
hsv.s = 255 * (rgbMax - rgbMin) / hsv.v;
|
||||||
|
if (hsv.s == 0) {
|
||||||
|
hsv.h = 0;
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
if (rgbMax == rgb.r) {
|
||||||
|
hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
|
||||||
|
} else if (rgbMax == rgb.g) {
|
||||||
|
hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
|
||||||
|
} else {
|
||||||
|
hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
|
||||||
|
}
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
espRgbColor_t espXYColorToRgbColor(uint8_t Level, espXyColor_t xy) {
|
||||||
|
return espXYToRgbColor(Level, xy.x, xy.y, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y, bool addXYZScaling) {
|
||||||
|
// convert xyY color space to RGB
|
||||||
|
|
||||||
|
// https://www.easyrgb.com/en/math.php
|
||||||
|
// https://en.wikipedia.org/wiki/SRGB
|
||||||
|
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
|
||||||
|
|
||||||
|
// The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y.
|
||||||
|
// The value of x/y shall be related to the current_X/current_Y attribute by the relationship
|
||||||
|
// x = current_X/65536
|
||||||
|
// y = current_Y/65536
|
||||||
|
// z = 1-x-y
|
||||||
|
|
||||||
|
espRgbColor_t rgb;
|
||||||
|
|
||||||
|
float x, y, z;
|
||||||
|
float X, Y, Z;
|
||||||
|
float r, g, b;
|
||||||
|
|
||||||
|
x = ((float)current_X) / 65535.0f;
|
||||||
|
y = ((float)current_Y) / 65535.0f;
|
||||||
|
|
||||||
|
z = 1.0f - x - y;
|
||||||
|
|
||||||
|
// Calculate XYZ values
|
||||||
|
|
||||||
|
// Y - given brightness in 0 - 1 range
|
||||||
|
Y = ((float)Level) / 254.0f;
|
||||||
|
X = (Y / y) * x;
|
||||||
|
Z = (Y / y) * z;
|
||||||
|
|
||||||
|
// X, Y and Z input refer to a D65/2° standard illuminant.
|
||||||
|
// sR, sG and sB (standard RGB) output range = 0 ÷ 255
|
||||||
|
// convert XYZ to RGB - CIE XYZ to sRGB
|
||||||
|
if (addXYZScaling) {
|
||||||
|
X = X / 100.0f;
|
||||||
|
Y = Y / 100.0f;
|
||||||
|
Z = Z / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f);
|
||||||
|
g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f);
|
||||||
|
b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f);
|
||||||
|
|
||||||
|
// apply gamma 2.2 correction
|
||||||
|
r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f);
|
||||||
|
g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f);
|
||||||
|
b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f);
|
||||||
|
|
||||||
|
// Round off
|
||||||
|
r = clamp(r, 0, 1);
|
||||||
|
g = clamp(g, 0, 1);
|
||||||
|
b = clamp(b, 0, 1);
|
||||||
|
|
||||||
|
// these rgb values are in the range of 0 to 1, convert to limit of HW specific LED
|
||||||
|
rgb.r = (uint8_t)(r * 255);
|
||||||
|
rgb.g = (uint8_t)(g * 255);
|
||||||
|
rgb.b = (uint8_t)(b * 255);
|
||||||
|
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
espRgbColor_t rgb = {r, g, b};
|
||||||
|
return espRgbColorToXYColor(rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb) {
|
||||||
|
// convert RGB to xy color space
|
||||||
|
|
||||||
|
// https://www.easyrgb.com/en/math.php
|
||||||
|
// https://en.wikipedia.org/wiki/SRGB
|
||||||
|
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
|
||||||
|
|
||||||
|
espXyColor_t xy;
|
||||||
|
|
||||||
|
float r, g, b;
|
||||||
|
float X, Y, Z;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
r = ((float)rgb.r) / 255.0f;
|
||||||
|
g = ((float)rgb.g) / 255.0f;
|
||||||
|
b = ((float)rgb.b) / 255.0f;
|
||||||
|
|
||||||
|
// convert RGB to XYZ - sRGB to CIE XYZ
|
||||||
|
r = (r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / 1.055f, 2.4f));
|
||||||
|
g = (g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / 1.055f, 2.4f));
|
||||||
|
b = (b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / 1.055f, 2.4f));
|
||||||
|
|
||||||
|
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
||||||
|
X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
|
||||||
|
Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
|
||||||
|
Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
|
||||||
|
|
||||||
|
// sR, sG and sB (standard RGB) input range = 0 ÷ 255
|
||||||
|
// X, Y and Z output refer to a D65/2° standard illuminant.
|
||||||
|
X = r * 0.4124564f + g * 0.3575761f + b * 0.1804375f;
|
||||||
|
Y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f;
|
||||||
|
Z = r * 0.0193339f + g * 0.1191920f + b * 0.9503041f;
|
||||||
|
|
||||||
|
// Calculate xy values
|
||||||
|
x = X / (X + Y + Z);
|
||||||
|
y = Y / (X + Y + Z);
|
||||||
|
|
||||||
|
// convert to 0-65535 range
|
||||||
|
xy.x = (uint16_t)(x * 65535);
|
||||||
|
xy.y = (uint16_t)(y * 65535);
|
||||||
|
return xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
espRgbColor_t espCTToRgbColor(uint16_t ct) {
|
||||||
|
espCtColor_t ctColor = {ct};
|
||||||
|
return espCTColorToRgbColor(ctColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct) {
|
||||||
|
espRgbColor_t rgb = {0, 0, 0};
|
||||||
|
float r, g, b;
|
||||||
|
|
||||||
|
if (ct.ctMireds == 0) {
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
// Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
|
||||||
|
|
||||||
|
// Convert Mireds to centiKelvins. k = 1,000,000/mired
|
||||||
|
float ctCentiKelvin = 10000 / ct.ctMireds;
|
||||||
|
|
||||||
|
// Red
|
||||||
|
if (ctCentiKelvin <= 66) {
|
||||||
|
r = 255;
|
||||||
|
} else {
|
||||||
|
r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Green
|
||||||
|
if (ctCentiKelvin <= 66) {
|
||||||
|
g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
|
||||||
|
} else {
|
||||||
|
g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blue
|
||||||
|
if (ctCentiKelvin >= 66) {
|
||||||
|
b = 255;
|
||||||
|
} else {
|
||||||
|
if (ctCentiKelvin <= 19) {
|
||||||
|
b = 0;
|
||||||
|
} else {
|
||||||
|
b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rgb.r = (uint8_t)clamp(r, 0, 255);
|
||||||
|
rgb.g = (uint8_t)clamp(g, 0, 255);
|
||||||
|
rgb.b = (uint8_t)clamp(b, 0, 255);
|
||||||
|
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
71
cores/esp32/ColorFormat.h
Normal file
71
cores/esp32/ColorFormat.h
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Project CHIP Authors
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct RgbColor_t {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HsvColor_t {
|
||||||
|
uint16_t h;
|
||||||
|
uint8_t s;
|
||||||
|
uint8_t v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XyColor_t {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CtColor_t {
|
||||||
|
uint16_t ctMireds;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RgbColor_t espRgbColor_t;
|
||||||
|
typedef struct HsvColor_t espHsvColor_t;
|
||||||
|
typedef struct XyColor_t espXyColor_t;
|
||||||
|
typedef struct CtColor_t espCtColor_t;
|
||||||
|
|
||||||
|
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y, bool addXYZScaling);
|
||||||
|
espRgbColor_t espXYColorToRgb(uint8_t Level, espXyColor_t xy);
|
||||||
|
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb);
|
||||||
|
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv);
|
||||||
|
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v);
|
||||||
|
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct);
|
||||||
|
espRgbColor_t espCTToRgbColor(uint16_t ct);
|
||||||
|
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb);
|
||||||
|
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
|
||||||
|
extern const espHsvColor_t HSV_BLACK, HSV_WHITE, HSV_RED, HSV_YELLOW, HSV_GREEN, HSV_CYAN, HSV_BLUE, HSV_MAGENTA;
|
||||||
|
extern const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE, DAYLIGHT_WHITE_COLOR_TEMPERATURE, WHITE_COLOR_TEMPERATURE, SOFT_WHITE_COLOR_TEMPERATURE,
|
||||||
|
WARM_WHITE_COLOR_TEMPERATURE;
|
||||||
|
extern const espRgbColor_t RGB_BLACK, RGB_WHITE, RGB_RED, RGB_YELLOW, RGB_GREEN, RGB_CYAN, RGB_BLUE, RGB_MAGENTA;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Esp.h"
|
#include "Esp.h"
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "spi_flash_mmap.h"
|
#include "spi_flash_mmap.h"
|
||||||
|
#include "esp_idf_version.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <soc/soc.h>
|
#include <soc/soc.h>
|
||||||
#include <esp_partition.h>
|
#include <esp_partition.h>
|
||||||
|
|
@ -35,11 +36,11 @@ extern "C" {
|
||||||
#include "esp_chip_info.h"
|
#include "esp_chip_info.h"
|
||||||
#include "esp_mac.h"
|
#include "esp_mac.h"
|
||||||
#include "esp_flash.h"
|
#include "esp_flash.h"
|
||||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||||
#include "esp32/rom/spi_flash.h"
|
#include "esp32/rom/spi_flash.h"
|
||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x1000 // Flash offset containing flash size and spi mode
|
#define ESP_FLASH_IMAGE_BASE 0x1000 // Flash offset containing flash size and spi mode
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/rom/spi_flash.h"
|
#include "esp32s2/rom/spi_flash.h"
|
||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
|
|
@ -47,23 +48,29 @@ extern "C" {
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32s3 is located at 0x0000
|
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32s3 is located at 0x0000
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
#include "esp32c2/rom/spi_flash.h"
|
#include "esp32c2/rom/spi_flash.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c2 is located at 0x0000
|
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c2 is located at 0x0000
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/spi_flash.h"
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c3 is located at 0x0000
|
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c3 is located at 0x0000
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
#include "esp32c6/rom/spi_flash.h"
|
#include "esp32c6/rom/spi_flash.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c6 is located at 0x0000
|
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c6 is located at 0x0000
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
#include "esp32h2/rom/spi_flash.h"
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000
|
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#include "esp32p4/rom/spi_flash.h"
|
||||||
|
#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32p4 is located at 0x2000
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
#include "esp32c5/rom/spi_flash.h"
|
||||||
|
#define ESP_FLASH_IMAGE_BASE 0x2000 // Esp32c5 is located at 0x2000
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
#else // ESP32 Before IDF 4.0
|
#else // ESP32 Before IDF 4.0
|
||||||
#include "rom/spi_flash.h"
|
#include "rom/spi_flash.h"
|
||||||
#define ESP_FLASH_IMAGE_BASE 0x1000
|
#define ESP_FLASH_IMAGE_BASE 0x1000
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -71,10 +78,11 @@ extern "C" {
|
||||||
// REG_SPI_BASE is not defined for S3/C3 ??
|
// REG_SPI_BASE is not defined for S3/C3 ??
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||||
#ifndef REG_SPI_BASE
|
#ifdef REG_SPI_BASE
|
||||||
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 )))
|
#undef REG_SPI_BASE
|
||||||
#endif // REG_SPI_BASE
|
#endif // REG_SPI_BASE
|
||||||
#endif // TARGET
|
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i) > 1) ? (((i) * 0x1000) + 0x20000) : (((~(i)) & 1) * 0x1000)))
|
||||||
|
#endif // TARGET
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User-defined Literals
|
* User-defined Literals
|
||||||
|
|
@ -83,323 +91,295 @@ extern "C" {
|
||||||
* uint32_t = test = 10_MHz; // --> 10000000
|
* uint32_t = test = 10_MHz; // --> 10000000
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned long long operator"" _kHz(unsigned long long x)
|
unsigned long long operator"" _kHz(unsigned long long x) {
|
||||||
{
|
return x * 1000;
|
||||||
return x * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _MHz(unsigned long long x)
|
unsigned long long operator"" _MHz(unsigned long long x) {
|
||||||
{
|
return x * 1000 * 1000;
|
||||||
return x * 1000 * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _GHz(unsigned long long x)
|
unsigned long long operator"" _GHz(unsigned long long x) {
|
||||||
{
|
return x * 1000 * 1000 * 1000;
|
||||||
return x * 1000 * 1000 * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _kBit(unsigned long long x)
|
unsigned long long operator"" _kBit(unsigned long long x) {
|
||||||
{
|
return x * 1024;
|
||||||
return x * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _MBit(unsigned long long x)
|
unsigned long long operator"" _MBit(unsigned long long x) {
|
||||||
{
|
return x * 1024 * 1024;
|
||||||
return x * 1024 * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _GBit(unsigned long long x)
|
unsigned long long operator"" _GBit(unsigned long long x) {
|
||||||
{
|
return x * 1024 * 1024 * 1024;
|
||||||
return x * 1024 * 1024 * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _kB(unsigned long long x)
|
unsigned long long operator"" _kB(unsigned long long x) {
|
||||||
{
|
return x * 1024;
|
||||||
return x * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _MB(unsigned long long x)
|
unsigned long long operator"" _MB(unsigned long long x) {
|
||||||
{
|
return x * 1024 * 1024;
|
||||||
return x * 1024 * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long operator"" _GB(unsigned long long x)
|
unsigned long long operator"" _GB(unsigned long long x) {
|
||||||
{
|
return x * 1024 * 1024 * 1024;
|
||||||
return x * 1024 * 1024 * 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EspClass ESP;
|
EspClass ESP;
|
||||||
|
|
||||||
void EspClass::deepSleep(uint64_t time_us)
|
void EspClass::deepSleep(uint64_t time_us) {
|
||||||
{
|
esp_deep_sleep(time_us);
|
||||||
esp_deep_sleep(time_us);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EspClass::restart(void)
|
void EspClass::restart(void) {
|
||||||
{
|
esp_restart();
|
||||||
esp_restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getHeapSize(void)
|
uint32_t EspClass::getHeapSize(void) {
|
||||||
{
|
return heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
|
||||||
return heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getFreeHeap(void)
|
uint32_t EspClass::getFreeHeap(void) {
|
||||||
{
|
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||||
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMinFreeHeap(void)
|
uint32_t EspClass::getMinFreeHeap(void) {
|
||||||
{
|
return heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
|
||||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMaxAllocHeap(void)
|
uint32_t EspClass::getMaxAllocHeap(void) {
|
||||||
{
|
return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
|
||||||
return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getPsramSize(void)
|
uint32_t EspClass::getPsramSize(void) {
|
||||||
{
|
if (psramFound()) {
|
||||||
if(psramFound()){
|
return heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
|
||||||
return heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
|
}
|
||||||
}
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getFreePsram(void)
|
uint32_t EspClass::getFreePsram(void) {
|
||||||
{
|
if (psramFound()) {
|
||||||
if(psramFound()){
|
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||||
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
}
|
||||||
}
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMinFreePsram(void)
|
uint32_t EspClass::getMinFreePsram(void) {
|
||||||
{
|
if (psramFound()) {
|
||||||
if(psramFound()){
|
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
||||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
}
|
||||||
}
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getMaxAllocPsram(void)
|
uint32_t EspClass::getMaxAllocPsram(void) {
|
||||||
{
|
if (psramFound()) {
|
||||||
if(psramFound()){
|
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
||||||
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
}
|
||||||
}
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t sketchSize(sketchSize_t response) {
|
static uint32_t sketchSize(sketchSize_t response) {
|
||||||
esp_image_metadata_t data;
|
esp_image_metadata_t data;
|
||||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
if (!running) return 0;
|
if (!running) {
|
||||||
const esp_partition_pos_t running_pos = {
|
return 0;
|
||||||
.offset = running->address,
|
}
|
||||||
.size = running->size,
|
const esp_partition_pos_t running_pos = {
|
||||||
};
|
.offset = running->address,
|
||||||
data.start_addr = running_pos.offset;
|
.size = running->size,
|
||||||
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
};
|
||||||
if (response) {
|
data.start_addr = running_pos.offset;
|
||||||
return running_pos.size - data.image_len;
|
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||||
} else {
|
if (response) {
|
||||||
return data.image_len;
|
return running_pos.size - data.image_len;
|
||||||
}
|
} else {
|
||||||
|
return data.image_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getSketchSize () {
|
uint32_t EspClass::getSketchSize() {
|
||||||
return sketchSize(SKETCH_SIZE_TOTAL);
|
return sketchSize(SKETCH_SIZE_TOTAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
String EspClass::getSketchMD5()
|
String EspClass::getSketchMD5() {
|
||||||
{
|
static String result;
|
||||||
static String result;
|
if (result.length()) {
|
||||||
if (result.length()) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
uint32_t lengthLeft = getSketchSize();
|
|
||||||
|
|
||||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
|
||||||
if (!running) {
|
|
||||||
log_e("Partition could not be found");
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t bufSize = SPI_FLASH_SEC_SIZE;
|
|
||||||
uint8_t *pb = (uint8_t *)malloc(bufSize);
|
|
||||||
if(!pb) {
|
|
||||||
log_e("Not enough memory to allocate buffer");
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
uint32_t offset = 0;
|
|
||||||
|
|
||||||
MD5Builder md5;
|
|
||||||
md5.begin();
|
|
||||||
while(lengthLeft > 0) {
|
|
||||||
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
|
|
||||||
if (!ESP.flashRead(running->address + offset, (uint32_t *)pb, (readBytes + 3) & ~3)) {
|
|
||||||
free(pb);
|
|
||||||
log_e("Could not read buffer from flash");
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
md5.add(pb, readBytes);
|
|
||||||
lengthLeft -= readBytes;
|
|
||||||
offset += readBytes;
|
|
||||||
|
|
||||||
#if CONFIG_FREERTOS_UNICORE
|
|
||||||
delay(1); // Fix solo WDT
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
free(pb);
|
|
||||||
md5.calculate();
|
|
||||||
result = md5.toString();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
uint32_t lengthLeft = getSketchSize();
|
||||||
|
|
||||||
uint32_t EspClass::getFreeSketchSpace () {
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
|
if (!running) {
|
||||||
if(!_partition){
|
log_e("Partition could not be found");
|
||||||
return 0;
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t bufSize = SPI_FLASH_SEC_SIZE;
|
||||||
|
uint8_t *pb = (uint8_t *)malloc(bufSize);
|
||||||
|
if (!pb) {
|
||||||
|
log_e("Not enough memory to allocate buffer");
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
MD5Builder md5;
|
||||||
|
md5.begin();
|
||||||
|
while (lengthLeft > 0) {
|
||||||
|
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
|
||||||
|
if (!ESP.flashRead(running->address + offset, (uint32_t *)pb, (readBytes + 3) & ~3)) {
|
||||||
|
free(pb);
|
||||||
|
log_e("Could not read buffer from flash");
|
||||||
|
return String();
|
||||||
}
|
}
|
||||||
|
md5.add(pb, readBytes);
|
||||||
|
lengthLeft -= readBytes;
|
||||||
|
offset += readBytes;
|
||||||
|
|
||||||
return _partition->size;
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
|
delay(1); // Fix solo WDT
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
free(pb);
|
||||||
|
md5.calculate();
|
||||||
|
result = md5.toString();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t EspClass::getChipRevision(void)
|
uint32_t EspClass::getFreeSketchSpace() {
|
||||||
{
|
const esp_partition_t *_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
esp_chip_info_t chip_info;
|
if (!_partition) {
|
||||||
esp_chip_info(&chip_info);
|
return 0;
|
||||||
return chip_info.revision;
|
}
|
||||||
|
|
||||||
|
return _partition->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * EspClass::getChipModel(void)
|
uint16_t EspClass::getChipRevision(void) {
|
||||||
{
|
esp_chip_info_t chip_info;
|
||||||
|
esp_chip_info(&chip_info);
|
||||||
|
return chip_info.revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *EspClass::getChipModel(void) {
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_PACKAGE);
|
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_PACKAGE);
|
||||||
uint32_t pkg_ver = chip_ver & 0x7;
|
uint32_t pkg_ver = chip_ver & 0x7;
|
||||||
switch (pkg_ver) {
|
switch (pkg_ver) {
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 :
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6:
|
||||||
if (getChipRevision() == 3)
|
if ((getChipRevision() / 100) == 3) {
|
||||||
return "ESP32-D0WDQ6-V3";
|
return "ESP32-D0WDQ6-V3";
|
||||||
else
|
} else {
|
||||||
return "ESP32-D0WDQ6";
|
return "ESP32-D0WDQ6";
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 :
|
}
|
||||||
if (getChipRevision() == 3)
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5:
|
||||||
return "ESP32-D0WD-V3";
|
if ((getChipRevision() / 100) == 3) {
|
||||||
else
|
return "ESP32-D0WD-V3";
|
||||||
return "ESP32-D0WD";
|
} else {
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 :
|
return "ESP32-D0WD";
|
||||||
return "ESP32-D2WD";
|
}
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 :
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5: return "ESP32-D2WD";
|
||||||
return "ESP32-PICO-D2";
|
case EFUSE_RD_CHIP_VER_PKG_ESP32U4WDH: return "ESP32-U4WDH";
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 :
|
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4: return "ESP32-PICO-D4";
|
||||||
return "ESP32-PICO-D4";
|
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302: return "ESP32-PICO-V3-02";
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302 :
|
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3: return "ESP32-D0WDR2-V3";
|
||||||
return "ESP32-PICO-V3-02";
|
default: return "Unknown";
|
||||||
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3 :
|
}
|
||||||
return "ESP32-D0WDR2-V3";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
|
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
|
||||||
switch (pkg_ver) {
|
switch (pkg_ver) {
|
||||||
case 0:
|
case 0: return "ESP32-S2";
|
||||||
return "ESP32-S2";
|
case 1: return "ESP32-S2FH16";
|
||||||
case 1:
|
case 2: return "ESP32-S2FH32";
|
||||||
return "ESP32-S2FH16";
|
default: return "ESP32-S2 (Unknown)";
|
||||||
case 2:
|
}
|
||||||
return "ESP32-S2FH32";
|
|
||||||
default:
|
|
||||||
return "ESP32-S2 (Unknown)";
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
esp_chip_info_t chip_info;
|
esp_chip_info_t chip_info;
|
||||||
esp_chip_info(&chip_info);
|
esp_chip_info(&chip_info);
|
||||||
switch(chip_info.model){
|
switch (chip_info.model) {
|
||||||
case CHIP_ESP32S3: return "ESP32-S3";
|
case CHIP_ESP32S3: return "ESP32-S3";
|
||||||
case CHIP_ESP32C3: return "ESP32-C3";
|
case CHIP_ESP32C3: return "ESP32-C3";
|
||||||
case CHIP_ESP32C2: return "ESP32-C2";
|
case CHIP_ESP32C2: return "ESP32-C2";
|
||||||
case CHIP_ESP32C6: return "ESP32-C6";
|
case CHIP_ESP32C6: return "ESP32-C6";
|
||||||
case CHIP_ESP32H2: return "ESP32-H2";
|
case CHIP_ESP32H2: return "ESP32-H2";
|
||||||
default: return "UNKNOWN";
|
case CHIP_ESP32P4: return "ESP32-P4";
|
||||||
}
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
|
||||||
|
case CHIP_ESP32C5: return "ESP32-C5";
|
||||||
|
case CHIP_ESP32C61: return "ESP32-C61";
|
||||||
|
case CHIP_ESP32H21: return "ESP32-H21";
|
||||||
|
#endif
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t EspClass::getChipCores(void)
|
uint8_t EspClass::getChipCores(void) {
|
||||||
{
|
esp_chip_info_t chip_info;
|
||||||
esp_chip_info_t chip_info;
|
esp_chip_info(&chip_info);
|
||||||
esp_chip_info(&chip_info);
|
return chip_info.cores;
|
||||||
return chip_info.cores;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * EspClass::getSdkVersion(void)
|
const char *EspClass::getSdkVersion(void) {
|
||||||
{
|
return esp_get_idf_version();
|
||||||
return esp_get_idf_version();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * EspClass::getCoreVersion(void)
|
const char *EspClass::getCoreVersion(void) {
|
||||||
{
|
return ESP_ARDUINO_VERSION_STR;
|
||||||
return ESP_ARDUINO_VERSION_STR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ESP_getFlashChipId(void)
|
uint32_t ESP_getFlashChipId(void) {
|
||||||
{
|
|
||||||
uint32_t id = g_rom_flashchip.device_id;
|
uint32_t id = g_rom_flashchip.device_id;
|
||||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getFlashChipSize(void)
|
uint32_t EspClass::getFlashChipSize(void) {
|
||||||
{
|
|
||||||
uint32_t id = (ESP_getFlashChipId() >> 16) & 0xFF;
|
uint32_t id = (ESP_getFlashChipId() >> 16) & 0xFF;
|
||||||
return 2 << (id - 1);
|
return 2 << (id - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::getFlashChipSpeed(void)
|
uint32_t EspClass::getFlashChipSpeed(void) {
|
||||||
{
|
esp_image_header_t fhdr;
|
||||||
esp_image_header_t fhdr;
|
if (esp_flash_read(esp_flash_default_chip, (void *)&fhdr, ESP_FLASH_IMAGE_BASE, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
|
||||||
if(esp_flash_read(esp_flash_default_chip, (void*)&fhdr, ESP_FLASH_IMAGE_BASE, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
return magicFlashChipSpeed(fhdr.spi_speed);
|
||||||
return magicFlashChipSpeed(fhdr.spi_speed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FlashMode_t EspClass::getFlashChipMode(void)
|
// FIXME for P4
|
||||||
{
|
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
FlashMode_t EspClass::getFlashChipMode(void) {
|
||||||
uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL);
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
#else
|
uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL);
|
||||||
#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
|
#else
|
||||||
uint32_t spi_ctrl = REG_READ(DR_REG_SPI0_BASE + 0x8);
|
#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
|
||||||
#else
|
uint32_t spi_ctrl = REG_READ(DR_REG_SPI0_BASE + 0x8);
|
||||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
#else
|
||||||
#endif
|
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||||
#endif
|
#endif
|
||||||
/* Not all of the following constants are already defined in older versions of spi_reg.h, so do it manually for now*/
|
#endif
|
||||||
if (spi_ctrl & BIT(24)) { //SPI_FREAD_QIO
|
/* Not all of the following constants are already defined in older versions of spi_reg.h, so do it manually for now*/
|
||||||
return (FM_QIO);
|
if (spi_ctrl & BIT(24)) { //SPI_FREAD_QIO
|
||||||
} else if (spi_ctrl & BIT(20)) { //SPI_FREAD_QUAD
|
return (FM_QIO);
|
||||||
return (FM_QOUT);
|
} else if (spi_ctrl & BIT(20)) { //SPI_FREAD_QUAD
|
||||||
} else if (spi_ctrl & BIT(23)) { //SPI_FREAD_DIO
|
return (FM_QOUT);
|
||||||
return (FM_DIO);
|
} else if (spi_ctrl & BIT(23)) { //SPI_FREAD_DIO
|
||||||
} else if (spi_ctrl & BIT(14)) { // SPI_FREAD_DUAL
|
return (FM_DIO);
|
||||||
return (FM_DOUT);
|
} else if (spi_ctrl & BIT(14)) { // SPI_FREAD_DUAL
|
||||||
} else if (spi_ctrl & BIT(13)) { //SPI_FASTRD_MODE
|
return (FM_DOUT);
|
||||||
return (FM_FAST_READ);
|
} else if (spi_ctrl & BIT(13)) { //SPI_FASTRD_MODE
|
||||||
} else {
|
return (FM_FAST_READ);
|
||||||
return (FM_SLOW_READ);
|
} else {
|
||||||
}
|
return (FM_SLOW_READ);
|
||||||
return (FM_DOUT);
|
}
|
||||||
|
return (FM_DOUT);
|
||||||
}
|
}
|
||||||
|
#endif // if !defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||||
|
|
||||||
uint32_t EspClass::magicFlashChipSize(uint8_t byte)
|
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
|
||||||
{
|
/*
|
||||||
/*
|
|
||||||
FLASH_SIZES = {
|
FLASH_SIZES = {
|
||||||
"1MB": 0x00,
|
"1MB": 0x00,
|
||||||
"2MB": 0x10,
|
"2MB": 0x10,
|
||||||
|
|
@ -411,24 +391,23 @@ uint32_t EspClass::magicFlashChipSize(uint8_t byte)
|
||||||
"128MB": 0x70,
|
"128MB": 0x70,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch(byte & 0x0F) {
|
switch (byte & 0x0F) {
|
||||||
case 0x0: return (1_MB); // 8 MBit (1MB)
|
case 0x0: return (1_MB); // 8 MBit (1MB)
|
||||||
case 0x1: return (2_MB); // 16 MBit (2MB)
|
case 0x1: return (2_MB); // 16 MBit (2MB)
|
||||||
case 0x2: return (4_MB); // 32 MBit (4MB)
|
case 0x2: return (4_MB); // 32 MBit (4MB)
|
||||||
case 0x3: return (8_MB); // 64 MBit (8MB)
|
case 0x3: return (8_MB); // 64 MBit (8MB)
|
||||||
case 0x4: return (16_MB); // 128 MBit (16MB)
|
case 0x4: return (16_MB); // 128 MBit (16MB)
|
||||||
case 0x5: return (32_MB); // 256 MBit (32MB)
|
case 0x5: return (32_MB); // 256 MBit (32MB)
|
||||||
case 0x6: return (64_MB); // 512 MBit (64MB)
|
case 0x6: return (64_MB); // 512 MBit (64MB)
|
||||||
case 0x7: return (128_MB); // 1 GBit (128MB)
|
case 0x7: return (128_MB); // 1 GBit (128MB)
|
||||||
default: // fail?
|
default: // fail?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
|
uint32_t EspClass::magicFlashChipSpeed(uint8_t byte) {
|
||||||
{
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C2
|
#if CONFIG_IDF_TARGET_ESP32C2
|
||||||
/*
|
/*
|
||||||
FLASH_FREQUENCY = {
|
FLASH_FREQUENCY = {
|
||||||
"60m": 0xF,
|
"60m": 0xF,
|
||||||
"30m": 0x0,
|
"30m": 0x0,
|
||||||
|
|
@ -436,34 +415,33 @@ uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
|
||||||
"15m": 0x2,
|
"15m": 0x2,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch(byte & 0x0F) {
|
switch (byte & 0x0F) {
|
||||||
case 0xF: return (60_MHz);
|
case 0xF: return (60_MHz);
|
||||||
case 0x0: return (30_MHz);
|
case 0x0: return (30_MHz);
|
||||||
case 0x1: return (20_MHz);
|
case 0x1: return (20_MHz);
|
||||||
case 0x2: return (15_MHz);
|
case 0x2: return (15_MHz);
|
||||||
default: // fail?
|
default: // fail?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
/*
|
/*
|
||||||
FLASH_FREQUENCY = {
|
FLASH_FREQUENCY = {
|
||||||
"80m": 0x0, # workaround for wrong mspi HS div value in ROM
|
"80m": 0x0, # workaround for wrong mspi HS div value in ROM
|
||||||
"40m": 0x0,
|
"40m": 0x0,
|
||||||
"20m": 0x2,
|
"20m": 0x2,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch(byte & 0x0F) {
|
switch (byte & 0x0F) {
|
||||||
case 0x0: return (80_MHz);
|
case 0x0: return (80_MHz);
|
||||||
case 0x2: return (20_MHz);
|
case 0x2: return (20_MHz);
|
||||||
default: // fail?
|
default: // fail?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FLASH_FREQUENCY = {
|
FLASH_FREQUENCY = {
|
||||||
"48m": 0xF,
|
"48m": 0xF,
|
||||||
"24m": 0x0,
|
"24m": 0x0,
|
||||||
|
|
@ -471,18 +449,17 @@ uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
|
||||||
"12m": 0x2,
|
"12m": 0x2,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch(byte & 0x0F) {
|
switch (byte & 0x0F) {
|
||||||
case 0xF: return (48_MHz);
|
case 0xF: return (48_MHz);
|
||||||
case 0x0: return (24_MHz);
|
case 0x0: return (24_MHz);
|
||||||
case 0x1: return (16_MHz);
|
case 0x1: return (16_MHz);
|
||||||
case 0x2: return (12_MHz);
|
case 0x2: return (12_MHz);
|
||||||
default: // fail?
|
default: // fail?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
FLASH_FREQUENCY = {
|
FLASH_FREQUENCY = {
|
||||||
"80m": 0xF,
|
"80m": 0xF,
|
||||||
"40m": 0x0,
|
"40m": 0x0,
|
||||||
|
|
@ -490,61 +467,52 @@ uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
|
||||||
"20m": 0x2,
|
"20m": 0x2,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch(byte & 0x0F) {
|
switch (byte & 0x0F) {
|
||||||
case 0xF: return (80_MHz);
|
case 0xF: return (80_MHz);
|
||||||
case 0x0: return (40_MHz);
|
case 0x0: return (40_MHz);
|
||||||
case 0x1: return (26_MHz);
|
case 0x1: return (26_MHz);
|
||||||
case 0x2: return (20_MHz);
|
case 0x2: return (20_MHz);
|
||||||
default: // fail?
|
default: // fail?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte) {
|
||||||
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
|
FlashMode_t mode = (FlashMode_t)byte;
|
||||||
{
|
if (mode > FM_SLOW_READ) {
|
||||||
FlashMode_t mode = (FlashMode_t) byte;
|
mode = FM_UNKNOWN;
|
||||||
if(mode > FM_SLOW_READ) {
|
}
|
||||||
mode = FM_UNKNOWN;
|
return mode;
|
||||||
}
|
|
||||||
return mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EspClass::flashEraseSector(uint32_t sector)
|
bool EspClass::flashEraseSector(uint32_t sector) {
|
||||||
{
|
return esp_flash_erase_region(esp_flash_default_chip, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE) == ESP_OK;
|
||||||
return esp_flash_erase_region(esp_flash_default_chip, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warning: These functions do not work with encrypted flash
|
// Warning: These functions do not work with encrypted flash
|
||||||
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size)
|
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) {
|
||||||
{
|
return esp_flash_write(esp_flash_default_chip, (const void *)data, offset, size) == ESP_OK;
|
||||||
return esp_flash_write(esp_flash_default_chip, (const void*) data, offset, size) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
|
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) {
|
||||||
{
|
return esp_flash_read(esp_flash_default_chip, (void *)data, offset, size) == ESP_OK;
|
||||||
return esp_flash_read(esp_flash_default_chip, (void*) data, offset, size) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EspClass::partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size)
|
bool EspClass::partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size) {
|
||||||
{
|
return esp_partition_erase_range(partition, offset, size) == ESP_OK;
|
||||||
return esp_partition_erase_range(partition, offset, size) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EspClass::partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
|
bool EspClass::partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) {
|
||||||
{
|
return esp_partition_write(partition, offset, data, size) == ESP_OK;
|
||||||
return esp_partition_write(partition, offset, data, size) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EspClass::partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
|
bool EspClass::partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) {
|
||||||
{
|
return esp_partition_read(partition, offset, data, size) == ESP_OK;
|
||||||
return esp_partition_read(partition, offset, data, size) == ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t EspClass::getEfuseMac(void)
|
uint64_t EspClass::getEfuseMac(void) {
|
||||||
{
|
uint64_t _chipmacid = 0LL;
|
||||||
uint64_t _chipmacid = 0LL;
|
esp_efuse_mac_get_default((uint8_t *)(&_chipmacid));
|
||||||
esp_efuse_mac_get_default((uint8_t*) (&_chipmacid));
|
return _chipmacid;
|
||||||
return _chipmacid;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,97 +26,95 @@
|
||||||
#include "esp_cpu.h"
|
#include "esp_cpu.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AVR macros for WDT managment
|
* AVR macros for WDT management
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WDTO_0MS = 0, //!< WDTO_0MS
|
WDTO_0MS = 0, //!< WDTO_0MS
|
||||||
WDTO_15MS = 15, //!< WDTO_15MS
|
WDTO_15MS = 15, //!< WDTO_15MS
|
||||||
WDTO_30MS = 30, //!< WDTO_30MS
|
WDTO_30MS = 30, //!< WDTO_30MS
|
||||||
WDTO_60MS = 60, //!< WDTO_60MS
|
WDTO_60MS = 60, //!< WDTO_60MS
|
||||||
WDTO_120MS = 120, //!< WDTO_120MS
|
WDTO_120MS = 120, //!< WDTO_120MS
|
||||||
WDTO_250MS = 250, //!< WDTO_250MS
|
WDTO_250MS = 250, //!< WDTO_250MS
|
||||||
WDTO_500MS = 500, //!< WDTO_500MS
|
WDTO_500MS = 500, //!< WDTO_500MS
|
||||||
WDTO_1S = 1000,//!< WDTO_1S
|
WDTO_1S = 1000, //!< WDTO_1S
|
||||||
WDTO_2S = 2000,//!< WDTO_2S
|
WDTO_2S = 2000, //!< WDTO_2S
|
||||||
WDTO_4S = 4000,//!< WDTO_4S
|
WDTO_4S = 4000, //!< WDTO_4S
|
||||||
WDTO_8S = 8000 //!< WDTO_8S
|
WDTO_8S = 8000 //!< WDTO_8S
|
||||||
} WDTO_t;
|
} WDTO_t;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FM_QIO = 0x00,
|
FM_QIO = 0x00,
|
||||||
FM_QOUT = 0x01,
|
FM_QOUT = 0x01,
|
||||||
FM_DIO = 0x02,
|
FM_DIO = 0x02,
|
||||||
FM_DOUT = 0x03,
|
FM_DOUT = 0x03,
|
||||||
FM_FAST_READ = 0x04,
|
FM_FAST_READ = 0x04,
|
||||||
FM_SLOW_READ = 0x05,
|
FM_SLOW_READ = 0x05,
|
||||||
FM_UNKNOWN = 0xff
|
FM_UNKNOWN = 0xff
|
||||||
} FlashMode_t;
|
} FlashMode_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SKETCH_SIZE_TOTAL = 0,
|
SKETCH_SIZE_TOTAL = 0,
|
||||||
SKETCH_SIZE_FREE = 1
|
SKETCH_SIZE_FREE = 1
|
||||||
} sketchSize_t;
|
} sketchSize_t;
|
||||||
|
|
||||||
class EspClass
|
class EspClass {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
EspClass() {}
|
EspClass() {}
|
||||||
~EspClass() {}
|
~EspClass() {}
|
||||||
void restart();
|
void restart();
|
||||||
|
|
||||||
//Internal RAM
|
//Internal RAM
|
||||||
uint32_t getHeapSize(); //total heap size
|
uint32_t getHeapSize(); //total heap size
|
||||||
uint32_t getFreeHeap(); //available heap
|
uint32_t getFreeHeap(); //available heap
|
||||||
uint32_t getMinFreeHeap(); //lowest level of free heap since boot
|
uint32_t getMinFreeHeap(); //lowest level of free heap since boot
|
||||||
uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once
|
uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once
|
||||||
|
|
||||||
//SPI RAM
|
//SPI RAM
|
||||||
uint32_t getPsramSize();
|
uint32_t getPsramSize();
|
||||||
uint32_t getFreePsram();
|
uint32_t getFreePsram();
|
||||||
uint32_t getMinFreePsram();
|
uint32_t getMinFreePsram();
|
||||||
uint32_t getMaxAllocPsram();
|
uint32_t getMaxAllocPsram();
|
||||||
|
|
||||||
uint16_t getChipRevision();
|
uint16_t getChipRevision();
|
||||||
const char * getChipModel();
|
const char *getChipModel();
|
||||||
uint8_t getChipCores();
|
uint8_t getChipCores();
|
||||||
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
|
uint32_t getCpuFreqMHz() {
|
||||||
inline uint32_t getCycleCount() __attribute__((always_inline));
|
return getCpuFrequencyMhz();
|
||||||
|
}
|
||||||
|
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||||
|
|
||||||
const char * getSdkVersion(); //version of ESP-IDF
|
const char *getSdkVersion(); //version of ESP-IDF
|
||||||
const char * getCoreVersion();//version of this core
|
const char *getCoreVersion(); //version of this core
|
||||||
|
|
||||||
void deepSleep(uint64_t time_us);
|
void deepSleep(uint64_t time_us);
|
||||||
|
|
||||||
uint32_t getFlashChipSize();
|
uint32_t getFlashChipSize();
|
||||||
uint32_t getFlashChipSpeed();
|
uint32_t getFlashChipSpeed();
|
||||||
FlashMode_t getFlashChipMode();
|
FlashMode_t getFlashChipMode();
|
||||||
|
|
||||||
uint32_t magicFlashChipSize(uint8_t byte);
|
uint32_t magicFlashChipSize(uint8_t byte);
|
||||||
uint32_t magicFlashChipSpeed(uint8_t byte);
|
uint32_t magicFlashChipSpeed(uint8_t byte);
|
||||||
FlashMode_t magicFlashChipMode(uint8_t byte);
|
FlashMode_t magicFlashChipMode(uint8_t byte);
|
||||||
|
|
||||||
uint32_t getSketchSize();
|
uint32_t getSketchSize();
|
||||||
String getSketchMD5();
|
String getSketchMD5();
|
||||||
uint32_t getFreeSketchSpace();
|
uint32_t getFreeSketchSpace();
|
||||||
|
|
||||||
bool flashEraseSector(uint32_t sector);
|
bool flashEraseSector(uint32_t sector);
|
||||||
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
|
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
|
||||||
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
|
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
|
||||||
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
|
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
|
||||||
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||||
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||||
|
|
||||||
uint64_t getEfuseMac();
|
|
||||||
|
|
||||||
|
uint64_t getEfuseMac();
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
|
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount() {
|
||||||
{
|
return (uint32_t)esp_cpu_get_cycle_count();
|
||||||
return (uint32_t)esp_cpu_get_cycle_count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern EspClass ESP;
|
extern EspClass ESP;
|
||||||
|
|
||||||
#endif //ESP_H
|
#endif //ESP_H
|
||||||
|
|
|
||||||
|
|
@ -19,22 +19,22 @@
|
||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
#include "esp_ota_ops.h"
|
#include "esp_ota_ops.h"
|
||||||
#include "esp_image_format.h"
|
#include "esp_image_format.h"
|
||||||
#include "esp32-hal.h"
|
|
||||||
#include "pins_arduino.h"
|
#include "pins_arduino.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
#include "firmware_msc_fat.h"
|
#include "firmware_msc_fat.h"
|
||||||
#include "spi_flash_mmap.h"
|
#include "spi_flash_mmap.h"
|
||||||
|
|
||||||
#ifndef USB_FW_MSC_VENDOR_ID
|
#ifndef USB_FW_MSC_VENDOR_ID
|
||||||
#define USB_FW_MSC_VENDOR_ID "ESP32" //max 8 chars
|
#define USB_FW_MSC_VENDOR_ID "ESP32" //max 8 chars
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_FW_MSC_PRODUCT_ID
|
#ifndef USB_FW_MSC_PRODUCT_ID
|
||||||
#define USB_FW_MSC_PRODUCT_ID "Firmware MSC"//max 16 chars
|
#define USB_FW_MSC_PRODUCT_ID "Firmware MSC" //max 16 chars
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_FW_MSC_PRODUCT_REVISION
|
#ifndef USB_FW_MSC_PRODUCT_REVISION
|
||||||
#define USB_FW_MSC_PRODUCT_REVISION "1.0" //max 4 chars
|
#define USB_FW_MSC_PRODUCT_REVISION "1.0" //max 4 chars
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_FW_MSC_VOLUME_NAME
|
#ifndef USB_FW_MSC_VOLUME_NAME
|
||||||
#define USB_FW_MSC_VOLUME_NAME "ESP32-FWMSC" //max 11 chars
|
#define USB_FW_MSC_VOLUME_NAME "ESP32-FWMSC" //max 11 chars
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_FW_MSC_SERIAL_NUMBER
|
#ifndef USB_FW_MSC_SERIAL_NUMBER
|
||||||
#define USB_FW_MSC_SERIAL_NUMBER 0x00000000
|
#define USB_FW_MSC_SERIAL_NUMBER 0x00000000
|
||||||
|
|
@ -45,19 +45,19 @@ esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id,
|
||||||
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
|
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
|
||||||
|
|
||||||
//General Variables
|
//General Variables
|
||||||
static uint8_t * msc_ram_disk = NULL;
|
static uint8_t *msc_ram_disk = NULL;
|
||||||
static fat_boot_sector_t * msc_boot = NULL;
|
static fat_boot_sector_t *msc_boot = NULL;
|
||||||
static uint8_t * msc_table = NULL;
|
static uint8_t *msc_table = NULL;
|
||||||
static uint16_t msc_table_sectors = 0;
|
static uint16_t msc_table_sectors = 0;
|
||||||
static uint16_t msc_total_sectors = 0;
|
static uint16_t msc_total_sectors = 0;
|
||||||
static bool mcs_is_fat16 = false;
|
static bool mcs_is_fat16 = false;
|
||||||
|
|
||||||
//Firmware Read
|
//Firmware Read
|
||||||
static const esp_partition_t* msc_run_partition = NULL;
|
static const esp_partition_t *msc_run_partition = NULL;
|
||||||
static uint16_t fw_start_sector = 0;
|
static uint16_t fw_start_sector = 0;
|
||||||
static uint16_t fw_end_sector = 0;
|
static uint16_t fw_end_sector = 0;
|
||||||
static size_t fw_size = 0;
|
static size_t fw_size = 0;
|
||||||
static fat_dir_entry_t * fw_entry = NULL;
|
static fat_dir_entry_t *fw_entry = NULL;
|
||||||
|
|
||||||
//Firmware Write
|
//Firmware Write
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -67,17 +67,17 @@ typedef enum {
|
||||||
MSC_UPDATE_END
|
MSC_UPDATE_END
|
||||||
} msc_update_state_t;
|
} msc_update_state_t;
|
||||||
|
|
||||||
static const esp_partition_t* msc_ota_partition = NULL;
|
static const esp_partition_t *msc_ota_partition = NULL;
|
||||||
static msc_update_state_t msc_update_state = MSC_UPDATE_IDLE;
|
static msc_update_state_t msc_update_state = MSC_UPDATE_IDLE;
|
||||||
static uint16_t msc_update_start_sector = 0;
|
static uint16_t msc_update_start_sector = 0;
|
||||||
static uint32_t msc_update_bytes_written = 0;
|
static uint32_t msc_update_bytes_written = 0;
|
||||||
static fat_dir_entry_t * msc_update_entry = NULL;
|
static fat_dir_entry_t *msc_update_entry = NULL;
|
||||||
|
|
||||||
static uint32_t get_firmware_size(const esp_partition_t* partition){
|
static uint32_t get_firmware_size(const esp_partition_t *partition) {
|
||||||
esp_image_metadata_t data;
|
esp_image_metadata_t data;
|
||||||
const esp_partition_pos_t running_pos = {
|
const esp_partition_pos_t running_pos = {
|
||||||
.offset = partition->address,
|
.offset = partition->address,
|
||||||
.size = partition->size,
|
.size = partition->size,
|
||||||
};
|
};
|
||||||
data.start_addr = running_pos.offset;
|
data.start_addr = running_pos.offset;
|
||||||
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||||
|
|
@ -85,19 +85,19 @@ static uint32_t get_firmware_size(const esp_partition_t* partition){
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get number of sectors required based on the size of the firmware and OTA partition
|
//Get number of sectors required based on the size of the firmware and OTA partition
|
||||||
static size_t msc_update_get_required_disk_sectors(){
|
static size_t msc_update_get_required_disk_sectors() {
|
||||||
size_t data_sectors = 16;
|
size_t data_sectors = 16;
|
||||||
size_t total_sectors = 0;
|
size_t total_sectors = 0;
|
||||||
msc_run_partition = esp_ota_get_running_partition();
|
msc_run_partition = esp_ota_get_running_partition();
|
||||||
msc_ota_partition = esp_ota_get_next_update_partition(NULL);
|
msc_ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
if(msc_run_partition){
|
if (msc_run_partition) {
|
||||||
fw_size = get_firmware_size(msc_run_partition);
|
fw_size = get_firmware_size(msc_run_partition);
|
||||||
data_sectors += FAT_SIZE_TO_SECTORS(fw_size);
|
data_sectors += FAT_SIZE_TO_SECTORS(fw_size);
|
||||||
log_d("APP size: %u (%u sectors)", fw_size, FAT_SIZE_TO_SECTORS(fw_size));
|
log_d("APP size: %u (%u sectors)", fw_size, FAT_SIZE_TO_SECTORS(fw_size));
|
||||||
} else {
|
} else {
|
||||||
log_w("APP partition not found. Reading disabled");
|
log_w("APP partition not found. Reading disabled");
|
||||||
}
|
}
|
||||||
if(msc_ota_partition){
|
if (msc_ota_partition) {
|
||||||
data_sectors += FAT_SIZE_TO_SECTORS(msc_ota_partition->size);
|
data_sectors += FAT_SIZE_TO_SECTORS(msc_ota_partition->size);
|
||||||
log_d("OTA size: %u (%u sectors)", msc_ota_partition->size, FAT_SIZE_TO_SECTORS(msc_ota_partition->size));
|
log_d("OTA size: %u (%u sectors)", msc_ota_partition->size, FAT_SIZE_TO_SECTORS(msc_ota_partition->size));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -105,7 +105,7 @@ static size_t msc_update_get_required_disk_sectors(){
|
||||||
}
|
}
|
||||||
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, false);
|
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, false);
|
||||||
total_sectors = data_sectors + msc_table_sectors + 2;
|
total_sectors = data_sectors + msc_table_sectors + 2;
|
||||||
if(total_sectors > 0xFF4){
|
if (total_sectors > 0xFF4) {
|
||||||
log_d("USING FAT16");
|
log_d("USING FAT16");
|
||||||
mcs_is_fat16 = true;
|
mcs_is_fat16 = true;
|
||||||
total_sectors -= msc_table_sectors;
|
total_sectors -= msc_table_sectors;
|
||||||
|
|
@ -123,11 +123,11 @@ static size_t msc_update_get_required_disk_sectors(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup the ramdisk and add the firmware download file
|
//setup the ramdisk and add the firmware download file
|
||||||
static bool msc_update_setup_disk(const char * volume_label, uint32_t serial_number){
|
static bool msc_update_setup_disk(const char *volume_label, uint32_t serial_number) {
|
||||||
msc_total_sectors = msc_update_get_required_disk_sectors();
|
msc_total_sectors = msc_update_get_required_disk_sectors();
|
||||||
uint8_t ram_sectors = msc_table_sectors + 2;
|
uint8_t ram_sectors = msc_table_sectors + 2;
|
||||||
msc_ram_disk = (uint8_t*)calloc(ram_sectors, DISK_SECTOR_SIZE);
|
msc_ram_disk = (uint8_t *)calloc(ram_sectors, DISK_SECTOR_SIZE);
|
||||||
if(!msc_ram_disk){
|
if (!msc_ram_disk) {
|
||||||
log_e("Failed to allocate RAM Disk: %u bytes", ram_sectors * DISK_SECTOR_SIZE);
|
log_e("Failed to allocate RAM Disk: %u bytes", ram_sectors * DISK_SECTOR_SIZE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -136,14 +136,14 @@ static bool msc_update_setup_disk(const char * volume_label, uint32_t serial_num
|
||||||
msc_boot = fat_add_boot_sector(msc_ram_disk, msc_total_sectors, msc_table_sectors, fat_file_system_type(mcs_is_fat16), volume_label, serial_number);
|
msc_boot = fat_add_boot_sector(msc_ram_disk, msc_total_sectors, msc_table_sectors, fat_file_system_type(mcs_is_fat16), volume_label, serial_number);
|
||||||
msc_table = fat_add_table(msc_ram_disk, msc_boot, mcs_is_fat16);
|
msc_table = fat_add_table(msc_ram_disk, msc_boot, mcs_is_fat16);
|
||||||
//fat_dir_entry_t * label = fat_add_label(msc_ram_disk, volume_label);
|
//fat_dir_entry_t * label = fat_add_label(msc_ram_disk, volume_label);
|
||||||
if(msc_run_partition){
|
if (msc_run_partition) {
|
||||||
fw_entry = fat_add_root_file(msc_ram_disk, 0, "FIRMWARE", "BIN", fw_size, 2, mcs_is_fat16);
|
fw_entry = fat_add_root_file(msc_ram_disk, 0, "FIRMWARE", "BIN", fw_size, 2, mcs_is_fat16);
|
||||||
fw_end_sector = FAT_SIZE_TO_SECTORS(fw_size) + fw_start_sector;
|
fw_end_sector = FAT_SIZE_TO_SECTORS(fw_size) + fw_start_sector;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msc_update_delete_disk(){
|
static void msc_update_delete_disk() {
|
||||||
fw_entry = NULL;
|
fw_entry = NULL;
|
||||||
fw_size = 0;
|
fw_size = 0;
|
||||||
fw_end_sector = 0;
|
fw_end_sector = 0;
|
||||||
|
|
@ -163,39 +163,39 @@ static void msc_update_delete_disk(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//filter out entries to only include BINs in the root folder
|
//filter out entries to only include BINs in the root folder
|
||||||
static fat_dir_entry_t * msc_update_get_root_bin_entry(uint8_t index){
|
static fat_dir_entry_t *msc_update_get_root_bin_entry(uint8_t index) {
|
||||||
fat_dir_entry_t * entry = (fat_dir_entry_t *)(msc_ram_disk + ((msc_boot->sectors_per_alloc_table+1) * DISK_SECTOR_SIZE) + (index * sizeof(fat_dir_entry_t)));
|
fat_dir_entry_t *entry = (fat_dir_entry_t *)(msc_ram_disk + ((msc_boot->sectors_per_alloc_table + 1) * DISK_SECTOR_SIZE) + (index * sizeof(fat_dir_entry_t)));
|
||||||
fat_lfn_entry_t * lfn = (fat_lfn_entry_t*)entry;
|
fat_lfn_entry_t *lfn = (fat_lfn_entry_t *)entry;
|
||||||
|
|
||||||
//empty entry
|
//empty entry
|
||||||
if(entry->file_magic == 0){
|
if (entry->file_magic == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//long file name
|
//long file name
|
||||||
if(lfn->attr == 0x0F && lfn->type == 0x00 && lfn->first_cluster == 0x0000){
|
if (lfn->attr == 0x0F && lfn->type == 0x00 && lfn->first_cluster == 0x0000) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//only files marked as archives
|
//only files marked as archives
|
||||||
if(entry->file_attr != FAT_FILE_ATTR_ARCHIVE){
|
if (entry->file_attr != FAT_FILE_ATTR_ARCHIVE) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//deleted
|
//deleted
|
||||||
if(entry->file_magic == 0xE5 || entry->file_magic == 0x05){
|
if (entry->file_magic == 0xE5 || entry->file_magic == 0x05) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//not bins
|
//not bins
|
||||||
if(memcmp("BIN", entry->file_extension, 3)){
|
if (memcmp("BIN", entry->file_extension, 3)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get an empty bin (the host will add an entry for file about to be written with size of zero)
|
//get an empty bin (the host will add an entry for file about to be written with size of zero)
|
||||||
static fat_dir_entry_t * msc_update_find_new_bin(){
|
static fat_dir_entry_t *msc_update_find_new_bin() {
|
||||||
for(uint8_t i=16; i;){
|
for (uint8_t i = 16; i;) {
|
||||||
i--;
|
i--;
|
||||||
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
|
fat_dir_entry_t *entry = msc_update_get_root_bin_entry(i);
|
||||||
if(entry && entry->file_size == 0){
|
if (entry && entry->file_size == 0) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,11 +203,11 @@ static fat_dir_entry_t * msc_update_find_new_bin(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//get a bin starting from particular sector
|
//get a bin starting from particular sector
|
||||||
static fat_dir_entry_t * msc_update_find_bin(uint16_t sector){
|
static fat_dir_entry_t *msc_update_find_bin(uint16_t sector) {
|
||||||
for(uint8_t i=16; i; ){
|
for (uint8_t i = 16; i;) {
|
||||||
i--;
|
i--;
|
||||||
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
|
fat_dir_entry_t *entry = msc_update_get_root_bin_entry(i);
|
||||||
if(entry && entry->data_start_sector == (sector - msc_boot->sectors_per_alloc_table)){
|
if (entry && entry->data_start_sector == (sector - msc_boot->sectors_per_alloc_table)) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -215,12 +215,12 @@ static fat_dir_entry_t * msc_update_find_bin(uint16_t sector){
|
||||||
}
|
}
|
||||||
|
|
||||||
//write the new data and erase the flash blocks when necessary
|
//write the new data and erase the flash blocks when necessary
|
||||||
static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t offset, void *data, size_t size){
|
static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t offset, void *data, size_t size) {
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
if((offset & (SPI_FLASH_SEC_SIZE-1)) == 0){
|
if ((offset & (SPI_FLASH_SEC_SIZE - 1)) == 0) {
|
||||||
err = esp_partition_erase_range(partition, offset, SPI_FLASH_SEC_SIZE);
|
err = esp_partition_erase_range(partition, offset, SPI_FLASH_SEC_SIZE);
|
||||||
log_v("ERASE[0x%08X]: %s", offset, (err != ESP_OK)?"FAIL":"OK");
|
log_v("ERASE[0x%08X]: %s", offset, (err != ESP_OK) ? "FAIL" : "OK");
|
||||||
if(err != ESP_OK){
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +228,7 @@ static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t off
|
||||||
}
|
}
|
||||||
|
|
||||||
//called when error was encountered while updating
|
//called when error was encountered while updating
|
||||||
static void msc_update_error(){
|
static void msc_update_error() {
|
||||||
log_e("UPDATE_ERROR: %u", msc_update_bytes_written);
|
log_e("UPDATE_ERROR: %u", msc_update_bytes_written);
|
||||||
arduino_firmware_msc_event_data_t p;
|
arduino_firmware_msc_event_data_t p;
|
||||||
p.error.size = msc_update_bytes_written;
|
p.error.size = msc_update_bytes_written;
|
||||||
|
|
@ -240,16 +240,16 @@ static void msc_update_error(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//called when all firmware bytes have been received
|
//called when all firmware bytes have been received
|
||||||
static void msc_update_end(){
|
static void msc_update_end() {
|
||||||
log_d("UPDATE_END: %u", msc_update_entry->file_size);
|
log_d("UPDATE_END: %u", msc_update_entry->file_size);
|
||||||
msc_update_state = MSC_UPDATE_END;
|
msc_update_state = MSC_UPDATE_END;
|
||||||
size_t ota_size = get_firmware_size(msc_ota_partition);
|
size_t ota_size = get_firmware_size(msc_ota_partition);
|
||||||
if(ota_size != msc_update_entry->file_size){
|
if (ota_size != msc_update_entry->file_size) {
|
||||||
log_e("OTA SIZE MISMATCH %u != %u", ota_size, msc_update_entry->file_size);
|
log_e("OTA SIZE MISMATCH %u != %u", ota_size, msc_update_entry->file_size);
|
||||||
msc_update_error();
|
msc_update_error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!ota_size || esp_ota_set_boot_partition(msc_ota_partition) != ESP_OK){
|
if (!ota_size || esp_ota_set_boot_partition(msc_ota_partition) != ESP_OK) {
|
||||||
log_e("ENABLING OTA PARTITION FAILED");
|
log_e("ENABLING OTA PARTITION FAILED");
|
||||||
msc_update_error();
|
msc_update_error();
|
||||||
return;
|
return;
|
||||||
|
|
@ -259,47 +259,47 @@ static void msc_update_end(){
|
||||||
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_END_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_END_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){
|
static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
|
||||||
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
||||||
if(lba < fw_start_sector){
|
if (lba < fw_start_sector) {
|
||||||
//write to sectors that are in RAM
|
//write to sectors that are in RAM
|
||||||
memcpy(msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, buffer, bufsize);
|
memcpy(msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, buffer, bufsize);
|
||||||
if(msc_ota_partition && lba == (fw_start_sector - 1)){
|
if (msc_ota_partition && lba == (fw_start_sector - 1)) {
|
||||||
//monitor the root folder table
|
//monitor the root folder table
|
||||||
if(msc_update_state <= MSC_UPDATE_RUNNING){
|
if (msc_update_state <= MSC_UPDATE_RUNNING) {
|
||||||
fat_dir_entry_t * update_entry = msc_update_find_new_bin();
|
fat_dir_entry_t *update_entry = msc_update_find_new_bin();
|
||||||
if(update_entry) {
|
if (update_entry) {
|
||||||
if(msc_update_entry) {
|
if (msc_update_entry) {
|
||||||
log_v("REPLACING ENTRY");
|
log_v("REPLACING ENTRY");
|
||||||
} else {
|
} else {
|
||||||
log_v("ASSIGNING ENTRY");
|
log_v("ASSIGNING ENTRY");
|
||||||
}
|
}
|
||||||
if(msc_update_state <= MSC_UPDATE_STARTING){
|
if (msc_update_state <= MSC_UPDATE_STARTING) {
|
||||||
msc_update_state = MSC_UPDATE_STARTING;
|
msc_update_state = MSC_UPDATE_STARTING;
|
||||||
msc_update_bytes_written = 0;
|
msc_update_bytes_written = 0;
|
||||||
msc_update_start_sector = 0;
|
msc_update_start_sector = 0;
|
||||||
}
|
}
|
||||||
msc_update_entry = update_entry;
|
msc_update_entry = update_entry;
|
||||||
} else if(msc_update_state == MSC_UPDATE_RUNNING){
|
} else if (msc_update_state == MSC_UPDATE_RUNNING) {
|
||||||
if(!msc_update_entry && msc_update_start_sector){
|
if (!msc_update_entry && msc_update_start_sector) {
|
||||||
msc_update_entry = msc_update_find_bin(msc_update_start_sector);
|
msc_update_entry = msc_update_find_bin(msc_update_start_sector);
|
||||||
}
|
}
|
||||||
if(msc_update_entry && msc_update_bytes_written >= msc_update_entry->file_size){
|
if (msc_update_entry && msc_update_bytes_written >= msc_update_entry->file_size) {
|
||||||
msc_update_end();
|
msc_update_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(msc_ota_partition && lba >= msc_update_start_sector){
|
} else if (msc_ota_partition && lba >= msc_update_start_sector) {
|
||||||
//handle writes to the region where the new firmware will be uploaded
|
//handle writes to the region where the new firmware will be uploaded
|
||||||
arduino_firmware_msc_event_data_t p;
|
arduino_firmware_msc_event_data_t p;
|
||||||
if(msc_update_state <= MSC_UPDATE_STARTING && buffer[0] == 0xE9){
|
if (msc_update_state <= MSC_UPDATE_STARTING && buffer[0] == 0xE9) {
|
||||||
msc_update_state = MSC_UPDATE_RUNNING;
|
msc_update_state = MSC_UPDATE_RUNNING;
|
||||||
msc_update_start_sector = lba;
|
msc_update_start_sector = lba;
|
||||||
msc_update_bytes_written = 0;
|
msc_update_bytes_written = 0;
|
||||||
log_d("UPDATE_START: %u (0x%02X)", lba, lba - msc_boot->sectors_per_alloc_table);
|
log_d("UPDATE_START: %u (0x%02X)", lba, lba - msc_boot->sectors_per_alloc_table);
|
||||||
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_START_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_START_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
|
if (msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK) {
|
||||||
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
||||||
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
||||||
|
|
@ -309,17 +309,18 @@ static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_
|
||||||
msc_update_error();
|
msc_update_error();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if(msc_update_state == MSC_UPDATE_RUNNING){
|
} else if (msc_update_state == MSC_UPDATE_RUNNING) {
|
||||||
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written < msc_update_entry->file_size && (msc_update_bytes_written + bufsize) >= msc_update_entry->file_size){
|
if (msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written < msc_update_entry->file_size
|
||||||
|
&& (msc_update_bytes_written + bufsize) >= msc_update_entry->file_size) {
|
||||||
bufsize = msc_update_entry->file_size - msc_update_bytes_written;
|
bufsize = msc_update_entry->file_size - msc_update_bytes_written;
|
||||||
}
|
}
|
||||||
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
|
if (msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK) {
|
||||||
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
|
||||||
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
|
||||||
p.write.size = bufsize;
|
p.write.size = bufsize;
|
||||||
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
|
||||||
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written >= msc_update_entry->file_size){
|
if (msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written >= msc_update_entry->file_size) {
|
||||||
msc_update_end();
|
msc_update_end();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -331,13 +332,13 @@ static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_
|
||||||
return bufsize;
|
return bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t msc_read(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){
|
static int32_t msc_read(uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
|
||||||
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
|
||||||
if(lba < fw_start_sector){
|
if (lba < fw_start_sector) {
|
||||||
memcpy(buffer, msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, bufsize);
|
memcpy(buffer, msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, bufsize);
|
||||||
} else if(msc_run_partition && lba < fw_end_sector){
|
} else if (msc_run_partition && lba < fw_end_sector) {
|
||||||
//read the currently running firmware
|
//read the currently running firmware
|
||||||
if(esp_partition_read(msc_run_partition, ((lba - fw_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) != ESP_OK){
|
if (esp_partition_read(msc_run_partition, ((lba - fw_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) != ESP_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -346,7 +347,7 @@ static int32_t msc_read(uint32_t lba, uint32_t offset, void* buffer, uint32_t bu
|
||||||
return bufsize;
|
return bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject){
|
static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject) {
|
||||||
//log_d("power: %u, start: %u, eject: %u", power_condition, start, load_eject);
|
//log_d("power: %u, start: %u, eject: %u", power_condition, start, load_eject);
|
||||||
arduino_firmware_msc_event_data_t p;
|
arduino_firmware_msc_event_data_t p;
|
||||||
p.power.power_condition = power_condition;
|
p.power.power_condition = power_condition;
|
||||||
|
|
@ -357,9 +358,9 @@ static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject)
|
||||||
}
|
}
|
||||||
|
|
||||||
static volatile TaskHandle_t msc_task_handle = NULL;
|
static volatile TaskHandle_t msc_task_handle = NULL;
|
||||||
static void msc_task(void *pvParameters){
|
static void msc_task(void *pvParameters) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if(msc_update_state == MSC_UPDATE_END){
|
if (msc_update_state == MSC_UPDATE_END) {
|
||||||
delay(100);
|
delay(100);
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
@ -369,24 +370,24 @@ static void msc_task(void *pvParameters){
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FirmwareMSC::FirmwareMSC():msc(){}
|
FirmwareMSC::FirmwareMSC() : msc() {}
|
||||||
|
|
||||||
FirmwareMSC::~FirmwareMSC(){
|
FirmwareMSC::~FirmwareMSC() {
|
||||||
end();
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirmwareMSC::begin(){
|
bool FirmwareMSC::begin() {
|
||||||
if(msc_ram_disk){
|
if (msc_ram_disk) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!msc_update_setup_disk(USB_FW_MSC_VOLUME_NAME, USB_FW_MSC_SERIAL_NUMBER)){
|
if (!msc_update_setup_disk(USB_FW_MSC_VOLUME_NAME, USB_FW_MSC_SERIAL_NUMBER)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!msc_task_handle){
|
if (!msc_task_handle) {
|
||||||
xTaskCreateUniversal(msc_task, "msc_disk", 1024, NULL, 2, (TaskHandle_t*)&msc_task_handle, 0);
|
xTaskCreateUniversal(msc_task, "msc_disk", 1024, NULL, 2, (TaskHandle_t *)&msc_task_handle, 0);
|
||||||
if(!msc_task_handle){
|
if (!msc_task_handle) {
|
||||||
msc_update_delete_disk();
|
msc_update_delete_disk();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -403,20 +404,20 @@ bool FirmwareMSC::begin(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirmwareMSC::end(){
|
void FirmwareMSC::end() {
|
||||||
msc.end();
|
msc.end();
|
||||||
if(msc_task_handle){
|
if (msc_task_handle) {
|
||||||
vTaskDelete(msc_task_handle);
|
vTaskDelete(msc_task_handle);
|
||||||
msc_task_handle = NULL;
|
msc_task_handle = NULL;
|
||||||
}
|
}
|
||||||
msc_update_delete_disk();
|
msc_update_delete_disk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirmwareMSC::onEvent(esp_event_handler_t callback){
|
void FirmwareMSC::onEvent(esp_event_handler_t callback) {
|
||||||
onEvent(ARDUINO_FIRMWARE_MSC_ANY_EVENT, callback);
|
onEvent(ARDUINO_FIRMWARE_MSC_ANY_EVENT, callback);
|
||||||
}
|
}
|
||||||
void FirmwareMSC::onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback){
|
void FirmwareMSC::onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback) {
|
||||||
arduino_usb_event_handler_register_with(ARDUINO_FIRMWARE_MSC_EVENTS, event, callback, this);
|
arduino_usb_event_handler_register_with(ARDUINO_FIRMWARE_MSC_EVENTS, event, callback, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINO_USB_MSC_ON_BOOT
|
#if ARDUINO_USB_MSC_ON_BOOT
|
||||||
|
|
|
||||||
|
|
@ -23,31 +23,31 @@
|
||||||
ESP_EVENT_DECLARE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
|
ESP_EVENT_DECLARE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ARDUINO_FIRMWARE_MSC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
ARDUINO_FIRMWARE_MSC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||||
ARDUINO_FIRMWARE_MSC_START_EVENT = 0,
|
ARDUINO_FIRMWARE_MSC_START_EVENT = 0,
|
||||||
ARDUINO_FIRMWARE_MSC_WRITE_EVENT,
|
ARDUINO_FIRMWARE_MSC_WRITE_EVENT,
|
||||||
ARDUINO_FIRMWARE_MSC_END_EVENT,
|
ARDUINO_FIRMWARE_MSC_END_EVENT,
|
||||||
ARDUINO_FIRMWARE_MSC_ERROR_EVENT,
|
ARDUINO_FIRMWARE_MSC_ERROR_EVENT,
|
||||||
ARDUINO_FIRMWARE_MSC_POWER_EVENT,
|
ARDUINO_FIRMWARE_MSC_POWER_EVENT,
|
||||||
ARDUINO_FIRMWARE_MSC_MAX_EVENT,
|
ARDUINO_FIRMWARE_MSC_MAX_EVENT,
|
||||||
} arduino_firmware_msc_event_t;
|
} arduino_firmware_msc_event_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
} write;
|
} write;
|
||||||
struct {
|
struct {
|
||||||
uint8_t power_condition;
|
uint8_t power_condition;
|
||||||
bool start;
|
bool start;
|
||||||
bool load_eject;
|
bool load_eject;
|
||||||
} power;
|
} power;
|
||||||
struct {
|
struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
} end;
|
} end;
|
||||||
struct {
|
struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
} error;
|
} error;
|
||||||
} arduino_firmware_msc_event_data_t;
|
} arduino_firmware_msc_event_data_t;
|
||||||
|
|
||||||
class FirmwareMSC {
|
class FirmwareMSC {
|
||||||
|
|
|
||||||
|
|
@ -9,36 +9,26 @@
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
typedef void (*voidFuncPtr)(void);
|
typedef void (*voidFuncPtr)(void);
|
||||||
typedef void (*voidFuncPtrArg)(void*);
|
typedef void (*voidFuncPtrArg)(void *);
|
||||||
|
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void *arg, int intr_type, bool functional);
|
||||||
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARDUINO_ISR_ATTR interruptFunctional(void* arg)
|
void ARDUINO_ISR_ATTR interruptFunctional(void *arg) {
|
||||||
{
|
InterruptArgStructure *localArg = (InterruptArgStructure *)arg;
|
||||||
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
|
if (localArg->interruptFunction) {
|
||||||
if (localArg->interruptFunction)
|
localArg->interruptFunction();
|
||||||
{
|
}
|
||||||
localArg->interruptFunction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
|
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode) {
|
||||||
{
|
// use the local interrupt routine which takes the ArgStructure as argument
|
||||||
// use the local interrupt routine which takes the ArgStructure as argument
|
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true);
|
||||||
__attachInterruptFunctionalArg (pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
void cleanupFunctional(void *arg) {
|
||||||
void cleanupFunctional(void* arg)
|
delete (InterruptArgStructure *)arg;
|
||||||
{
|
}
|
||||||
delete (InterruptArgStructure*)arg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct InterruptArgStructure {
|
struct InterruptArgStructure {
|
||||||
std::function<void(void)> interruptFunction;
|
std::function<void(void)> interruptFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The extra set of parentheses here prevents macros defined
|
// The extra set of parentheses here prevents macros defined
|
||||||
// in io_pin_remap.h from applying to this declaration.
|
// in io_pin_remap.h from applying to this declaration.
|
||||||
void (attachInterrupt)(uint8_t pin, std::function<void(void)> intRoutine, int mode);
|
void(attachInterrupt)(uint8_t pin, std::function<void(void)> intRoutine, int mode);
|
||||||
|
|
||||||
#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */
|
#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */
|
||||||
|
|
|
||||||
|
|
@ -20,52 +20,57 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HEXBuilder.h>
|
#include <HEXBuilder.h>
|
||||||
|
|
||||||
static uint8_t hex_char_to_byte(uint8_t c)
|
static uint8_t hex_char_to_byte(uint8_t c) {
|
||||||
{
|
return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa))
|
||||||
return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa)) :
|
: (c >= 'A' && c <= 'F') ? (c - ((uint8_t)'A' - 0xA))
|
||||||
(c >= 'A' && c <= 'F') ? (c - ((uint8_t)'A' - 0xA)) :
|
: (c >= '0' && c <= '9') ? (c - (uint8_t)'0')
|
||||||
(c >= '0' && c<= '9') ? (c - (uint8_t)'0') : 0x10; // unknown char is 16
|
: 0x10; // unknown char is 16
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HEXBuilder::hex2bytes(unsigned char * out, size_t maxlen, String &in) {
|
size_t HEXBuilder::hex2bytes(unsigned char *out, size_t maxlen, String &in) {
|
||||||
return hex2bytes(out, maxlen, in.c_str());
|
return hex2bytes(out, maxlen, in.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HEXBuilder::hex2bytes(unsigned char * out, size_t maxlen, const char * in) {
|
size_t HEXBuilder::hex2bytes(unsigned char *out, size_t maxlen, const char *in) {
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
for(;*in;in++) {
|
for (; *in; in++) {
|
||||||
uint8_t c = hex_char_to_byte(*in);
|
uint8_t c = hex_char_to_byte(*in);
|
||||||
// Silently skip anything unknown.
|
// Silently skip anything unknown.
|
||||||
if (c > 15)
|
if (c > 15) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (len & 1) {
|
|
||||||
if (len/2 < maxlen)
|
|
||||||
out[len/2] |= c;
|
|
||||||
} else {
|
|
||||||
if (len/2 < maxlen)
|
|
||||||
out[len/2] = c<<4;
|
|
||||||
}
|
|
||||||
len++;
|
|
||||||
}
|
}
|
||||||
return (len + 1)/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t HEXBuilder::bytes2hex(char * out, size_t maxlen, const unsigned char * in, size_t len) {
|
if (len & 1) {
|
||||||
for(size_t i = 0; i < len; i++) {
|
if (len / 2 < maxlen) {
|
||||||
if (i*2 + 1 < maxlen) {
|
out[len / 2] |= c;
|
||||||
sprintf(out + (i * 2), "%02x", in[i]);
|
}
|
||||||
}
|
} else {
|
||||||
|
if (len / 2 < maxlen) {
|
||||||
|
out[len / 2] = c << 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return len * 2 + 1;
|
len++;
|
||||||
|
}
|
||||||
|
return (len + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
String HEXBuilder::bytes2hex(const unsigned char * in, size_t len) {
|
size_t HEXBuilder::bytes2hex(char *out, size_t maxlen, const unsigned char *in, size_t len) {
|
||||||
size_t maxlen = len * 2 + 1;
|
for (size_t i = 0; i < len; i++) {
|
||||||
char * out = (char *) malloc(maxlen);
|
if (i * 2 + 1 < maxlen) {
|
||||||
if (!out) return String();
|
sprintf(out + (i * 2), "%02x", in[i]);
|
||||||
bytes2hex(out, maxlen, in, len);
|
}
|
||||||
String ret = String(out);
|
}
|
||||||
free(out);
|
return len * 2 + 1;
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
|
String HEXBuilder::bytes2hex(const unsigned char *in, size_t len) {
|
||||||
|
size_t maxlen = len * 2 + 1;
|
||||||
|
char *out = (char *)malloc(maxlen);
|
||||||
|
if (!out) {
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
bytes2hex(out, maxlen, in, len);
|
||||||
|
String ret = String(out);
|
||||||
|
free(out);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@
|
||||||
|
|
||||||
class HEXBuilder {
|
class HEXBuilder {
|
||||||
public:
|
public:
|
||||||
static size_t hex2bytes(unsigned char * out, size_t maxlen, String & in);
|
static size_t hex2bytes(unsigned char *out, size_t maxlen, String &in);
|
||||||
static size_t hex2bytes(unsigned char * out, size_t maxlen, const char * in);
|
static size_t hex2bytes(unsigned char *out, size_t maxlen, const char *in);
|
||||||
|
|
||||||
static String bytes2hex(const unsigned char * in, size_t len);
|
static String bytes2hex(const unsigned char *in, size_t len);
|
||||||
static size_t bytes2hex(char * out, size_t maxlen, const unsigned char * in, size_t len);
|
static size_t bytes2hex(char *out, size_t maxlen, const unsigned char *in, size_t len);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2015-2024 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "soc/usb_serial_jtag_struct.h"
|
||||||
#pragma GCC diagnostic ignored "-Wvolatile"
|
#pragma GCC diagnostic ignored "-Wvolatile"
|
||||||
#include "hal/usb_serial_jtag_ll.h"
|
#include "hal/usb_serial_jtag_ll.h"
|
||||||
#pragma GCC diagnostic warning "-Wvolatile"
|
#pragma GCC diagnostic warning "-Wvolatile"
|
||||||
|
|
@ -35,408 +36,577 @@ static RingbufHandle_t tx_ring_buf = NULL;
|
||||||
static QueueHandle_t rx_queue = NULL;
|
static QueueHandle_t rx_queue = NULL;
|
||||||
static uint8_t rx_data_buf[64] = {0};
|
static uint8_t rx_data_buf[64] = {0};
|
||||||
static intr_handle_t intr_handle = NULL;
|
static intr_handle_t intr_handle = NULL;
|
||||||
static volatile bool initial_empty = false;
|
|
||||||
static SemaphoreHandle_t tx_lock = NULL;
|
static SemaphoreHandle_t tx_lock = NULL;
|
||||||
|
static volatile bool connected = false;
|
||||||
|
|
||||||
// workaround for when USB CDC is not connected
|
// SOF in ISR causes problems for uploading firmware
|
||||||
static uint32_t tx_timeout_ms = 0;
|
//static volatile unsigned long lastSOF_ms;
|
||||||
static bool tx_timeout_change_request = false;
|
//static volatile uint8_t SOF_TIMEOUT;
|
||||||
|
|
||||||
|
// timeout has no effect when USB CDC is unplugged
|
||||||
|
static uint32_t tx_timeout_ms = 100;
|
||||||
|
|
||||||
static esp_event_loop_handle_t arduino_hw_cdc_event_loop_handle = NULL;
|
static esp_event_loop_handle_t arduino_hw_cdc_event_loop_handle = NULL;
|
||||||
|
|
||||||
static esp_err_t arduino_hw_cdc_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, BaseType_t *task_unblocked){
|
static esp_err_t
|
||||||
if(arduino_hw_cdc_event_loop_handle == NULL){
|
arduino_hw_cdc_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, BaseType_t *task_unblocked) {
|
||||||
return ESP_FAIL;
|
if (arduino_hw_cdc_event_loop_handle == NULL) {
|
||||||
}
|
return ESP_FAIL;
|
||||||
return esp_event_isr_post_to(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_data, event_data_size, task_unblocked);
|
}
|
||||||
|
return esp_event_isr_post_to(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_data, event_data_size, task_unblocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg){
|
static esp_err_t
|
||||||
if (!arduino_hw_cdc_event_loop_handle) {
|
arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg) {
|
||||||
esp_event_loop_args_t event_task_args = {
|
if (!arduino_hw_cdc_event_loop_handle) {
|
||||||
.queue_size = 5,
|
esp_event_loop_args_t event_task_args = {
|
||||||
.task_name = "arduino_hw_cdc_events",
|
.queue_size = 5, .task_name = "arduino_hw_cdc_events", .task_priority = 5, .task_stack_size = 2048, .task_core_id = tskNO_AFFINITY
|
||||||
.task_priority = 5,
|
};
|
||||||
.task_stack_size = 2048,
|
if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) {
|
||||||
.task_core_id = tskNO_AFFINITY
|
log_e("esp_event_loop_create failed");
|
||||||
};
|
|
||||||
if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) {
|
|
||||||
log_e("esp_event_loop_create failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(arduino_hw_cdc_event_loop_handle == NULL){
|
}
|
||||||
return ESP_FAIL;
|
if (arduino_hw_cdc_event_loop_handle == NULL) {
|
||||||
}
|
return ESP_FAIL;
|
||||||
return esp_event_handler_register_with(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
|
}
|
||||||
|
return esp_event_handler_register_with(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hw_cdc_isr_handler(void *arg) {
|
static void hw_cdc_isr_handler(void *arg) {
|
||||||
portBASE_TYPE xTaskWoken = 0;
|
portBASE_TYPE xTaskWoken = 0;
|
||||||
uint32_t usbjtag_intr_status = 0;
|
uint32_t usbjtag_intr_status = 0;
|
||||||
arduino_hw_cdc_event_data_t event = {0};
|
arduino_hw_cdc_event_data_t event = {0};
|
||||||
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
|
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
|
||||||
|
|
||||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
|
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
|
||||||
// Interrupt tells us the host picked up the data we sent.
|
// Interrupt tells us the host picked up the data we sent.
|
||||||
if (usb_serial_jtag_ll_txfifo_writable() == 1) {
|
if (!HWCDC::isPlugged()) {
|
||||||
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
|
connected = false;
|
||||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
if(!initial_empty){
|
// USB is unplugged, nothing to be done here
|
||||||
initial_empty = true;
|
return;
|
||||||
// First time USB is plugged and the application has not explicitly set TX Timeout, set it to default 100ms.
|
} else {
|
||||||
// Otherwise, USB is still unplugged and the timeout will be kept as Zero in order to avoid any delay in the
|
connected = true;
|
||||||
// application whenever it uses write() and the TX Queue gets full.
|
|
||||||
if (!tx_timeout_change_request) {
|
|
||||||
tx_timeout_ms = 100;
|
|
||||||
}
|
|
||||||
//send event?
|
|
||||||
//ets_printf("CONNECTED\n");
|
|
||||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_CONNECTED_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
|
||||||
}
|
|
||||||
size_t queued_size;
|
|
||||||
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64);
|
|
||||||
// If the hardware fifo is avaliable, write in it. Otherwise, do nothing.
|
|
||||||
if (queued_buff != NULL) { //Although tx_queued_bytes may be larger than 0. We may have interrupt before xRingbufferSend() was called.
|
|
||||||
//Copy the queued buffer into the TX FIFO
|
|
||||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
|
||||||
usb_serial_jtag_ll_write_txfifo(queued_buff, queued_size);
|
|
||||||
usb_serial_jtag_ll_txfifo_flush();
|
|
||||||
vRingbufferReturnItemFromISR(tx_ring_buf, queued_buff, &xTaskWoken);
|
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
|
||||||
//send event?
|
|
||||||
//ets_printf("TX:%u\n", queued_size);
|
|
||||||
event.tx.len = queued_size;
|
|
||||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_TX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (tx_ring_buf != NULL && usb_serial_jtag_ll_txfifo_writable() == 1) {
|
||||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
|
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
|
||||||
// read rx buffer(max length is 64), and send avaliable data to ringbuffer.
|
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
// Ensure the rx buffer size is larger than RX_MAX_SIZE.
|
size_t queued_size = 0;
|
||||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64);
|
||||||
uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(rx_data_buf, 64);
|
// If the hardware fifo is available, write in it. Otherwise, do nothing.
|
||||||
uint32_t i=0;
|
if (queued_buff != NULL) { //Although tx_queued_bytes may be larger than 0. We may have interrupt before xRingbufferSend() was called.
|
||||||
for(i=0; i<rx_fifo_len; i++){
|
//Copy the queued buffer into the TX FIFO
|
||||||
if(rx_queue == NULL || !xQueueSendFromISR(rx_queue, rx_data_buf+i, &xTaskWoken)){
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
break;
|
usb_serial_jtag_ll_write_txfifo(queued_buff, queued_size);
|
||||||
}
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
vRingbufferReturnItemFromISR(tx_ring_buf, queued_buff, &xTaskWoken);
|
||||||
|
if (connected) {
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
}
|
}
|
||||||
//send event?
|
//send event?
|
||||||
//ets_printf("RX:%u/%u\n", i, rx_fifo_len);
|
//ets_printf("TX:%u\n", queued_size);
|
||||||
event.rx.len = i;
|
event.tx.len = queued_size;
|
||||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_RX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_TX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
|
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
|
||||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_BUS_RESET);
|
// read rx buffer(max length is 64), and send available data to ringbuffer.
|
||||||
initial_empty = false;
|
// Ensure the rx buffer size is larger than RX_MAX_SIZE.
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||||
//ets_printf("BUS_RESET\n");
|
uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(rx_data_buf, 64);
|
||||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_BUS_RESET_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
uint32_t i = 0;
|
||||||
|
for (i = 0; i < rx_fifo_len; i++) {
|
||||||
|
if (rx_queue == NULL || !xQueueSendFromISR(rx_queue, rx_data_buf + i, &xTaskWoken)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
event.rx.len = i;
|
||||||
|
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_RX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (xTaskWoken == pdTRUE) {
|
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
|
||||||
portYIELD_FROM_ISR();
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_BUS_RESET);
|
||||||
|
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_BUS_RESET_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOF ISR is causing esptool to be unable to upload firmware to the board
|
||||||
|
// if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SOF) {
|
||||||
|
// usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF);
|
||||||
|
// lastSOF_ms = millis();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (xTaskWoken == pdTRUE) {
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moved to header file as inline function. Kept just as future reference.
|
||||||
|
//inline bool HWCDC::isPlugged(void) {
|
||||||
|
// SOF ISR is causing esptool to be unable to upload firmware to the board
|
||||||
|
// Timer test for SOF seems to work when uploading firmware
|
||||||
|
// return usb_serial_jtag_is_connected();//(lastSOF_ms + SOF_TIMEOUT) >= millis();
|
||||||
|
//}
|
||||||
|
|
||||||
|
bool HWCDC::isCDC_Connected() {
|
||||||
|
static bool running = false;
|
||||||
|
|
||||||
|
// USB may be unplugged
|
||||||
|
if (!isPlugged()) {
|
||||||
|
connected = false;
|
||||||
|
running = false;
|
||||||
|
// SOF in ISR causes problems for uploading firmware
|
||||||
|
//SOF_TIMEOUT = 5; // SOF timeout when unplugged
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//else {
|
||||||
|
// SOF_TIMEOUT = 50; // SOF timeout when plugged
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
running = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running == false && !connected) { // enables it only once!
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this will feed CDC TX FIFO to trigger IN_EMPTY
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
running = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flushTXBuffer(const uint8_t *buffer, size_t size) {
|
||||||
|
if (!tx_ring_buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UBaseType_t uxItemsWaiting = 0;
|
||||||
|
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||||
|
size_t freeSpace = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||||
|
size_t ringbufferLength = freeSpace + uxItemsWaiting;
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
// just flush the whole ring buffer and exit - used by HWCDC::flush()
|
||||||
|
size_t queued_size = 0;
|
||||||
|
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpTo(tx_ring_buf, &queued_size, 0, ringbufferLength);
|
||||||
|
if (queued_size && queued_buff != NULL) {
|
||||||
|
vRingbufferReturnItem(tx_ring_buf, (void *)queued_buff);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (size == 0) {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
if (freeSpace >= size) {
|
||||||
|
// there is enough space, just add the data to the ring buffer
|
||||||
|
if (xRingbufferSend(tx_ring_buf, (void *)buffer, size, 0) != pdTRUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// how many byte should be flushed to make space for the new data
|
||||||
|
size_t to_flush = size - freeSpace;
|
||||||
|
if (to_flush > ringbufferLength) {
|
||||||
|
to_flush = ringbufferLength;
|
||||||
|
}
|
||||||
|
size_t queued_size = 0;
|
||||||
|
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpTo(tx_ring_buf, &queued_size, 0, to_flush);
|
||||||
|
if (queued_size && queued_buff != NULL) {
|
||||||
|
vRingbufferReturnItem(tx_ring_buf, (void *)queued_buff);
|
||||||
|
}
|
||||||
|
// now add the new data that fits into the ring buffer
|
||||||
|
uint8_t *bptr = (uint8_t *)buffer;
|
||||||
|
if (size >= ringbufferLength) {
|
||||||
|
size = ringbufferLength;
|
||||||
|
bptr = (uint8_t *)buffer + (size - ringbufferLength);
|
||||||
|
}
|
||||||
|
if (xRingbufferSend(tx_ring_buf, (void *)bptr, size, 0) != pdTRUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// flushes CDC FIFO
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
|
static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
|
||||||
if(xPortInIsrContext()){
|
if (tx_ring_buf == NULL) {
|
||||||
xRingbufferSendFromISR(tx_ring_buf, (void*) (&c), 1, NULL);
|
return;
|
||||||
} else {
|
}
|
||||||
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, tx_timeout_ms / portTICK_PERIOD_MS);
|
if (!HWCDC::isConnected()) {
|
||||||
}
|
// just pop/push RingBuffer and apply FIFO policy
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
flushTXBuffer((const uint8_t *)&c, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (xPortInIsrContext()) {
|
||||||
|
xRingbufferSendFromISR(tx_ring_buf, (void *)(&c), 1, NULL);
|
||||||
|
} else {
|
||||||
|
xRingbufferSend(tx_ring_buf, (void *)(&c), 1, tx_timeout_ms / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWCDC::HWCDC() {
|
HWCDC::HWCDC() {
|
||||||
|
perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, HWCDC::deinit);
|
||||||
|
perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, HWCDC::deinit);
|
||||||
|
// SOF in ISR causes problems for uploading firmware
|
||||||
|
// lastSOF_ms = 0;
|
||||||
|
// SOF_TIMEOUT = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWCDC::~HWCDC(){
|
HWCDC::~HWCDC() {
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// It should return <true> just when USB is plugged and CDC is connected.
|
||||||
|
HWCDC::operator bool() const {
|
||||||
|
return HWCDC::isCDC_Connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWCDC::onEvent(esp_event_handler_t callback) {
|
||||||
|
onEvent(ARDUINO_HW_CDC_ANY_EVENT, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWCDC::onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback) {
|
||||||
|
arduino_hw_cdc_event_handler_register_with(ARDUINO_HW_CDC_EVENTS, event, callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HWCDC::deinit(void *busptr) {
|
||||||
|
// avoid any recursion issue with Peripheral Manager perimanSetPinBus() call
|
||||||
|
static bool running = false;
|
||||||
|
if (running) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
running = true;
|
||||||
|
// Setting USB D+ D- pins
|
||||||
|
bool retCode = true;
|
||||||
|
retCode &= perimanClearPinBus(USB_INT_PHY0_DM_GPIO_NUM);
|
||||||
|
retCode &= perimanClearPinBus(USB_INT_PHY0_DP_GPIO_NUM);
|
||||||
|
if (retCode) {
|
||||||
|
// Force the host to re-enumerate (BUS_RESET)
|
||||||
|
pinMode(USB_INT_PHY0_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
|
||||||
|
pinMode(USB_INT_PHY0_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
|
||||||
|
digitalWrite(USB_INT_PHY0_DM_GPIO_NUM, LOW);
|
||||||
|
digitalWrite(USB_INT_PHY0_DP_GPIO_NUM, LOW);
|
||||||
|
}
|
||||||
|
// release the flag
|
||||||
|
running = false;
|
||||||
|
return retCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWCDC::begin(unsigned long baud) {
|
||||||
|
if (tx_lock == NULL) {
|
||||||
|
tx_lock = xSemaphoreCreateMutex();
|
||||||
|
}
|
||||||
|
//RX Buffer default has 256 bytes if not preset
|
||||||
|
if (rx_queue == NULL) {
|
||||||
|
if (!setRxBufferSize(256)) {
|
||||||
|
log_e("HW CDC RX Buffer error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TX Buffer default has 256 bytes if not preset
|
||||||
|
if (tx_ring_buf == NULL) {
|
||||||
|
if (!setTxBufferSize(256)) {
|
||||||
|
log_e("HW CDC TX Buffer error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the HW Serial pins needs to be first deinited in order to allow `if(Serial)` to work :-(
|
||||||
|
// But this is also causing terminal to hang, so they are disabled
|
||||||
|
// deinit(NULL);
|
||||||
|
// delay(10); // USB Host has to enumerate it again
|
||||||
|
|
||||||
|
// Peripheral Manager setting for USB D+ D- pins
|
||||||
|
uint8_t pin = USB_INT_PHY0_DM_GPIO_NUM;
|
||||||
|
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DM, (void *)this, -1, -1)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
pin = USB_INT_PHY0_DP_GPIO_NUM;
|
||||||
|
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_USB_DP, (void *)this, -1, -1)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure PHY
|
||||||
|
// USB_Serial_JTAG use internal PHY
|
||||||
|
USB_SERIAL_JTAG.conf0.phy_sel = 0;
|
||||||
|
// Disable software control USB D+ D- pullup pulldown (Device FS: dp_pullup = 1)
|
||||||
|
USB_SERIAL_JTAG.conf0.pad_pull_override = 0;
|
||||||
|
// Enable USB D+ pullup
|
||||||
|
USB_SERIAL_JTAG.conf0.dp_pullup = 1;
|
||||||
|
// Enable USB pad function
|
||||||
|
USB_SERIAL_JTAG.conf0.usb_pad_enable = 1;
|
||||||
|
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
|
||||||
|
// SOF ISR is causing esptool to be unable to upload firmware to the board
|
||||||
|
// usb_serial_jtag_ll_ena_intr_mask(
|
||||||
|
// USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET | USB_SERIAL_JTAG_INTR_SOF
|
||||||
|
// );
|
||||||
|
if (!intr_handle && esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK) {
|
||||||
|
isr_log_e("HW USB CDC failed to init interrupts");
|
||||||
end();
|
end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
log_e("Serial JTAG Pin %u can't be set into Peripheral Manager.", pin);
|
||||||
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
HWCDC::operator bool() const
|
void HWCDC::end() {
|
||||||
{
|
//Disable/clear/free tx/rx interrupt.
|
||||||
return initial_empty;
|
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
||||||
|
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
||||||
|
esp_intr_free(intr_handle);
|
||||||
|
intr_handle = NULL;
|
||||||
|
if (tx_lock != NULL) {
|
||||||
|
vSemaphoreDelete(tx_lock);
|
||||||
|
tx_lock = NULL;
|
||||||
|
}
|
||||||
|
setRxBufferSize(0);
|
||||||
|
setTxBufferSize(0);
|
||||||
|
if (arduino_hw_cdc_event_loop_handle) {
|
||||||
|
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
|
||||||
|
arduino_hw_cdc_event_loop_handle = NULL;
|
||||||
|
}
|
||||||
|
HWCDC::deinit(this);
|
||||||
|
setDebugOutput(false);
|
||||||
|
connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWCDC::onEvent(esp_event_handler_t callback){
|
void HWCDC::setTxTimeoutMs(uint32_t timeout) {
|
||||||
onEvent(ARDUINO_HW_CDC_ANY_EVENT, callback);
|
tx_timeout_ms = timeout;
|
||||||
}
|
|
||||||
|
|
||||||
void HWCDC::onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback){
|
|
||||||
arduino_hw_cdc_event_handler_register_with(ARDUINO_HW_CDC_EVENTS, event, callback, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HWCDC::deinit(void * busptr)
|
|
||||||
{
|
|
||||||
// avoid any recursion issue with Peripheral Manager perimanSetPinBus() call
|
|
||||||
static bool running = false;
|
|
||||||
if (running) return true;
|
|
||||||
running = true;
|
|
||||||
// Setting USB D+ D- pins
|
|
||||||
bool retCode = true;
|
|
||||||
retCode &= perimanClearPinBus(USB_DM_GPIO_NUM);
|
|
||||||
retCode &= perimanClearPinBus(USB_DP_GPIO_NUM);
|
|
||||||
if (retCode) {
|
|
||||||
// Force the host to re-enumerate (BUS_RESET)
|
|
||||||
pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
|
|
||||||
pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
|
|
||||||
digitalWrite(USB_DM_GPIO_NUM, LOW);
|
|
||||||
digitalWrite(USB_DP_GPIO_NUM, LOW);
|
|
||||||
}
|
|
||||||
// release the flag
|
|
||||||
running = false;
|
|
||||||
return retCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HWCDC::begin(unsigned long baud)
|
|
||||||
{
|
|
||||||
if(tx_lock == NULL) {
|
|
||||||
tx_lock = xSemaphoreCreateMutex();
|
|
||||||
}
|
|
||||||
//RX Buffer default has 256 bytes if not preset
|
|
||||||
if(rx_queue == NULL) {
|
|
||||||
if (!setRxBufferSize(256)) {
|
|
||||||
log_e("HW CDC RX Buffer error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TX Buffer default has 256 bytes if not preset
|
|
||||||
if (tx_ring_buf == NULL) {
|
|
||||||
if (!setTxBufferSize(256)) {
|
|
||||||
log_e("HW CDC TX Buffer error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
|
||||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
|
|
||||||
if(!intr_handle && esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK){
|
|
||||||
isr_log_e("HW USB CDC failed to init interrupts");
|
|
||||||
end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, HWCDC::deinit) && perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, HWCDC::deinit)) {
|
|
||||||
// Setting USB D+ D- pins
|
|
||||||
perimanSetPinBus(USB_DM_GPIO_NUM, ESP32_BUS_TYPE_USB_DM, (void *) this, -1, -1);
|
|
||||||
perimanSetPinBus(USB_DP_GPIO_NUM, ESP32_BUS_TYPE_USB_DP, (void *) this, -1, -1);
|
|
||||||
} else {
|
|
||||||
log_e("Serial JTAG Pins can't be set into Peripheral Manager.");
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_serial_jtag_ll_txfifo_flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HWCDC::end()
|
|
||||||
{
|
|
||||||
//Disable tx/rx interrupt.
|
|
||||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
|
|
||||||
esp_intr_free(intr_handle);
|
|
||||||
intr_handle = NULL;
|
|
||||||
if(tx_lock != NULL) {
|
|
||||||
vSemaphoreDelete(tx_lock);
|
|
||||||
tx_lock = NULL;
|
|
||||||
}
|
|
||||||
setRxBufferSize(0);
|
|
||||||
setTxBufferSize(0);
|
|
||||||
if (arduino_hw_cdc_event_loop_handle) {
|
|
||||||
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
|
|
||||||
arduino_hw_cdc_event_loop_handle = NULL;
|
|
||||||
}
|
|
||||||
HWCDC::deinit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HWCDC::setTxTimeoutMs(uint32_t timeout){
|
|
||||||
tx_timeout_ms = timeout;
|
|
||||||
// it registers that the user has explicitly requested to use a value as TX timeout
|
|
||||||
// used for the workaround with unplugged USB and TX Queue Full that causes a delay on every write()
|
|
||||||
tx_timeout_change_request = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WRITING
|
* WRITING
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t HWCDC::setTxBufferSize(size_t tx_queue_len){
|
size_t HWCDC::setTxBufferSize(size_t tx_queue_len) {
|
||||||
if(tx_ring_buf){
|
if (tx_ring_buf) {
|
||||||
vRingbufferDelete(tx_ring_buf);
|
vRingbufferDelete(tx_ring_buf);
|
||||||
tx_ring_buf = NULL;
|
tx_ring_buf = NULL;
|
||||||
}
|
}
|
||||||
if(!tx_queue_len){
|
if (!tx_queue_len) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tx_ring_buf = xRingbufferCreate(tx_queue_len, RINGBUF_TYPE_BYTEBUF);
|
tx_ring_buf = xRingbufferCreate(tx_queue_len, RINGBUF_TYPE_BYTEBUF);
|
||||||
if(!tx_ring_buf){
|
if (!tx_ring_buf) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return tx_queue_len;
|
return tx_queue_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HWCDC::availableForWrite(void)
|
int HWCDC::availableForWrite(void) {
|
||||||
{
|
if (tx_ring_buf == NULL || tx_lock == NULL) {
|
||||||
if(tx_ring_buf == NULL || tx_lock == NULL){
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
size_t a = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||||
size_t a = xRingbufferGetCurFreeSize(tx_ring_buf);
|
xSemaphoreGive(tx_lock);
|
||||||
xSemaphoreGive(tx_lock);
|
return a;
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HWCDC::write(const uint8_t *buffer, size_t size)
|
size_t HWCDC::write(const uint8_t *buffer, size_t size) {
|
||||||
{
|
if (buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL) {
|
||||||
if(buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL){
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
if (!isCDC_Connected()) {
|
||||||
size_t max_size = xRingbufferGetMaxItemSize(tx_ring_buf);
|
// just pop/push RingBuffer and apply FIFO policy
|
||||||
|
flushTXBuffer(buffer, size);
|
||||||
|
} else {
|
||||||
size_t space = xRingbufferGetCurFreeSize(tx_ring_buf);
|
size_t space = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||||
size_t to_send = size, so_far = 0;
|
size_t to_send = size, so_far = 0;
|
||||||
|
|
||||||
if(space > size){
|
if (space > size) {
|
||||||
space = size;
|
space = size;
|
||||||
}
|
}
|
||||||
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||||
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), space, 0) != pdTRUE){
|
if (space > 0 && xRingbufferSend(tx_ring_buf, (void *)(buffer), space, 0) != pdTRUE) {
|
||||||
size = 0;
|
size = 0;
|
||||||
} else {
|
} else {
|
||||||
to_send -= space;
|
to_send -= space;
|
||||||
so_far += space;
|
so_far += space;
|
||||||
// Now trigger the ISR to read data from the ring buffer.
|
// Now trigger the ISR to read data from the ring buffer.
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
if (connected) {
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
|
}
|
||||||
while(to_send){
|
// tracks CDC transmission progress to avoid hanging if CDC is unplugged while still sending data
|
||||||
if(max_size > to_send){
|
size_t last_toSend = to_send;
|
||||||
max_size = to_send;
|
uint32_t tries = tx_timeout_ms; // waits 1ms per sending data attempt, in case CDC is unplugged
|
||||||
}
|
while (connected && to_send) {
|
||||||
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
space = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||||
if(xRingbufferSend(tx_ring_buf, (void*) (buffer+so_far), max_size, tx_timeout_ms / portTICK_PERIOD_MS) != pdTRUE){
|
if (space > to_send) {
|
||||||
size = so_far;
|
space = to_send;
|
||||||
break;
|
|
||||||
}
|
|
||||||
so_far += max_size;
|
|
||||||
to_send -= max_size;
|
|
||||||
// Now trigger the ISR to read data from the ring buffer.
|
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
|
||||||
}
|
}
|
||||||
|
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||||
|
if (xRingbufferSend(tx_ring_buf, (void *)(buffer + so_far), space, tx_timeout_ms / portTICK_PERIOD_MS) != pdTRUE) {
|
||||||
|
size = so_far;
|
||||||
|
log_w("write failed due to ring buffer full - timeout");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
so_far += space;
|
||||||
|
to_send -= space;
|
||||||
|
// Now trigger the ISR to read data from the ring buffer.
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
if (connected) {
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
|
}
|
||||||
|
if (last_toSend == to_send) {
|
||||||
|
// no progress in sending data... USB CDC is probably unplugged
|
||||||
|
tries--;
|
||||||
|
delay(1);
|
||||||
|
} else {
|
||||||
|
last_toSend = to_send;
|
||||||
|
tries = tx_timeout_ms; // reset the timeout
|
||||||
|
}
|
||||||
|
if (tries == 0) { // CDC isn't connected anymore...
|
||||||
|
size = so_far;
|
||||||
|
log_w("write failed due to waiting USB Host - timeout");
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive(tx_lock);
|
// CDC was disconnected while sending data ==> flush the TX buffer keeping the last data
|
||||||
return size;
|
if (to_send && !usb_serial_jtag_ll_txfifo_writable()) {
|
||||||
|
connected = false;
|
||||||
|
flushTXBuffer(buffer + so_far, to_send);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(tx_lock);
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HWCDC::write(uint8_t c)
|
size_t HWCDC::write(uint8_t c) {
|
||||||
{
|
return write(&c, 1);
|
||||||
return write(&c, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWCDC::flush(void)
|
void HWCDC::flush(void) {
|
||||||
{
|
if (tx_ring_buf == NULL || tx_lock == NULL) {
|
||||||
if(tx_ring_buf == NULL || tx_lock == NULL){
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (!isCDC_Connected()) {
|
||||||
|
flushTXBuffer(NULL, 0);
|
||||||
|
} else {
|
||||||
UBaseType_t uxItemsWaiting = 0;
|
UBaseType_t uxItemsWaiting = 0;
|
||||||
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||||
if(uxItemsWaiting){
|
if (uxItemsWaiting) {
|
||||||
// Now trigger the ISR to read data from the ring buffer.
|
// Now trigger the ISR to read data from the ring buffer.
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
if (connected) {
|
||||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while(uxItemsWaiting){
|
uint32_t tries = tx_timeout_ms; // waits 1ms per ISR sending data attempt, in case CDC is unplugged
|
||||||
delay(5);
|
while (connected && tries && uxItemsWaiting) {
|
||||||
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
delay(1);
|
||||||
|
UBaseType_t lastUxItemsWaiting = uxItemsWaiting;
|
||||||
|
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||||
|
if (lastUxItemsWaiting == uxItemsWaiting) {
|
||||||
|
tries--;
|
||||||
|
}
|
||||||
|
if (connected) {
|
||||||
|
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive(tx_lock);
|
if (tries == 0) { // CDC isn't connected anymore...
|
||||||
|
connected = false;
|
||||||
|
flushTXBuffer(NULL, 0); // flushes all TX Buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(tx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* READING
|
* READING
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t HWCDC::setRxBufferSize(size_t rx_queue_len){
|
size_t HWCDC::setRxBufferSize(size_t rx_queue_len) {
|
||||||
if(rx_queue){
|
if (rx_queue) {
|
||||||
vQueueDelete(rx_queue);
|
vQueueDelete(rx_queue);
|
||||||
rx_queue = NULL;
|
rx_queue = NULL;
|
||||||
}
|
}
|
||||||
if(!rx_queue_len){
|
if (!rx_queue_len) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
||||||
if(!rx_queue){
|
if (!rx_queue) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return rx_queue_len;
|
return rx_queue_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HWCDC::available(void)
|
int HWCDC::available(void) {
|
||||||
{
|
if (rx_queue == NULL) {
|
||||||
if(rx_queue == NULL){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return uxQueueMessagesWaiting(rx_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HWCDC::peek(void)
|
|
||||||
{
|
|
||||||
if(rx_queue == NULL){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uint8_t c;
|
|
||||||
if(xQueuePeek(rx_queue, &c, 0)) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
return uxQueueMessagesWaiting(rx_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HWCDC::read(void)
|
int HWCDC::peek(void) {
|
||||||
{
|
if (rx_queue == NULL) {
|
||||||
if(rx_queue == NULL){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uint8_t c = 0;
|
|
||||||
if(xQueueReceive(rx_queue, &c, 0)) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t c;
|
||||||
|
if (xQueuePeek(rx_queue, &c, 0)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HWCDC::read(uint8_t *buffer, size_t size)
|
int HWCDC::read(void) {
|
||||||
{
|
if (rx_queue == NULL) {
|
||||||
if(rx_queue == NULL){
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
uint8_t c = 0;
|
||||||
uint8_t c = 0;
|
if (xQueueReceive(rx_queue, &c, 0)) {
|
||||||
size_t count = 0;
|
return c;
|
||||||
while(count < size && xQueueReceive(rx_queue, &c, 0)){
|
}
|
||||||
buffer[count++] = c;
|
return -1;
|
||||||
}
|
}
|
||||||
return count;
|
|
||||||
|
size_t HWCDC::read(uint8_t *buffer, size_t size) {
|
||||||
|
if (rx_queue == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t c = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
while (count < size && xQueueReceive(rx_queue, &c, 0)) {
|
||||||
|
buffer[count++] = c;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DEBUG
|
* DEBUG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void HWCDC::setDebugOutput(bool en)
|
void HWCDC::setDebugOutput(bool en) {
|
||||||
{
|
if (en) {
|
||||||
if(en) {
|
uartSetDebug(NULL);
|
||||||
uartSetDebug(NULL);
|
ets_install_putc2((void (*)(char)) & cdc0_write_char);
|
||||||
ets_install_putc1((void (*)(char)) &cdc0_write_char);
|
} else {
|
||||||
} else {
|
ets_install_putc2(NULL);
|
||||||
ets_install_putc1(NULL);
|
}
|
||||||
}
|
ets_install_putc1(NULL); // closes UART log output
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINO_USB_MODE // Hardware JTAG CDC selected
|
#if ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Hardware JTAG CDC selected
|
||||||
// USBSerial is always available to be used
|
// USBSerial is always available to be used
|
||||||
HWCDC HWCDCSerial;
|
HWCDC HWCDCSerial;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2015-2024 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,88 +21,93 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
|
#include "driver/usb_serial_jtag.h"
|
||||||
|
|
||||||
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
|
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||||
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
|
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
|
||||||
ARDUINO_HW_CDC_BUS_RESET_EVENT,
|
ARDUINO_HW_CDC_BUS_RESET_EVENT,
|
||||||
ARDUINO_HW_CDC_RX_EVENT,
|
ARDUINO_HW_CDC_RX_EVENT,
|
||||||
ARDUINO_HW_CDC_TX_EVENT,
|
ARDUINO_HW_CDC_TX_EVENT,
|
||||||
ARDUINO_HW_CDC_MAX_EVENT,
|
ARDUINO_HW_CDC_MAX_EVENT,
|
||||||
} arduino_hw_cdc_event_t;
|
} arduino_hw_cdc_event_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
} rx;
|
} rx;
|
||||||
struct {
|
struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
} tx;
|
} tx;
|
||||||
} arduino_hw_cdc_event_data_t;
|
} arduino_hw_cdc_event_data_t;
|
||||||
|
|
||||||
class HWCDC: public Stream
|
class HWCDC : public Stream {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
static bool deinit(void * busptr);
|
static bool deinit(void *busptr);
|
||||||
|
static bool isCDC_Connected();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HWCDC();
|
HWCDC();
|
||||||
~HWCDC();
|
~HWCDC();
|
||||||
|
|
||||||
void onEvent(esp_event_handler_t callback);
|
void onEvent(esp_event_handler_t callback);
|
||||||
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
|
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
|
||||||
|
|
||||||
size_t setRxBufferSize(size_t);
|
size_t setRxBufferSize(size_t);
|
||||||
size_t setTxBufferSize(size_t);
|
size_t setTxBufferSize(size_t);
|
||||||
void setTxTimeoutMs(uint32_t timeout);
|
void setTxTimeoutMs(uint32_t timeout);
|
||||||
void begin(unsigned long baud=0);
|
void begin(unsigned long baud = 0);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
int available(void);
|
int available(void);
|
||||||
int availableForWrite(void);
|
int availableForWrite(void);
|
||||||
int peek(void);
|
int peek(void);
|
||||||
int read(void);
|
int read(void);
|
||||||
size_t read(uint8_t *buffer, size_t size);
|
size_t read(uint8_t *buffer, size_t size);
|
||||||
size_t write(uint8_t);
|
size_t write(uint8_t);
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
void flush(void);
|
void flush(void);
|
||||||
|
|
||||||
inline size_t read(char * buffer, size_t size)
|
inline static bool isPlugged(void) {
|
||||||
{
|
// SOF ISR is causing esptool to be unable to upload firmware to the board
|
||||||
return read((uint8_t*) buffer, size);
|
// Using IDF 5.1 helper function because it is based on Timer check instead of ISR
|
||||||
}
|
return usb_serial_jtag_is_connected();
|
||||||
inline size_t write(const char * buffer, size_t size)
|
}
|
||||||
{
|
|
||||||
return write((uint8_t*) buffer, size);
|
|
||||||
}
|
|
||||||
inline size_t write(const char * s)
|
|
||||||
{
|
|
||||||
return write((uint8_t*) s, strlen(s));
|
|
||||||
}
|
|
||||||
inline size_t write(unsigned long n)
|
|
||||||
{
|
|
||||||
return write((uint8_t) n);
|
|
||||||
}
|
|
||||||
inline size_t write(long n)
|
|
||||||
{
|
|
||||||
return write((uint8_t) n);
|
|
||||||
}
|
|
||||||
inline size_t write(unsigned int n)
|
|
||||||
{
|
|
||||||
return write((uint8_t) n);
|
|
||||||
}
|
|
||||||
inline size_t write(int n)
|
|
||||||
{
|
|
||||||
return write((uint8_t) n);
|
|
||||||
}
|
|
||||||
operator bool() const;
|
|
||||||
void setDebugOutput(bool);
|
|
||||||
uint32_t baudRate(){return 115200;}
|
|
||||||
|
|
||||||
|
inline static bool isConnected(void) {
|
||||||
|
return isCDC_Connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t read(char *buffer, size_t size) {
|
||||||
|
return read((uint8_t *)buffer, size);
|
||||||
|
}
|
||||||
|
inline size_t write(const char *buffer, size_t size) {
|
||||||
|
return write((uint8_t *)buffer, size);
|
||||||
|
}
|
||||||
|
inline size_t write(const char *s) {
|
||||||
|
return write((uint8_t *)s, strlen(s));
|
||||||
|
}
|
||||||
|
inline size_t write(unsigned long n) {
|
||||||
|
return write((uint8_t)n);
|
||||||
|
}
|
||||||
|
inline size_t write(long n) {
|
||||||
|
return write((uint8_t)n);
|
||||||
|
}
|
||||||
|
inline size_t write(unsigned int n) {
|
||||||
|
return write((uint8_t)n);
|
||||||
|
}
|
||||||
|
inline size_t write(int n) {
|
||||||
|
return write((uint8_t)n);
|
||||||
|
}
|
||||||
|
operator bool() const;
|
||||||
|
void setDebugOutput(bool);
|
||||||
|
uint32_t baudRate() {
|
||||||
|
return 115200;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#if ARDUINO_USB_MODE // Hardware JTAG CDC selected
|
#if ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Hardware JTAG CDC selected
|
||||||
#ifndef HWCDC_SERIAL_IS_DEFINED
|
#ifndef HWCDC_SERIAL_IS_DEFINED
|
||||||
#define HWCDC_SERIAL_IS_DEFINED 1
|
#define HWCDC_SERIAL_IS_DEFINED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -20,23 +20,24 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class HardwareI2C : public Stream
|
class HardwareI2C : public Stream {
|
||||||
{
|
public:
|
||||||
public:
|
virtual bool begin() = 0;
|
||||||
virtual bool begin() = 0;
|
virtual bool begin(uint8_t address) = 0;
|
||||||
virtual bool begin(uint8_t address) = 0;
|
virtual bool end() = 0;
|
||||||
virtual bool end() = 0;
|
|
||||||
|
|
||||||
virtual bool setClock(uint32_t freq) = 0;
|
virtual bool setClock(uint32_t freq) = 0;
|
||||||
|
|
||||||
virtual void beginTransmission(uint8_t address) = 0;
|
virtual void beginTransmission(uint8_t address) = 0;
|
||||||
virtual uint8_t endTransmission(bool stopBit) = 0;
|
virtual uint8_t endTransmission(bool stopBit) = 0;
|
||||||
virtual uint8_t endTransmission(void) = 0;
|
virtual uint8_t endTransmission(void) = 0;
|
||||||
|
|
||||||
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
|
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
|
||||||
virtual size_t requestFrom(uint8_t address, size_t len) = 0;
|
virtual size_t requestFrom(uint8_t address, size_t len) = 0;
|
||||||
|
|
||||||
virtual void onReceive(void(*)(int)) = 0;
|
// Update base class to use std::function
|
||||||
virtual void onRequest(void(*)(void)) = 0;
|
virtual void onReceive(const std::function<void(int)> &) = 0;
|
||||||
|
virtual void onRequest(const std::function<void()> &) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -58,55 +58,89 @@
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
enum SerialConfig {
|
enum SerialConfig {
|
||||||
SERIAL_5N1 = 0x8000010,
|
SERIAL_5N1 = 0x8000010,
|
||||||
SERIAL_6N1 = 0x8000014,
|
SERIAL_6N1 = 0x8000014,
|
||||||
SERIAL_7N1 = 0x8000018,
|
SERIAL_7N1 = 0x8000018,
|
||||||
SERIAL_8N1 = 0x800001c,
|
SERIAL_8N1 = 0x800001c,
|
||||||
SERIAL_5N2 = 0x8000030,
|
SERIAL_5N2 = 0x8000030,
|
||||||
SERIAL_6N2 = 0x8000034,
|
SERIAL_6N2 = 0x8000034,
|
||||||
SERIAL_7N2 = 0x8000038,
|
SERIAL_7N2 = 0x8000038,
|
||||||
SERIAL_8N2 = 0x800003c,
|
SERIAL_8N2 = 0x800003c,
|
||||||
SERIAL_5E1 = 0x8000012,
|
SERIAL_5E1 = 0x8000012,
|
||||||
SERIAL_6E1 = 0x8000016,
|
SERIAL_6E1 = 0x8000016,
|
||||||
SERIAL_7E1 = 0x800001a,
|
SERIAL_7E1 = 0x800001a,
|
||||||
SERIAL_8E1 = 0x800001e,
|
SERIAL_8E1 = 0x800001e,
|
||||||
SERIAL_5E2 = 0x8000032,
|
SERIAL_5E2 = 0x8000032,
|
||||||
SERIAL_6E2 = 0x8000036,
|
SERIAL_6E2 = 0x8000036,
|
||||||
SERIAL_7E2 = 0x800003a,
|
SERIAL_7E2 = 0x800003a,
|
||||||
SERIAL_8E2 = 0x800003e,
|
SERIAL_8E2 = 0x800003e,
|
||||||
SERIAL_5O1 = 0x8000013,
|
SERIAL_5O1 = 0x8000013,
|
||||||
SERIAL_6O1 = 0x8000017,
|
SERIAL_6O1 = 0x8000017,
|
||||||
SERIAL_7O1 = 0x800001b,
|
SERIAL_7O1 = 0x800001b,
|
||||||
SERIAL_8O1 = 0x800001f,
|
SERIAL_8O1 = 0x800001f,
|
||||||
SERIAL_5O2 = 0x8000033,
|
SERIAL_5O2 = 0x8000033,
|
||||||
SERIAL_6O2 = 0x8000037,
|
SERIAL_6O2 = 0x8000037,
|
||||||
SERIAL_7O2 = 0x800003b,
|
SERIAL_7O2 = 0x800003b,
|
||||||
SERIAL_8O2 = 0x800003f
|
SERIAL_8O2 = 0x800003f
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uart_mode_t SerialMode;
|
typedef uart_mode_t SerialMode;
|
||||||
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;
|
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_NO_ERROR,
|
UART_NO_ERROR,
|
||||||
UART_BREAK_ERROR,
|
UART_BREAK_ERROR,
|
||||||
UART_BUFFER_FULL_ERROR,
|
UART_BUFFER_FULL_ERROR,
|
||||||
UART_FIFO_OVF_ERROR,
|
UART_FIFO_OVF_ERROR,
|
||||||
UART_FRAME_ERROR,
|
UART_FRAME_ERROR,
|
||||||
UART_PARITY_ERROR
|
UART_PARITY_ERROR
|
||||||
} hardwareSerial_error_t;
|
} hardwareSerial_error_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UART_CLK_SRC_DEFAULT = UART_SCLK_DEFAULT,
|
||||||
|
#if SOC_UART_SUPPORT_APB_CLK
|
||||||
|
UART_CLK_SRC_APB = UART_SCLK_APB,
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_SUPPORT_PLL_F40M_CLK
|
||||||
|
UART_CLK_SRC_PLL = UART_SCLK_PLL_F40M,
|
||||||
|
#elif SOC_UART_SUPPORT_PLL_F80M_CLK
|
||||||
|
UART_CLK_SRC_PLL = UART_SCLK_PLL_F80M,
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
UART_CLK_SRC_PLL = UART_SCLK_PLL_F48M,
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_SUPPORT_XTAL_CLK
|
||||||
|
UART_CLK_SRC_XTAL = UART_SCLK_XTAL,
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_SUPPORT_RTC_CLK
|
||||||
|
UART_CLK_SRC_RTC = UART_SCLK_RTC,
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_SUPPORT_REF_TICK
|
||||||
|
UART_CLK_SRC_REF_TICK = UART_SCLK_REF_TICK,
|
||||||
|
#endif
|
||||||
|
} SerialClkSrc;
|
||||||
|
|
||||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
||||||
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
|
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
|
||||||
|
#else
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE CONFIG_ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
||||||
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES-1)
|
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
||||||
|
#else
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY CONFIG_ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||||
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
|
#ifndef CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
|
||||||
|
#else
|
||||||
|
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE CONFIG_ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// UART0 pins are defined by default by the bootloader.
|
// UART0 pins are defined by default by the bootloader.
|
||||||
|
|
@ -114,234 +148,265 @@ typedef enum {
|
||||||
// have changed and you know what you are doing.
|
// have changed and you know what you are doing.
|
||||||
|
|
||||||
#ifndef SOC_RX0
|
#ifndef SOC_RX0
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define SOC_RX0 (gpio_num_t)3
|
#define SOC_RX0 (gpio_num_t)3
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define SOC_RX0 (gpio_num_t)44
|
#define SOC_RX0 (gpio_num_t)44
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
#define SOC_RX0 (gpio_num_t)19
|
#define SOC_RX0 (gpio_num_t)19
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define SOC_RX0 (gpio_num_t)20
|
#define SOC_RX0 (gpio_num_t)20
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
#define SOC_RX0 (gpio_num_t)17
|
#define SOC_RX0 (gpio_num_t)17
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
#define SOC_RX0 (gpio_num_t)23
|
#define SOC_RX0 (gpio_num_t)23
|
||||||
#endif
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#define SOC_RX0 (gpio_num_t)38
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
#define SOC_RX0 (gpio_num_t)12
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SOC_TX0
|
#ifndef SOC_TX0
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define SOC_TX0 (gpio_num_t)1
|
#define SOC_TX0 (gpio_num_t)1
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define SOC_TX0 (gpio_num_t)43
|
#define SOC_TX0 (gpio_num_t)43
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
#define SOC_TX0 (gpio_num_t)20
|
#define SOC_TX0 (gpio_num_t)20
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define SOC_TX0 (gpio_num_t)21
|
#define SOC_TX0 (gpio_num_t)21
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
#define SOC_TX0 (gpio_num_t)16
|
#define SOC_TX0 (gpio_num_t)16
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
#define SOC_TX0 (gpio_num_t)24
|
#define SOC_TX0 (gpio_num_t)24
|
||||||
#endif
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#define SOC_TX0 (gpio_num_t)37
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
#define SOC_TX0 (gpio_num_t)11
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Default pins for UART1 are arbitrary, and defined here for convenience.
|
// Default pins for UART1 are arbitrary, and defined here for convenience.
|
||||||
|
|
||||||
#if SOC_UART_NUM > 1
|
#if SOC_UART_HP_NUM > 1
|
||||||
#ifndef RX1
|
#ifndef RX1
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define RX1 (gpio_num_t)26
|
#define RX1 (gpio_num_t)26
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#define RX1 (gpio_num_t)4
|
#define RX1 (gpio_num_t)4
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
#define RX1 (gpio_num_t)10
|
#define RX1 (gpio_num_t)10
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define RX1 (gpio_num_t)18
|
#define RX1 (gpio_num_t)18
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define RX1 (gpio_num_t)15
|
#define RX1 (gpio_num_t)15
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
#define RX1 (gpio_num_t)4
|
#define RX1 (gpio_num_t)4
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
#define RX1 (gpio_num_t)0
|
#define RX1 (gpio_num_t)0
|
||||||
#endif
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
#endif
|
#define RX1 (gpio_num_t)11
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
#define RX1 (gpio_num_t)4
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef TX1
|
#ifndef TX1
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define TX1 (gpio_num_t)27
|
#define TX1 (gpio_num_t)27
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
#define TX1 (gpio_num_t)5
|
#define TX1 (gpio_num_t)5
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
#define TX1 (gpio_num_t)18
|
#define TX1 (gpio_num_t)18
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define TX1 (gpio_num_t)19
|
#define TX1 (gpio_num_t)19
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define TX1 (gpio_num_t)16
|
#define TX1 (gpio_num_t)16
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
#define TX1 (gpio_num_t)5
|
#define TX1 (gpio_num_t)5
|
||||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
#define TX1 (gpio_num_t)1
|
#define TX1 (gpio_num_t)1
|
||||||
#endif
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
#endif
|
#define TX1 (gpio_num_t)10
|
||||||
#endif /* SOC_UART_NUM > 1 */
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
#define TX1 (gpio_num_t)5
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif /* SOC_UART_HP_NUM > 1 */
|
||||||
|
|
||||||
// Default pins for UART2 are arbitrary, and defined here for convenience.
|
// Default pins for UART2 are arbitrary, and defined here for convenience.
|
||||||
|
|
||||||
#if SOC_UART_NUM > 2
|
#if SOC_UART_HP_NUM > 2
|
||||||
#ifndef RX2
|
#ifndef RX2
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define RX2 (gpio_num_t)4
|
#define RX2 (gpio_num_t)4
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define RX2 (gpio_num_t)19
|
#define RX2 (gpio_num_t)19
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TX2
|
#ifndef TX2
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define TX2 (gpio_num_t)25
|
#define TX2 (gpio_num_t)25
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#define TX2 (gpio_num_t)20
|
#define TX2 (gpio_num_t)20
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif /* SOC_UART_NUM > 2 */
|
#endif /* SOC_UART_HP_NUM > 2 */
|
||||||
|
|
||||||
|
#if SOC_UART_LP_NUM >= 1
|
||||||
|
#ifndef LP_RX0
|
||||||
|
#define LP_RX0 (gpio_num_t) LP_U0RXD_GPIO_NUM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LP_TX0
|
||||||
|
#define LP_TX0 (gpio_num_t) LP_U0TXD_GPIO_NUM
|
||||||
|
#endif
|
||||||
|
#endif /* SOC_UART_LP_NUM >= 1 */
|
||||||
|
|
||||||
typedef std::function<void(void)> OnReceiveCb;
|
typedef std::function<void(void)> OnReceiveCb;
|
||||||
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
|
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
|
||||||
|
|
||||||
class HardwareSerial: public Stream
|
class HardwareSerial : public Stream {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
HardwareSerial(uint8_t uart_nr);
|
HardwareSerial(uint8_t uart_nr);
|
||||||
~HardwareSerial();
|
~HardwareSerial();
|
||||||
|
|
||||||
// setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
|
// setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
|
||||||
// param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
|
// param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
|
||||||
// Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
|
// Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
|
||||||
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
|
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
|
||||||
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
|
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
|
||||||
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
|
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
|
||||||
bool setRxTimeout(uint8_t symbols_timeout);
|
bool setRxTimeout(uint8_t symbols_timeout);
|
||||||
|
|
||||||
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
|
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
|
||||||
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
|
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
|
||||||
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
|
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
|
||||||
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
|
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
|
||||||
bool setRxFIFOFull(uint8_t fifoBytes);
|
bool setRxFIFOFull(uint8_t fifoBytes);
|
||||||
|
|
||||||
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
|
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
|
||||||
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
|
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
|
||||||
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
|
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbols by default in IDF)
|
||||||
// onlyOnTimeout parameter will define how onReceive will behave:
|
// onlyOnTimeout parameter will define how onReceive will behave:
|
||||||
// Default: true -- The callback will only be called when RX Timeout happens.
|
// Default: true -- The callback will only be called when RX Timeout happens.
|
||||||
// Whole stream of bytes will be ready for being read on the callback function at once.
|
// Whole stream of bytes will be ready for being read on the callback function at once.
|
||||||
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
|
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
|
||||||
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
|
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
|
||||||
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
|
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
|
||||||
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
|
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
|
||||||
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
|
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
|
||||||
|
|
||||||
// onReceive will be called on error events (see hardwareSerial_error_t)
|
// onReceive will be called on error events (see hardwareSerial_error_t)
|
||||||
void onReceiveError(OnReceiveErrorCb function);
|
void onReceiveError(OnReceiveErrorCb function);
|
||||||
|
|
||||||
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe usefull in some use cases
|
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe useful in some use cases
|
||||||
void eventQueueReset();
|
void eventQueueReset();
|
||||||
|
|
||||||
// When pins are changed, it will detach the previous ones
|
// When pins are changed, it will detach the previous ones
|
||||||
// if pin is negative, it won't be set/changed and will be kept as is
|
// if pin is negative, it won't be set/changed and will be kept as is
|
||||||
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
|
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
|
||||||
// invert will invert RX/TX polarity
|
// invert will invert RX/TX polarity
|
||||||
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
|
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
|
||||||
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
|
void begin(
|
||||||
void end(void);
|
unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL,
|
||||||
void updateBaudRate(unsigned long baud);
|
uint8_t rxfifo_full_thrhd = 120
|
||||||
int available(void);
|
);
|
||||||
int availableForWrite(void);
|
void end(void);
|
||||||
int peek(void);
|
void updateBaudRate(unsigned long baud);
|
||||||
int read(void);
|
int available(void);
|
||||||
size_t read(uint8_t *buffer, size_t size);
|
int availableForWrite(void);
|
||||||
inline size_t read(char * buffer, size_t size)
|
int peek(void);
|
||||||
{
|
int read(void);
|
||||||
return read((uint8_t*) buffer, size);
|
size_t read(uint8_t *buffer, size_t size);
|
||||||
}
|
inline size_t read(char *buffer, size_t size) {
|
||||||
// Overrides Stream::readBytes() to be faster using IDF
|
return read((uint8_t *)buffer, size);
|
||||||
size_t readBytes(uint8_t *buffer, size_t length);
|
}
|
||||||
size_t readBytes(char *buffer, size_t length)
|
// Overrides Stream::readBytes() to be faster using IDF
|
||||||
{
|
size_t readBytes(uint8_t *buffer, size_t length);
|
||||||
return readBytes((uint8_t *) buffer, length);
|
size_t readBytes(char *buffer, size_t length) {
|
||||||
}
|
return readBytes((uint8_t *)buffer, length);
|
||||||
void flush(void);
|
}
|
||||||
void flush( bool txOnly);
|
void flush(void);
|
||||||
size_t write(uint8_t);
|
void flush(bool txOnly);
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
size_t write(uint8_t);
|
||||||
inline size_t write(const char * buffer, size_t size)
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
{
|
inline size_t write(const char *buffer, size_t size) {
|
||||||
return write((uint8_t*) buffer, size);
|
return write((uint8_t *)buffer, size);
|
||||||
}
|
}
|
||||||
inline size_t write(const char * s)
|
inline size_t write(const char *s) {
|
||||||
{
|
return write((uint8_t *)s, strlen(s));
|
||||||
return write((uint8_t*) s, strlen(s));
|
}
|
||||||
}
|
inline size_t write(unsigned long n) {
|
||||||
inline size_t write(unsigned long n)
|
return write((uint8_t)n);
|
||||||
{
|
}
|
||||||
return write((uint8_t) n);
|
inline size_t write(long n) {
|
||||||
}
|
return write((uint8_t)n);
|
||||||
inline size_t write(long n)
|
}
|
||||||
{
|
inline size_t write(unsigned int n) {
|
||||||
return write((uint8_t) n);
|
return write((uint8_t)n);
|
||||||
}
|
}
|
||||||
inline size_t write(unsigned int n)
|
inline size_t write(int n) {
|
||||||
{
|
return write((uint8_t)n);
|
||||||
return write((uint8_t) n);
|
}
|
||||||
}
|
uint32_t baudRate();
|
||||||
inline size_t write(int n)
|
operator bool() const;
|
||||||
{
|
|
||||||
return write((uint8_t) n);
|
|
||||||
}
|
|
||||||
uint32_t baudRate();
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
void setDebugOutput(bool);
|
void setDebugOutput(bool);
|
||||||
|
|
||||||
void setRxInvert(bool);
|
void setRxInvert(bool);
|
||||||
|
|
||||||
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
|
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
|
||||||
// setPins() can be called after or before begin()
|
// setPins() can be called after or before begin()
|
||||||
// When pins are changed, it will detach the previous ones
|
// When pins are changed, it will detach the previous ones
|
||||||
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
|
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
|
||||||
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
|
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
|
||||||
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
|
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
|
||||||
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
|
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
|
||||||
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
|
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
|
||||||
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
|
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
|
||||||
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
|
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
|
||||||
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
|
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
|
||||||
// UART_MODE_UART = 0x00 mode: regular UART mode
|
// UART_MODE_UART = 0x00 mode: regular UART mode
|
||||||
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
|
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
|
||||||
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
|
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
|
||||||
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
|
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
|
||||||
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
|
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
|
||||||
bool setMode(SerialMode mode);
|
bool setMode(SerialMode mode);
|
||||||
size_t setRxBufferSize(size_t new_size);
|
// Used to set the UART clock source mode. It must be set before calling begin(), otherwise it won't have any effect.
|
||||||
size_t setTxBufferSize(size_t new_size);
|
// Not all clock source are available to every SoC. The compatible option are listed here:
|
||||||
|
// UART_CLK_SRC_DEFAULT :: any SoC - it will set whatever IDF defines as the default UART Clock Source
|
||||||
|
// UART_CLK_SRC_APB :: ESP32, ESP32-S2, ESP32-C3 and ESP32-S3
|
||||||
|
// UART_CLK_SRC_PLL :: ESP32-C2, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2 and ESP32-P4
|
||||||
|
// UART_CLK_SRC_XTAL :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
|
||||||
|
// UART_CLK_SRC_RTC :: ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, ESP32-S3 and ESP32-P4
|
||||||
|
// UART_CLK_SRC_REF_TICK :: ESP32 and ESP32-S2
|
||||||
|
// Note: CLK_SRC_PLL Freq depends on the SoC - ESP32-C2 has 40MHz, ESP32-H2 has 48MHz and ESP32-C5, C6, C61 and P4 has 80MHz
|
||||||
|
// Note: ESP32-C6, C61, ESP32-P4 and ESP32-C5 have LP UART that will use only RTC_FAST or XTAL/2 as Clock Source
|
||||||
|
bool setClockSource(SerialClkSrc clkSrc);
|
||||||
|
size_t setRxBufferSize(size_t new_size);
|
||||||
|
size_t setTxBufferSize(size_t new_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t _uart_nr;
|
uint8_t _uart_nr;
|
||||||
uart_t* _uart;
|
uart_t *_uart;
|
||||||
size_t _rxBufferSize;
|
size_t _rxBufferSize;
|
||||||
size_t _txBufferSize;
|
size_t _txBufferSize;
|
||||||
OnReceiveCb _onReceiveCB;
|
OnReceiveCb _onReceiveCB;
|
||||||
OnReceiveErrorCb _onReceiveErrorCB;
|
OnReceiveErrorCb _onReceiveErrorCB;
|
||||||
// _onReceive and _rxTimeout have be consistent when timeout is disabled
|
// _onReceive and _rxTimeout have be consistent when timeout is disabled
|
||||||
bool _onReceiveTimeout;
|
bool _onReceiveTimeout;
|
||||||
uint8_t _rxTimeout, _rxFIFOFull;
|
uint8_t _rxTimeout, _rxFIFOFull;
|
||||||
TaskHandle_t _eventTask;
|
TaskHandle_t _eventTask;
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
SemaphoreHandle_t _lock;
|
SemaphoreHandle_t _lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void _createEventTask(void *args);
|
void _createEventTask(void *args);
|
||||||
void _destroyEventTask(void);
|
void _destroyEventTask(void);
|
||||||
static void _uartEventTask(void *args);
|
static void _uartEventTask(void *args);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void serialEventRun(void) __attribute__((weak));
|
extern void serialEventRun(void) __attribute__((weak));
|
||||||
|
|
@ -350,11 +415,11 @@ extern void serialEventRun(void) __attribute__((weak));
|
||||||
#ifndef ARDUINO_USB_CDC_ON_BOOT
|
#ifndef ARDUINO_USB_CDC_ON_BOOT
|
||||||
#define ARDUINO_USB_CDC_ON_BOOT 0
|
#define ARDUINO_USB_CDC_ON_BOOT 0
|
||||||
#endif
|
#endif
|
||||||
#if ARDUINO_USB_CDC_ON_BOOT //Serial used from Native_USB_CDC | HW_CDC_JTAG
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used from Native_USB_CDC | HW_CDC_JTAG
|
||||||
#if ARDUINO_USB_MODE // Hardware CDC mode
|
#if ARDUINO_USB_MODE // Hardware CDC mode
|
||||||
// Arduino Serial is the HW JTAG CDC device
|
// Arduino Serial is the HW JTAG CDC device
|
||||||
#define Serial HWCDCSerial
|
#define Serial HWCDCSerial
|
||||||
#else // !ARDUINO_USB_MODE -- Native USB Mode
|
#else // !ARDUINO_USB_MODE -- Native USB Mode
|
||||||
// Arduino Serial is the Native USB CDC device
|
// Arduino Serial is the Native USB CDC device
|
||||||
#define Serial USBSerial
|
#define Serial USBSerial
|
||||||
#endif // ARDUINO_USB_MODE
|
#endif // ARDUINO_USB_MODE
|
||||||
|
|
@ -370,6 +435,15 @@ extern HardwareSerial Serial1;
|
||||||
#if SOC_UART_NUM > 2
|
#if SOC_UART_NUM > 2
|
||||||
extern HardwareSerial Serial2;
|
extern HardwareSerial Serial2;
|
||||||
#endif
|
#endif
|
||||||
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
#if SOC_UART_NUM > 3
|
||||||
|
extern HardwareSerial Serial3;
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_NUM > 4
|
||||||
|
extern HardwareSerial Serial4;
|
||||||
|
#endif
|
||||||
|
#if SOC_UART_NUM > 5
|
||||||
|
extern HardwareSerial Serial5;
|
||||||
|
#endif
|
||||||
|
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||||
|
|
||||||
#endif // HardwareSerial_h
|
#endif // HardwareSerial_h
|
||||||
|
|
|
||||||
|
|
@ -20,33 +20,29 @@
|
||||||
|
|
||||||
#include "HEXBuilder.h"
|
#include "HEXBuilder.h"
|
||||||
|
|
||||||
class HashBuilder : public HEXBuilder
|
class HashBuilder : public HEXBuilder {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual ~HashBuilder() {}
|
virtual ~HashBuilder() {}
|
||||||
virtual void begin() = 0;
|
virtual void begin() = 0;
|
||||||
|
|
||||||
virtual void add(const uint8_t* data, size_t len) = 0;
|
virtual void add(const uint8_t *data, size_t len) = 0;
|
||||||
virtual void add(const char* data)
|
virtual void add(const char *data) {
|
||||||
{
|
add((const uint8_t *)data, strlen(data));
|
||||||
add((const uint8_t*)data, strlen(data));
|
}
|
||||||
}
|
virtual void add(String data) {
|
||||||
virtual void add(String data)
|
add(data.c_str());
|
||||||
{
|
}
|
||||||
add(data.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void addHexString(const char* data) = 0;
|
virtual void addHexString(const char *data) = 0;
|
||||||
virtual void addHexString(String data)
|
virtual void addHexString(String data) {
|
||||||
{
|
addHexString(data.c_str());
|
||||||
addHexString(data.c_str());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool addStream(Stream& stream, const size_t maxLen) = 0;
|
virtual bool addStream(Stream &stream, const size_t maxLen) = 0;
|
||||||
virtual void calculate() = 0;
|
virtual void calculate() = 0;
|
||||||
virtual void getBytes(uint8_t* output) = 0;
|
virtual void getBytes(uint8_t *output) = 0;
|
||||||
virtual void getChars(char* output) = 0;
|
virtual void getChars(char *output) = 0;
|
||||||
virtual String toString() = 0;
|
virtual String toString() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,409 +22,432 @@
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "StreamString.h"
|
#include "StreamString.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_LWIP_IPV6
|
||||||
|
#define IP6_NO_ZONE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
IPAddress::IPAddress() : IPAddress(IPv4) {}
|
IPAddress::IPAddress() : IPAddress(IPv4) {}
|
||||||
|
|
||||||
IPAddress::IPAddress(IPType ip_type)
|
IPAddress::IPAddress(IPType ip_type) {
|
||||||
{
|
_type = ip_type;
|
||||||
_type = ip_type;
|
_zone = IP6_NO_ZONE;
|
||||||
_zone = IP6_NO_ZONE;
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
||||||
{
|
_type = IPv4;
|
||||||
_type = IPv4;
|
_zone = IP6_NO_ZONE;
|
||||||
_zone = IP6_NO_ZONE;
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX] = first_octet;
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX] = first_octet;
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 1] = second_octet;
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 1] = second_octet;
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 2] = third_octet;
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 2] = third_octet;
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = fourth_octet;
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = fourth_octet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z) {
|
IPAddress::IPAddress(
|
||||||
_type = IPv6;
|
uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12,
|
||||||
_address.bytes[0] = o1;
|
uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z
|
||||||
_address.bytes[1] = o2;
|
) {
|
||||||
_address.bytes[2] = o3;
|
_type = IPv6;
|
||||||
_address.bytes[3] = o4;
|
_address.bytes[0] = o1;
|
||||||
_address.bytes[4] = o5;
|
_address.bytes[1] = o2;
|
||||||
_address.bytes[5] = o6;
|
_address.bytes[2] = o3;
|
||||||
_address.bytes[6] = o7;
|
_address.bytes[3] = o4;
|
||||||
_address.bytes[7] = o8;
|
_address.bytes[4] = o5;
|
||||||
_address.bytes[8] = o9;
|
_address.bytes[5] = o6;
|
||||||
_address.bytes[9] = o10;
|
_address.bytes[6] = o7;
|
||||||
_address.bytes[10] = o11;
|
_address.bytes[7] = o8;
|
||||||
_address.bytes[11] = o12;
|
_address.bytes[8] = o9;
|
||||||
_address.bytes[12] = o13;
|
_address.bytes[9] = o10;
|
||||||
_address.bytes[13] = o14;
|
_address.bytes[10] = o11;
|
||||||
_address.bytes[14] = o15;
|
_address.bytes[11] = o12;
|
||||||
_address.bytes[15] = o16;
|
_address.bytes[12] = o13;
|
||||||
_zone = z;
|
_address.bytes[13] = o14;
|
||||||
|
_address.bytes[14] = o15;
|
||||||
|
_address.bytes[15] = o16;
|
||||||
|
_zone = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(uint32_t address)
|
IPAddress::IPAddress(uint32_t address) {
|
||||||
{
|
// IPv4 only
|
||||||
// IPv4 only
|
_type = IPv4;
|
||||||
_type = IPv4;
|
_zone = IP6_NO_ZONE;
|
||||||
_zone = IP6_NO_ZONE;
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
|
||||||
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
|
|
||||||
|
|
||||||
// NOTE on conversion/comparison and uint32_t:
|
// NOTE on conversion/comparison and uint32_t:
|
||||||
// These conversions are host platform dependent.
|
// These conversions are host platform dependent.
|
||||||
// There is a defined integer representation of IPv4 addresses,
|
// There is a defined integer representation of IPv4 addresses,
|
||||||
// based on network byte order (will be the value on big endian systems),
|
// based on network byte order (will be the value on big endian systems),
|
||||||
// e.g. http://2398766798 is the same as http://142.250.70.206,
|
// e.g. http://2398766798 is the same as http://142.250.70.206,
|
||||||
// However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE,
|
// However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE,
|
||||||
// in that order, will form the integer (uint32_t) 3460758158 .
|
// in that order, will form the integer (uint32_t) 3460758158 .
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {}
|
IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {}
|
||||||
|
|
||||||
IPAddress::IPAddress(IPType ip_type, const uint8_t *address, uint8_t z)
|
IPAddress::IPAddress(IPType ip_type, const uint8_t *address, uint8_t z) {
|
||||||
{
|
_type = ip_type;
|
||||||
_type = ip_type;
|
if (ip_type == IPv4) {
|
||||||
if (ip_type == IPv4) {
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
|
||||||
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
|
_zone = 0;
|
||||||
_zone = 0;
|
} else {
|
||||||
} else {
|
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
_zone = z;
|
||||||
_zone = z;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(const char *address)
|
IPAddress::IPAddress(const char *address) {
|
||||||
{
|
fromString(address);
|
||||||
fromString(address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(const IPAddress& address)
|
IPAddress::IPAddress(const IPAddress &address) {
|
||||||
{
|
*this = address;
|
||||||
*this = address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String IPAddress::toString(bool includeZone) const
|
String IPAddress::toString(bool includeZone) const {
|
||||||
{
|
StreamString s;
|
||||||
StreamString s;
|
printTo(s, includeZone);
|
||||||
printTo(s, includeZone);
|
return String(s);
|
||||||
return String(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPAddress::fromString(const char *address) {
|
bool IPAddress::fromString(const char *address) {
|
||||||
if (!fromString4(address)) {
|
if (!fromString4(address)) {
|
||||||
return fromString6(address);
|
return fromString6(address);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPAddress::fromString4(const char *address)
|
bool IPAddress::fromString4(const char *address) {
|
||||||
{
|
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||||
// TODO: add support for "a", "a.b", "a.b.c" formats
|
|
||||||
|
|
||||||
int16_t acc = -1; // Accumulator
|
int16_t acc = -1; // Accumulator
|
||||||
uint8_t dots = 0;
|
uint8_t dots = 0;
|
||||||
|
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
while (*address)
|
while (*address) {
|
||||||
{
|
char c = *address++;
|
||||||
char c = *address++;
|
if (c >= '0' && c <= '9') {
|
||||||
if (c >= '0' && c <= '9')
|
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
|
||||||
{
|
if (acc > 255) {
|
||||||
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
|
// Value out of [0..255] range
|
||||||
if (acc > 255) {
|
|
||||||
// Value out of [0..255] range
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == '.')
|
|
||||||
{
|
|
||||||
if (dots == 3) {
|
|
||||||
// Too many dots (there must be 3 dots)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (acc < 0) {
|
|
||||||
/* No value between dots, e.g. '1..' */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
|
|
||||||
acc = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Invalid char
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dots != 3) {
|
|
||||||
// Too few dots (there must be 3 dots)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (acc < 0) {
|
} else if (c == '.') {
|
||||||
|
if (dots == 3) {
|
||||||
|
// Too many dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (acc < 0) {
|
||||||
/* No value between dots, e.g. '1..' */
|
/* No value between dots, e.g. '1..' */
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
|
||||||
|
acc = -1;
|
||||||
|
} else {
|
||||||
|
// Invalid char
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc;
|
}
|
||||||
_type = IPv4;
|
|
||||||
return true;
|
if (dots != 3) {
|
||||||
|
// Too few dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (acc < 0) {
|
||||||
|
/* No value between dots, e.g. '1..' */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc;
|
||||||
|
_type = IPv4;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPAddress::fromString6(const char *address) {
|
bool IPAddress::fromString6(const char *address) {
|
||||||
uint32_t acc = 0; // Accumulator
|
uint32_t acc = 0; // Accumulator
|
||||||
int colons = 0, double_colons = -1;
|
int colons = 0, double_colons = -1;
|
||||||
|
|
||||||
while (*address)
|
while (*address) {
|
||||||
{
|
char c = tolower(*address++);
|
||||||
char c = tolower(*address++);
|
if (isalnum(c) && c <= 'f') {
|
||||||
if (isalnum(c) && c <= 'f') {
|
if (c >= 'a') {
|
||||||
if (c >= 'a')
|
c -= 'a' - '0' - 10;
|
||||||
c -= 'a' - '0' - 10;
|
}
|
||||||
acc = acc * 16 + (c - '0');
|
acc = acc * 16 + (c - '0');
|
||||||
if (acc > 0xffff)
|
if (acc > 0xffff) {
|
||||||
// Value out of range
|
// Value out of range
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (c == ':') {
|
|
||||||
if (*address == ':') {
|
|
||||||
if (double_colons >= 0) {
|
|
||||||
// :: allowed once
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (*address != '\0' && *(address + 1) == ':') {
|
|
||||||
// ::: not allowed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// remember location
|
|
||||||
double_colons = colons + !!acc;
|
|
||||||
address++;
|
|
||||||
} else if (*address == '\0') {
|
|
||||||
// can't end with a single colon
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (colons == 7)
|
|
||||||
// too many separators
|
|
||||||
return false;
|
|
||||||
_address.bytes[colons * 2] = acc >> 8;
|
|
||||||
_address.bytes[colons * 2 + 1] = acc & 0xff;
|
|
||||||
colons++;
|
|
||||||
acc = 0;
|
|
||||||
}
|
|
||||||
else if (c == '%') {
|
|
||||||
_zone = netif_name_to_index(address);
|
|
||||||
while(*address != '\0'){
|
|
||||||
address++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// Invalid char
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (double_colons == -1 && colons != 7) {
|
|
||||||
// Too few separators
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (double_colons > -1 && colons > 6) {
|
} else if (c == ':') {
|
||||||
// Too many segments (double colon must be at least one zero field)
|
if (*address == ':') {
|
||||||
|
if (double_colons >= 0) {
|
||||||
|
// :: allowed once
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*address != '\0' && *(address + 1) == ':') {
|
||||||
|
// ::: not allowed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// remember location
|
||||||
|
double_colons = colons + !!acc;
|
||||||
|
address++;
|
||||||
|
} else if (*address == '\0') {
|
||||||
|
// can't end with a single colon
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
if (colons == 7) {
|
||||||
|
// too many separators
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[colons * 2] = acc >> 8;
|
||||||
|
_address.bytes[colons * 2 + 1] = acc & 0xff;
|
||||||
|
colons++;
|
||||||
|
acc = 0;
|
||||||
|
} else if (c == '%') {
|
||||||
|
// netif_index_to_name crashes on latest esp-idf
|
||||||
|
// _zone = netif_name_to_index(address);
|
||||||
|
// in the interim, we parse the suffix as a zone number
|
||||||
|
while ((*address != '\0') && (!isdigit(*address))) { // skip all non-digit after '%'
|
||||||
|
address++;
|
||||||
|
}
|
||||||
|
_zone = atol(address) + 1; // increase by one by convention, so we can have zone '0'
|
||||||
|
while (*address != '\0') {
|
||||||
|
address++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Invalid char
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
_address.bytes[colons * 2] = acc >> 8;
|
}
|
||||||
_address.bytes[colons * 2 + 1] = acc & 0xff;
|
|
||||||
colons++;
|
|
||||||
|
|
||||||
if (double_colons != -1) {
|
if (double_colons == -1 && colons != 7) {
|
||||||
for (int i = colons * 2 - double_colons * 2 - 1; i >= 0; i--)
|
// Too few separators
|
||||||
_address.bytes[16 - colons * 2 + double_colons * 2 + i] = _address.bytes[double_colons * 2 + i];
|
return false;
|
||||||
for (int i = double_colons * 2; i < 16 - colons * 2 + double_colons * 2; i++)
|
}
|
||||||
_address.bytes[i] = 0;
|
if (double_colons > -1 && colons > 6) {
|
||||||
|
// Too many segments (double colon must be at least one zero field)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_address.bytes[colons * 2] = acc >> 8;
|
||||||
|
_address.bytes[colons * 2 + 1] = acc & 0xff;
|
||||||
|
colons++;
|
||||||
|
|
||||||
|
if (double_colons != -1) {
|
||||||
|
for (int i = colons * 2 - double_colons * 2 - 1; i >= 0; i--) {
|
||||||
|
_address.bytes[16 - colons * 2 + double_colons * 2 + i] = _address.bytes[double_colons * 2 + i];
|
||||||
}
|
}
|
||||||
|
for (int i = double_colons * 2; i < 16 - colons * 2 + double_colons * 2; i++) {
|
||||||
|
_address.bytes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_type = IPv6;
|
_type = IPv6;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
IPAddress &IPAddress::operator=(const uint8_t *address) {
|
||||||
{
|
// IPv4 only conversion from byte pointer
|
||||||
// IPv4 only conversion from byte pointer
|
_type = IPv4;
|
||||||
_type = IPv4;
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
|
||||||
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress& IPAddress::operator=(const char *address)
|
IPAddress &IPAddress::operator=(const char *address) {
|
||||||
{
|
fromString(address);
|
||||||
fromString(address);
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress& IPAddress::operator=(uint32_t address)
|
IPAddress &IPAddress::operator=(uint32_t address) {
|
||||||
{
|
// IPv4 conversion
|
||||||
// IPv4 conversion
|
// See note on conversion/comparison and uint32_t
|
||||||
// See note on conversion/comparison and uint32_t
|
_type = IPv4;
|
||||||
_type = IPv4;
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
|
||||||
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress& IPAddress::operator=(const IPAddress& address){
|
IPAddress &IPAddress::operator=(const IPAddress &address) {
|
||||||
_type = address.type();
|
_type = address.type();
|
||||||
_zone = address.zone();
|
_zone = address.zone();
|
||||||
memcpy(_address.bytes, address._address.bytes, sizeof(_address.bytes));
|
memcpy(_address.bytes, address._address.bytes, sizeof(_address.bytes));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPAddress::operator==(const IPAddress& addr) const {
|
bool IPAddress::operator==(const IPAddress &addr) const {
|
||||||
return (addr._type == _type)
|
return (addr._type == _type) && (_type == IPType::IPv4 ? addr._address.dword[IPADDRESS_V4_DWORD_INDEX] == _address.dword[IPADDRESS_V4_DWORD_INDEX] : memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0);
|
||||||
&& (memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPAddress::operator==(const uint8_t* addr) const
|
bool IPAddress::operator==(const uint8_t *addr) const {
|
||||||
{
|
// IPv4 only comparison to byte pointer
|
||||||
// IPv4 only comparison to byte pointer
|
// Can't support IPv6 as we know our type, but not the length of the pointer
|
||||||
// Can't support IPv6 as we know our type, but not the length of the pointer
|
return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0;
|
||||||
return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t IPAddress::operator[](int index) const {
|
uint8_t IPAddress::operator[](int index) const {
|
||||||
if (_type == IPv4) {
|
if (_type == IPv4) {
|
||||||
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
|
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
|
||||||
}
|
}
|
||||||
return _address.bytes[index];
|
return _address.bytes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t& IPAddress::operator[](int index) {
|
uint8_t &IPAddress::operator[](int index) {
|
||||||
if (_type == IPv4) {
|
if (_type == IPv4) {
|
||||||
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
|
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
|
||||||
}
|
}
|
||||||
return _address.bytes[index];
|
return _address.bytes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IPAddress::printTo(Print& p) const
|
size_t IPAddress::printTo(Print &p) const {
|
||||||
{
|
return printTo(p, false);
|
||||||
return printTo(p, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IPAddress::printTo(Print& p, bool includeZone) const
|
size_t IPAddress::printTo(Print &p, bool includeZone) const {
|
||||||
{
|
size_t n = 0;
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
if (_type == IPv6) {
|
if (_type == IPv6) {
|
||||||
// IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case
|
// IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case
|
||||||
int8_t longest_start = -1;
|
int8_t longest_start = -1;
|
||||||
int8_t longest_length = 1;
|
int8_t longest_length = 1;
|
||||||
int8_t current_start = -1;
|
int8_t current_start = -1;
|
||||||
int8_t current_length = 0;
|
int8_t current_length = 0;
|
||||||
for (int8_t f = 0; f < 8; f++) {
|
for (int8_t f = 0; f < 8; f++) {
|
||||||
if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) {
|
if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) {
|
||||||
if (current_start == -1) {
|
if (current_start == -1) {
|
||||||
current_start = f;
|
current_start = f;
|
||||||
current_length = 1;
|
current_length = 1;
|
||||||
} else {
|
} else {
|
||||||
current_length++;
|
current_length++;
|
||||||
}
|
|
||||||
if (current_length > longest_length) {
|
|
||||||
longest_start = current_start;
|
|
||||||
longest_length = current_length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current_start = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int f = 0; f < 8; f++) {
|
if (current_length > longest_length) {
|
||||||
if (f < longest_start || f >= longest_start + longest_length) {
|
longest_start = current_start;
|
||||||
uint8_t c1 = _address.bytes[f * 2] >> 4;
|
longest_length = current_length;
|
||||||
uint8_t c2 = _address.bytes[f * 2] & 0xf;
|
|
||||||
uint8_t c3 = _address.bytes[f * 2 + 1] >> 4;
|
|
||||||
uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf;
|
|
||||||
if (c1 > 0) {
|
|
||||||
n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10));
|
|
||||||
}
|
|
||||||
if (c1 > 0 || c2 > 0) {
|
|
||||||
n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10));
|
|
||||||
}
|
|
||||||
if (c1 > 0 || c2 > 0 || c3 > 0) {
|
|
||||||
n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10));
|
|
||||||
}
|
|
||||||
n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10));
|
|
||||||
if (f < 7) {
|
|
||||||
n += p.print(':');
|
|
||||||
}
|
|
||||||
} else if (f == longest_start) {
|
|
||||||
if (longest_start == 0) {
|
|
||||||
n += p.print(':');
|
|
||||||
}
|
|
||||||
n += p.print(':');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add a zone if zone-id is non-zero
|
} else {
|
||||||
if(_zone > 0 && includeZone){
|
current_start = -1;
|
||||||
n += p.print('%');
|
}
|
||||||
char if_name[NETIF_NAMESIZE];
|
|
||||||
netif_index_to_name(_zone, if_name);
|
|
||||||
n += p.print(if_name);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
for (int f = 0; f < 8; f++) {
|
||||||
// IPv4
|
if (f < longest_start || f >= longest_start + longest_length) {
|
||||||
for (int i =0; i < 3; i++)
|
uint8_t c1 = _address.bytes[f * 2] >> 4;
|
||||||
{
|
uint8_t c2 = _address.bytes[f * 2] & 0xf;
|
||||||
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC);
|
uint8_t c3 = _address.bytes[f * 2 + 1] >> 4;
|
||||||
n += p.print('.');
|
uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf;
|
||||||
|
if (c1 > 0) {
|
||||||
|
n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10));
|
||||||
|
}
|
||||||
|
if (c1 > 0 || c2 > 0) {
|
||||||
|
n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10));
|
||||||
|
}
|
||||||
|
if (c1 > 0 || c2 > 0 || c3 > 0) {
|
||||||
|
n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10));
|
||||||
|
}
|
||||||
|
n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10));
|
||||||
|
if (f < 7) {
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
} else if (f == longest_start) {
|
||||||
|
if (longest_start == 0) {
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add a zone if zone-id is non-zero (causes exception on recent IDF builds)
|
||||||
|
// if (_zone > 0 && includeZone) {
|
||||||
|
// n += p.print('%');
|
||||||
|
// char if_name[NETIF_NAMESIZE];
|
||||||
|
// netif_index_to_name(_zone, if_name);
|
||||||
|
// n += p.print(if_name);
|
||||||
|
// }
|
||||||
|
// In the interim, we just output the index number
|
||||||
|
if (_zone > 0 && includeZone) {
|
||||||
|
n += p.print('%');
|
||||||
|
// look for the interface name
|
||||||
|
for (netif *intf = netif_list; intf != nullptr; intf = intf->next) {
|
||||||
|
if (_zone - 1 == intf->num) {
|
||||||
|
n += p.print(intf->name[0]);
|
||||||
|
n += p.print(intf->name[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n += p.print(_zone - 1);
|
||||||
}
|
}
|
||||||
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC);
|
|
||||||
return n;
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC);
|
||||||
|
n += p.print('.');
|
||||||
|
}
|
||||||
|
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC);
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress::IPAddress(const ip_addr_t *addr){
|
IPAddress::IPAddress(const ip_addr_t *addr) {
|
||||||
from_ip_addr_t(addr);
|
from_ip_addr_t(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPAddress::to_ip_addr_t(ip_addr_t* addr) const {
|
void IPAddress::to_ip_addr_t(ip_addr_t *addr) const {
|
||||||
if(_type == IPv6){
|
#if CONFIG_LWIP_IPV6
|
||||||
addr->type = IPADDR_TYPE_V6;
|
if (_type == IPv6) {
|
||||||
addr->u_addr.ip6.addr[0] = _address.dword[0];
|
addr->type = IPADDR_TYPE_V6;
|
||||||
addr->u_addr.ip6.addr[1] = _address.dword[1];
|
addr->u_addr.ip6.addr[0] = _address.dword[0];
|
||||||
addr->u_addr.ip6.addr[2] = _address.dword[2];
|
addr->u_addr.ip6.addr[1] = _address.dword[1];
|
||||||
addr->u_addr.ip6.addr[3] = _address.dword[3];
|
addr->u_addr.ip6.addr[2] = _address.dword[2];
|
||||||
|
addr->u_addr.ip6.addr[3] = _address.dword[3];
|
||||||
#if LWIP_IPV6_SCOPES
|
#if LWIP_IPV6_SCOPES
|
||||||
addr->u_addr.ip6.zone = _zone;
|
addr->u_addr.ip6.zone = _zone;
|
||||||
#endif /* LWIP_IPV6_SCOPES */
|
#endif /* LWIP_IPV6_SCOPES */
|
||||||
} else {
|
} else {
|
||||||
addr->type = IPADDR_TYPE_V4;
|
addr->type = IPADDR_TYPE_V4;
|
||||||
addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX];
|
addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX];
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
addr->addr = _address.dword[IPADDRESS_V4_DWORD_INDEX];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress& IPAddress::from_ip_addr_t(const ip_addr_t* addr){
|
IPAddress &IPAddress::from_ip_addr_t(const ip_addr_t *addr) {
|
||||||
if(addr->type == IPADDR_TYPE_V6){
|
#if CONFIG_LWIP_IPV6
|
||||||
_type = IPv6;
|
if (addr->type == IPADDR_TYPE_V6) {
|
||||||
_address.dword[0] = addr->u_addr.ip6.addr[0];
|
_type = IPv6;
|
||||||
_address.dword[1] = addr->u_addr.ip6.addr[1];
|
_address.dword[0] = addr->u_addr.ip6.addr[0];
|
||||||
_address.dword[2] = addr->u_addr.ip6.addr[2];
|
_address.dword[1] = addr->u_addr.ip6.addr[1];
|
||||||
_address.dword[3] = addr->u_addr.ip6.addr[3];
|
_address.dword[2] = addr->u_addr.ip6.addr[2];
|
||||||
|
_address.dword[3] = addr->u_addr.ip6.addr[3];
|
||||||
#if LWIP_IPV6_SCOPES
|
#if LWIP_IPV6_SCOPES
|
||||||
_zone = addr->u_addr.ip6.zone;
|
_zone = addr->u_addr.ip6.zone;
|
||||||
#endif /* LWIP_IPV6_SCOPES */
|
#endif /* LWIP_IPV6_SCOPES */
|
||||||
} else {
|
} else {
|
||||||
_type = IPv4;
|
#endif
|
||||||
_address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr;
|
_type = IPv4;
|
||||||
}
|
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||||
return *this;
|
#if CONFIG_LWIP_IPV6
|
||||||
|
_address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr;
|
||||||
|
#else
|
||||||
|
_address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->addr;
|
||||||
|
#endif
|
||||||
|
#if CONFIG_LWIP_IPV6
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_LWIP_IPV6
|
||||||
esp_ip6_addr_type_t IPAddress::addr_type() const {
|
esp_ip6_addr_type_t IPAddress::addr_type() const {
|
||||||
if(_type != IPv6){
|
if (_type != IPv6) {
|
||||||
return ESP_IP6_ADDR_IS_UNKNOWN;
|
return ESP_IP6_ADDR_IS_UNKNOWN;
|
||||||
}
|
}
|
||||||
ip_addr_t addr;
|
ip_addr_t addr;
|
||||||
to_ip_addr_t(&addr);
|
to_ip_addr_t(&addr);
|
||||||
return esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)(&(addr.u_addr.ip6)));
|
return esp_netif_ip6_get_addr_type((esp_ip6_addr_t *)(&(addr.u_addr.ip6)));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_LWIP_IPV6
|
||||||
const IPAddress IN6ADDR_ANY(IPv6);
|
const IPAddress IN6ADDR_ANY(IPv6);
|
||||||
const IPAddress INADDR_NONE(0,0,0,0);
|
#endif
|
||||||
|
const IPAddress INADDR_NONE(0, 0, 0, 0);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "WString.h"
|
#include "WString.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "esp_netif_ip_addr.h"
|
#include "esp_netif_ip_addr.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#define IPADDRESS_V4_BYTES_INDEX 12
|
#define IPADDRESS_V4_BYTES_INDEX 12
|
||||||
#define IPADDRESS_V4_DWORD_INDEX 3
|
#define IPADDRESS_V4_DWORD_INDEX 3
|
||||||
|
|
@ -31,88 +32,108 @@
|
||||||
// A class to make it easier to handle and pass around IP addresses
|
// A class to make it easier to handle and pass around IP addresses
|
||||||
|
|
||||||
enum IPType {
|
enum IPType {
|
||||||
IPv4,
|
IPv4,
|
||||||
IPv6
|
IPv6
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPAddress : public Printable {
|
class IPAddress : public Printable {
|
||||||
private:
|
private:
|
||||||
union {
|
union {
|
||||||
uint8_t bytes[16];
|
uint8_t bytes[16];
|
||||||
uint32_t dword[4];
|
uint32_t dword[4];
|
||||||
} _address;
|
} _address;
|
||||||
IPType _type;
|
IPType _type;
|
||||||
uint8_t _zone;
|
uint8_t _zone;
|
||||||
|
|
||||||
// Access the raw byte array containing the address. Because this returns a pointer
|
// Access the raw byte array containing the address. Because this returns a pointer
|
||||||
// to the internal structure rather than a copy of the address this function should only
|
// to the internal structure rather than a copy of the address this function should only
|
||||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||||
// stored.
|
// stored.
|
||||||
uint8_t* raw_address() { return _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes; }
|
uint8_t *raw_address() {
|
||||||
|
return _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
// Default IPv4
|
// Default IPv4
|
||||||
IPAddress();
|
IPAddress();
|
||||||
IPAddress(IPType ip_type);
|
IPAddress(IPType ip_type);
|
||||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z=0);
|
IPAddress(
|
||||||
// IPv4; see implementation note
|
uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12,
|
||||||
IPAddress(uint32_t address);
|
uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z = 0
|
||||||
// Default IPv4
|
);
|
||||||
IPAddress(const uint8_t *address);
|
// IPv4; see implementation note
|
||||||
IPAddress(IPType ip_type, const uint8_t *address, uint8_t z=0);
|
IPAddress(uint32_t address);
|
||||||
// If IPv4 fails tries IPv6 see fromString function
|
// Default IPv4
|
||||||
IPAddress(const char *address);
|
IPAddress(const uint8_t *address);
|
||||||
IPAddress(const IPAddress& address);
|
IPAddress(IPType ip_type, const uint8_t *address, uint8_t z = 0);
|
||||||
|
// If IPv4 fails tries IPv6 see fromString function
|
||||||
|
IPAddress(const char *address);
|
||||||
|
IPAddress(const IPAddress &address);
|
||||||
|
|
||||||
bool fromString(const char *address);
|
bool fromString(const char *address);
|
||||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
bool fromString(const String &address) {
|
||||||
|
return fromString(address.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Overloaded cast operator to allow IPAddress objects to be used where a uint32_t is expected
|
// Overloaded cast operator to allow IPAddress objects to be used where a uint32_t is expected
|
||||||
// NOTE: IPv4 only; see implementation note
|
// NOTE: IPv4 only; see implementation note
|
||||||
operator uint32_t() const { return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0; };
|
operator uint32_t() const {
|
||||||
|
return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0;
|
||||||
|
};
|
||||||
|
|
||||||
bool operator==(const IPAddress& addr) const;
|
bool operator==(const IPAddress &addr) const;
|
||||||
bool operator!=(const IPAddress& addr) const { return !(*this == addr); };
|
bool operator!=(const IPAddress &addr) const {
|
||||||
|
return !(*this == addr);
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE: IPv4 only; we don't know the length of the pointer
|
// NOTE: IPv4 only; we don't know the length of the pointer
|
||||||
bool operator==(const uint8_t* addr) const;
|
bool operator==(const uint8_t *addr) const;
|
||||||
|
|
||||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||||
uint8_t operator[](int index) const;
|
uint8_t operator[](int index) const;
|
||||||
uint8_t& operator[](int index);
|
uint8_t &operator[](int index);
|
||||||
|
|
||||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
// Overloaded copy operators to allow initialization of IPAddress objects from other types
|
||||||
// NOTE: IPv4 only
|
// NOTE: IPv4 only
|
||||||
IPAddress& operator=(const uint8_t *address);
|
IPAddress &operator=(const uint8_t *address);
|
||||||
// NOTE: IPv4 only; see implementation note
|
// NOTE: IPv4 only; see implementation note
|
||||||
IPAddress& operator=(uint32_t address);
|
IPAddress &operator=(uint32_t address);
|
||||||
// If IPv4 fails tries IPv6 see fromString function
|
// If IPv4 fails tries IPv6 see fromString function
|
||||||
IPAddress& operator=(const char *address);
|
IPAddress &operator=(const char *address);
|
||||||
IPAddress& operator=(const IPAddress& address);
|
IPAddress &operator=(const IPAddress &address);
|
||||||
|
|
||||||
virtual size_t printTo(Print& p) const;
|
virtual size_t printTo(Print &p) const;
|
||||||
String toString(bool includeZone = false) const;
|
String toString(bool includeZone = false) const;
|
||||||
|
|
||||||
IPType type() const { return _type; }
|
IPType type() const {
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
// Espresif LwIP conversions
|
// Espresif LwIP conversions
|
||||||
IPAddress(const ip_addr_t *addr);
|
IPAddress(const ip_addr_t *addr);
|
||||||
void to_ip_addr_t(ip_addr_t* addr) const;
|
void to_ip_addr_t(ip_addr_t *addr) const;
|
||||||
IPAddress& from_ip_addr_t(const ip_addr_t* addr);
|
IPAddress &from_ip_addr_t(const ip_addr_t *addr);
|
||||||
esp_ip6_addr_type_t addr_type() const;
|
#if CONFIG_LWIP_IPV6
|
||||||
uint8_t zone() const { return (type() == IPv6)?_zone:0; }
|
esp_ip6_addr_type_t addr_type() const;
|
||||||
size_t printTo(Print& p, bool includeZone) const;
|
#endif
|
||||||
|
uint8_t zone() const {
|
||||||
|
return (type() == IPv6) ? _zone : 0;
|
||||||
|
}
|
||||||
|
size_t printTo(Print &p, bool includeZone) const;
|
||||||
|
|
||||||
friend class UDP;
|
friend class UDP;
|
||||||
friend class Client;
|
friend class Client;
|
||||||
friend class Server;
|
friend class Server;
|
||||||
|
friend class EthernetClass;
|
||||||
|
friend class DhcpClass;
|
||||||
|
friend class DNSClient;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool fromString4(const char *address);
|
bool fromString4(const char *address);
|
||||||
bool fromString6(const char *address);
|
bool fromString6(const char *address);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const IPAddress IN6ADDR_ANY;
|
extern const IPAddress IN6ADDR_ANY;
|
||||||
|
|
|
||||||
|
|
@ -21,87 +21,79 @@
|
||||||
#include <HEXBuilder.h>
|
#include <HEXBuilder.h>
|
||||||
#include <MD5Builder.h>
|
#include <MD5Builder.h>
|
||||||
|
|
||||||
void MD5Builder::begin(void)
|
void MD5Builder::begin(void) {
|
||||||
{
|
memset(_buf, 0x00, ESP_ROM_MD5_DIGEST_LEN);
|
||||||
memset(_buf, 0x00, ESP_ROM_MD5_DIGEST_LEN);
|
esp_rom_md5_init(&_ctx);
|
||||||
esp_rom_md5_init(&_ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5Builder::add(const uint8_t * data, size_t len)
|
void MD5Builder::add(const uint8_t *data, size_t len) {
|
||||||
{
|
esp_rom_md5_update(&_ctx, data, len);
|
||||||
esp_rom_md5_update(&_ctx, data, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5Builder::addHexString(const char * data)
|
void MD5Builder::addHexString(const char *data) {
|
||||||
{
|
size_t len = strlen(data);
|
||||||
size_t len = strlen(data);
|
uint8_t *tmp = (uint8_t *)malloc(len / 2);
|
||||||
uint8_t * tmp = (uint8_t*)malloc(len/2);
|
if (tmp == NULL) {
|
||||||
if(tmp == NULL) {
|
return;
|
||||||
return;
|
}
|
||||||
|
hex2bytes(tmp, len / 2, data);
|
||||||
|
add(tmp, len / 2);
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MD5Builder::addStream(Stream &stream, const size_t maxLen) {
|
||||||
|
const int buf_size = 512;
|
||||||
|
int maxLengthLeft = maxLen;
|
||||||
|
uint8_t *buf = (uint8_t *)malloc(buf_size);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytesAvailable = stream.available();
|
||||||
|
while ((bytesAvailable > 0) && (maxLengthLeft > 0)) {
|
||||||
|
|
||||||
|
// determine number of bytes to read
|
||||||
|
int readBytes = bytesAvailable;
|
||||||
|
if (readBytes > maxLengthLeft) {
|
||||||
|
readBytes = maxLengthLeft; // read only until max_len
|
||||||
}
|
}
|
||||||
hex2bytes(tmp, len/2, data);
|
if (readBytes > buf_size) {
|
||||||
add(tmp, len/2);
|
readBytes = buf_size; // not read more the buffer can handle
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MD5Builder::addStream(Stream & stream, const size_t maxLen)
|
|
||||||
{
|
|
||||||
const int buf_size = 512;
|
|
||||||
int maxLengthLeft = maxLen;
|
|
||||||
uint8_t * buf = (uint8_t*) malloc(buf_size);
|
|
||||||
|
|
||||||
if(!buf) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytesAvailable = stream.available();
|
// read data and check if we got something
|
||||||
while((bytesAvailable > 0) && (maxLengthLeft > 0)) {
|
int numBytesRead = stream.readBytes(buf, readBytes);
|
||||||
|
if (numBytesRead < 1) {
|
||||||
// determine number of bytes to read
|
free(buf);
|
||||||
int readBytes = bytesAvailable;
|
return false;
|
||||||
if(readBytes > maxLengthLeft) {
|
|
||||||
readBytes = maxLengthLeft ; // read only until max_len
|
|
||||||
}
|
|
||||||
if(readBytes > buf_size) {
|
|
||||||
readBytes = buf_size; // not read more the buffer can handle
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data and check if we got something
|
|
||||||
int numBytesRead = stream.readBytes(buf, readBytes);
|
|
||||||
if(numBytesRead< 1) {
|
|
||||||
free(buf);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update MD5 with buffer payload
|
|
||||||
esp_rom_md5_update(&_ctx, buf, numBytesRead);
|
|
||||||
|
|
||||||
// update available number of bytes
|
|
||||||
maxLengthLeft -= numBytesRead;
|
|
||||||
bytesAvailable = stream.available();
|
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
return true;
|
// Update MD5 with buffer payload
|
||||||
|
esp_rom_md5_update(&_ctx, buf, numBytesRead);
|
||||||
|
|
||||||
|
// update available number of bytes
|
||||||
|
maxLengthLeft -= numBytesRead;
|
||||||
|
bytesAvailable = stream.available();
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5Builder::calculate(void)
|
void MD5Builder::calculate(void) {
|
||||||
{
|
esp_rom_md5_final(_buf, &_ctx);
|
||||||
esp_rom_md5_final(_buf, &_ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5Builder::getBytes(uint8_t * output)
|
void MD5Builder::getBytes(uint8_t *output) {
|
||||||
{
|
memcpy(output, _buf, ESP_ROM_MD5_DIGEST_LEN);
|
||||||
memcpy(output, _buf, ESP_ROM_MD5_DIGEST_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5Builder::getChars(char * output)
|
void MD5Builder::getChars(char *output) {
|
||||||
{
|
bytes2hex(output, ESP_ROM_MD5_DIGEST_LEN * 2 + 1, _buf, ESP_ROM_MD5_DIGEST_LEN);
|
||||||
bytes2hex(output, ESP_ROM_MD5_DIGEST_LEN*2+1, _buf, ESP_ROM_MD5_DIGEST_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String MD5Builder::toString(void)
|
String MD5Builder::toString(void) {
|
||||||
{
|
char out[(ESP_ROM_MD5_DIGEST_LEN * 2) + 1];
|
||||||
char out[(ESP_ROM_MD5_DIGEST_LEN * 2) + 1];
|
getChars(out);
|
||||||
getChars(out);
|
return String(out);
|
||||||
return String(out);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,25 +29,25 @@
|
||||||
|
|
||||||
#include "HashBuilder.h"
|
#include "HashBuilder.h"
|
||||||
|
|
||||||
class MD5Builder : public HashBuilder
|
class MD5Builder : public HashBuilder {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
md5_context_t _ctx;
|
md5_context_t _ctx;
|
||||||
uint8_t _buf[ESP_ROM_MD5_DIGEST_LEN];
|
uint8_t _buf[ESP_ROM_MD5_DIGEST_LEN];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin(void) override;
|
void begin(void) override;
|
||||||
|
|
||||||
using HashBuilder::add;
|
using HashBuilder::add;
|
||||||
void add(const uint8_t * data, size_t len) override;
|
void add(const uint8_t *data, size_t len) override;
|
||||||
|
|
||||||
using HashBuilder::addHexString;
|
using HashBuilder::addHexString;
|
||||||
void addHexString(const char * data) override;
|
void addHexString(const char *data) override;
|
||||||
|
|
||||||
bool addStream(Stream & stream, const size_t maxLen) override;
|
bool addStream(Stream &stream, const size_t maxLen) override;
|
||||||
void calculate(void) override;
|
void calculate(void) override;
|
||||||
void getBytes(uint8_t * output) override;
|
void getBytes(uint8_t *output) override;
|
||||||
void getChars(char * output) override;
|
void getChars(char *output) override;
|
||||||
String toString(void) override;
|
String toString(void) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
228
cores/esp32/MacAddress.cpp
Normal file
228
cores/esp32/MacAddress.cpp
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
#include <MacAddress.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Print.h>
|
||||||
|
|
||||||
|
//Default constructor, blank mac address.
|
||||||
|
MacAddress::MacAddress() : MacAddress(MAC6) {}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(MACType mac_type) {
|
||||||
|
_type = mac_type;
|
||||||
|
memset(_mac.bytes, 0, sizeof(_mac.bytes));
|
||||||
|
}
|
||||||
|
MacAddress::MacAddress(MACType mac_type, uint64_t mac) {
|
||||||
|
_type = mac_type;
|
||||||
|
_mac.val = mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(MACType mac_type, const uint8_t *macbytearray) {
|
||||||
|
_type = mac_type;
|
||||||
|
memset(_mac.bytes, 0, sizeof(_mac.bytes));
|
||||||
|
if (_type == MAC6) {
|
||||||
|
memcpy(_mac.bytes, macbytearray, 6);
|
||||||
|
} else {
|
||||||
|
memcpy(_mac.bytes, macbytearray, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(const char *macstr) {
|
||||||
|
fromString(macstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(const String &macstr) {
|
||||||
|
fromString(macstr.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6) {
|
||||||
|
_type = MAC6;
|
||||||
|
memset(_mac.bytes, 0, sizeof(_mac.bytes));
|
||||||
|
_mac.bytes[0] = b1;
|
||||||
|
_mac.bytes[1] = b2;
|
||||||
|
_mac.bytes[2] = b3;
|
||||||
|
_mac.bytes[3] = b4;
|
||||||
|
_mac.bytes[4] = b5;
|
||||||
|
_mac.bytes[5] = b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacAddress::MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) {
|
||||||
|
_type = MAC8;
|
||||||
|
_mac.bytes[0] = b1;
|
||||||
|
_mac.bytes[1] = b2;
|
||||||
|
_mac.bytes[2] = b3;
|
||||||
|
_mac.bytes[3] = b4;
|
||||||
|
_mac.bytes[4] = b5;
|
||||||
|
_mac.bytes[5] = b6;
|
||||||
|
_mac.bytes[6] = b7;
|
||||||
|
_mac.bytes[7] = b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse user entered string into MAC address
|
||||||
|
bool MacAddress::fromString(const char *buf) {
|
||||||
|
if (strlen(buf) == 17) {
|
||||||
|
return fromString6(buf);
|
||||||
|
} else if (strlen(buf) == 23) {
|
||||||
|
return fromString8(buf);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse user entered string into MAC address
|
||||||
|
bool MacAddress::fromString6(const char *buf) {
|
||||||
|
char cs[18]; // 17 + 1 for null terminator
|
||||||
|
char *token;
|
||||||
|
char *next; //Unused but required
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strncpy(cs, buf, sizeof(cs) - 1); //strtok modifies the buffer: copy to working buffer.
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
token = strtok((i == 0) ? cs : NULL, ":"); //Find first or next token
|
||||||
|
if (!token) { //No more tokens found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_mac.bytes[i] = strtol(token, &next, 16);
|
||||||
|
}
|
||||||
|
_type = MAC6;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacAddress::fromString8(const char *buf) {
|
||||||
|
char cs[24]; // 23 + 1 for null terminator
|
||||||
|
char *token;
|
||||||
|
char *next; //Unused but required
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strncpy(cs, buf, sizeof(cs) - 1); //strtok modifies the buffer: copy to working buffer.
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
token = strtok((i == 0) ? cs : NULL, ":"); //Find first or next token
|
||||||
|
if (!token) { //No more tokens found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_mac.bytes[i] = strtol(token, &next, 16);
|
||||||
|
}
|
||||||
|
_type = MAC8;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy MAC into byte array
|
||||||
|
void MacAddress::toBytes(uint8_t *buf) {
|
||||||
|
if (_type == MAC6) {
|
||||||
|
memcpy(buf, _mac.bytes, 6);
|
||||||
|
} else {
|
||||||
|
memcpy(buf, _mac.bytes, sizeof(_mac.bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Print MAC address into a C string.
|
||||||
|
//MAC: Buffer must be at least 18 chars
|
||||||
|
int MacAddress::toString(char *buf) {
|
||||||
|
if (_type == MAC6) {
|
||||||
|
return sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", _mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
|
||||||
|
} else {
|
||||||
|
return sprintf(
|
||||||
|
buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", _mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3], _mac.bytes[4], _mac.bytes[5], _mac.bytes[6],
|
||||||
|
_mac.bytes[7]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacAddress::toString() const {
|
||||||
|
uint8_t bytes = (_type == MAC6) ? 18 : 24;
|
||||||
|
char buf[bytes];
|
||||||
|
if (_type == MAC6) {
|
||||||
|
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X", _mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3], _mac.bytes[4], _mac.bytes[5]);
|
||||||
|
} else {
|
||||||
|
snprintf(
|
||||||
|
buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", _mac.bytes[0], _mac.bytes[1], _mac.bytes[2], _mac.bytes[3], _mac.bytes[4], _mac.bytes[5],
|
||||||
|
_mac.bytes[6], _mac.bytes[7]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t MacAddress::Value() {
|
||||||
|
return _mac.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Allow getting individual octets of the address. e.g. uint8_t b0 = ma[0];
|
||||||
|
uint8_t MacAddress::operator[](int index) const {
|
||||||
|
index = EnforceIndexBounds(index);
|
||||||
|
return _mac.bytes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Allow setting individual octets of the address. e.g. ma[2] = 255;
|
||||||
|
uint8_t &MacAddress::operator[](int index) {
|
||||||
|
index = EnforceIndexBounds(index);
|
||||||
|
return _mac.bytes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Overloaded copy operator: init MacAddress object from byte array
|
||||||
|
MacAddress &MacAddress::operator=(const uint8_t *macbytearray) {
|
||||||
|
// 6-bytes MacAddress only
|
||||||
|
_type = MAC6;
|
||||||
|
memset(_mac.bytes, 0, sizeof(_mac.bytes));
|
||||||
|
memcpy(_mac.bytes, macbytearray, 6);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Overloaded copy operator: init MacAddress object from uint64_t
|
||||||
|
MacAddress &MacAddress::operator=(uint64_t macval) {
|
||||||
|
// 6-bytes MacAddress only
|
||||||
|
_type = MAC6;
|
||||||
|
_mac.val = macval;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Compare class to byte array
|
||||||
|
bool MacAddress::operator==(const uint8_t *macbytearray) const {
|
||||||
|
return !memcmp(_mac.bytes, macbytearray, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Allow comparing value of two classes
|
||||||
|
bool MacAddress::operator==(const MacAddress &mac2) const {
|
||||||
|
return _mac.val == mac2._mac.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Type converter object to uint64_t [same as .Value()]
|
||||||
|
MacAddress::operator uint64_t() const {
|
||||||
|
return _mac.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Type converter object to read only pointer to mac bytes. e.g. const uint8_t *ip_8 = ma;
|
||||||
|
MacAddress::operator const uint8_t *() const {
|
||||||
|
return _mac.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Type converter object to read only pointer to mac value. e.g. const uint32_t *ip_64 = ma;
|
||||||
|
MacAddress::operator const uint64_t *() const {
|
||||||
|
return &_mac.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MacAddress::printTo(Print &p) const {
|
||||||
|
uint8_t bytes = (_type == MAC6) ? 6 : 8;
|
||||||
|
size_t n = 0;
|
||||||
|
for (int i = 0; i < bytes; i++) {
|
||||||
|
if (i) {
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
n += p.printf("%02X", _mac.bytes[i]);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bounds checking
|
||||||
|
int MacAddress::EnforceIndexBounds(int i) const {
|
||||||
|
if (i < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (_type == MAC6) {
|
||||||
|
if (i >= 6) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i >= 8) {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
104
cores/esp32/MacAddress.h
Normal file
104
cores/esp32/MacAddress.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// MacAddress.h - class to make it easier to handle BSSID and MAC addresses.
|
||||||
|
//
|
||||||
|
// Copyright 2022 David McCurley
|
||||||
|
// Modified by Espressif Systems 2024
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||||
|
// You may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef MacAddress_h
|
||||||
|
#define MacAddress_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <WString.h>
|
||||||
|
#include <Printable.h>
|
||||||
|
|
||||||
|
enum MACType {
|
||||||
|
MAC6,
|
||||||
|
MAC8
|
||||||
|
};
|
||||||
|
|
||||||
|
// A class to make it easier to handle and pass around MAC addresses, supporting both 6-byte and 8-byte MAC addresses.
|
||||||
|
class MacAddress : public Printable {
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
uint8_t bytes[8];
|
||||||
|
uint64_t val;
|
||||||
|
} _mac;
|
||||||
|
MACType _type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//Default MAC6
|
||||||
|
MacAddress();
|
||||||
|
|
||||||
|
MacAddress(MACType mac_type);
|
||||||
|
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6);
|
||||||
|
MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8);
|
||||||
|
|
||||||
|
MacAddress(MACType mac_type, uint64_t mac);
|
||||||
|
MacAddress(MACType mac_type, const uint8_t *macbytearray);
|
||||||
|
|
||||||
|
//Default MAC6
|
||||||
|
MacAddress(uint64_t mac) : MacAddress(MAC6, mac) {}
|
||||||
|
MacAddress(const uint8_t *macbytearray) : MacAddress(MAC6, macbytearray) {}
|
||||||
|
|
||||||
|
MacAddress(const char *macstr);
|
||||||
|
MacAddress(const String &macstr);
|
||||||
|
|
||||||
|
virtual ~MacAddress() {}
|
||||||
|
|
||||||
|
bool fromString(const char *buf);
|
||||||
|
bool fromString(const String &macstr) {
|
||||||
|
return fromString(macstr.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void toBytes(uint8_t *buf);
|
||||||
|
int toString(char *buf);
|
||||||
|
String toString() const;
|
||||||
|
uint64_t Value();
|
||||||
|
|
||||||
|
uint8_t operator[](int index) const;
|
||||||
|
uint8_t &operator[](int index);
|
||||||
|
|
||||||
|
//MAC6 only
|
||||||
|
MacAddress &operator=(const uint8_t *macbytearray);
|
||||||
|
MacAddress &operator=(uint64_t macval);
|
||||||
|
|
||||||
|
bool operator==(const uint8_t *macbytearray) const;
|
||||||
|
bool operator==(const MacAddress &mac2) const;
|
||||||
|
operator uint64_t() const;
|
||||||
|
operator const uint8_t *() const;
|
||||||
|
operator const uint64_t *() const;
|
||||||
|
|
||||||
|
virtual size_t printTo(Print &p) const;
|
||||||
|
|
||||||
|
// future use in Arduino Networking
|
||||||
|
/*
|
||||||
|
friend class EthernetClass;
|
||||||
|
friend class UDP;
|
||||||
|
friend class Client;
|
||||||
|
friend class Server;
|
||||||
|
friend class DhcpClass;
|
||||||
|
friend class DNSClient;
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool fromString6(const char *buf);
|
||||||
|
bool fromString8(const char *buf);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int EnforceIndexBounds(int i) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -29,351 +29,317 @@
|
||||||
|
|
||||||
#include "Print.h"
|
#include "Print.h"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public Methods //////////////////////////////////////////////////////////////
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/* default implementation: may be overridden */
|
/* default implementation: may be overridden */
|
||||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
size_t Print::write(const uint8_t *buffer, size_t size) {
|
||||||
{
|
size_t n = 0;
|
||||||
size_t n = 0;
|
while (size--) {
|
||||||
while(size--) {
|
n += write(*buffer++);
|
||||||
n += write(*buffer++);
|
}
|
||||||
}
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::vprintf(const char *format, va_list arg)
|
size_t Print::vprintf(const char *format, va_list arg) {
|
||||||
{
|
char loc_buf[64];
|
||||||
char loc_buf[64];
|
char *temp = loc_buf;
|
||||||
char * temp = loc_buf;
|
va_list copy;
|
||||||
va_list copy;
|
va_copy(copy, arg);
|
||||||
va_copy(copy, arg);
|
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||||
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
va_end(copy);
|
||||||
va_end(copy);
|
if (len < 0) {
|
||||||
if(len < 0) {
|
|
||||||
va_end(arg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(len >= (int)sizeof(loc_buf)){ // comparation of same sign type for the compiler
|
|
||||||
temp = (char*) malloc(len+1);
|
|
||||||
if(temp == NULL) {
|
|
||||||
va_end(arg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
len = vsnprintf(temp, len+1, format, arg);
|
|
||||||
}
|
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
len = write((uint8_t*)temp, len);
|
return 0;
|
||||||
if(temp != loc_buf){
|
}
|
||||||
free(temp);
|
if (len >= (int)sizeof(loc_buf)) { // comparison of same sign type for the compiler
|
||||||
|
temp = (char *)malloc(len + 1);
|
||||||
|
if (temp == NULL) {
|
||||||
|
va_end(arg);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return len;
|
len = vsnprintf(temp, len + 1, format, arg);
|
||||||
|
}
|
||||||
|
va_end(arg);
|
||||||
|
len = write((uint8_t *)temp, len);
|
||||||
|
if (temp != loc_buf) {
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::printf(const __FlashStringHelper *ifsh, ...)
|
size_t Print::printf(const __FlashStringHelper *ifsh, ...) {
|
||||||
{
|
va_list arg;
|
||||||
va_list arg;
|
va_start(arg, ifsh);
|
||||||
va_start(arg, ifsh);
|
const char *format = (reinterpret_cast<const char *>(ifsh));
|
||||||
const char * format = (reinterpret_cast<const char *>(ifsh));
|
size_t ret = vprintf(format, arg);
|
||||||
size_t ret = vprintf(format, arg);
|
va_end(arg);
|
||||||
va_end(arg);
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::printf(const char *format, ...)
|
size_t Print::printf(const char *format, ...) {
|
||||||
{
|
va_list arg;
|
||||||
va_list arg;
|
va_start(arg, format);
|
||||||
va_start(arg, format);
|
size_t ret = vprintf(format, arg);
|
||||||
size_t ret = vprintf(format, arg);
|
va_end(arg);
|
||||||
va_end(arg);
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(const String &s)
|
size_t Print::print(const String &s) {
|
||||||
{
|
return write(s.c_str(), s.length());
|
||||||
return write(s.c_str(), s.length());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(const char str[])
|
size_t Print::print(const char str[]) {
|
||||||
{
|
return write(str);
|
||||||
return write(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(char c)
|
size_t Print::print(char c) {
|
||||||
{
|
return write(c);
|
||||||
return write(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(unsigned char b, int base)
|
size_t Print::print(unsigned char b, int base) {
|
||||||
{
|
return print((unsigned long)b, base);
|
||||||
return print((unsigned long) b, base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(int n, int base)
|
size_t Print::print(int n, int base) {
|
||||||
{
|
return print((long)n, base);
|
||||||
return print((long) n, base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(unsigned int n, int base)
|
size_t Print::print(unsigned int n, int base) {
|
||||||
{
|
return print((unsigned long)n, base);
|
||||||
return print((unsigned long) n, base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(long n, int base)
|
size_t Print::print(long n, int base) {
|
||||||
{
|
int t = 0;
|
||||||
int t = 0;
|
if (base == 10 && n < 0) {
|
||||||
if (base == 10 && n < 0) {
|
t = print('-');
|
||||||
t = print('-');
|
n = -n;
|
||||||
n = -n;
|
}
|
||||||
}
|
return printNumber(static_cast<unsigned long>(n), base) + t;
|
||||||
return printNumber(static_cast<unsigned long>(n), base) + t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(unsigned long n, int base)
|
size_t Print::print(unsigned long n, int base) {
|
||||||
{
|
if (base == 0) {
|
||||||
if(base == 0) {
|
return write(n);
|
||||||
return write(n);
|
} else {
|
||||||
} else {
|
return printNumber(n, base);
|
||||||
return printNumber(n, base);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(long long n, int base)
|
size_t Print::print(long long n, int base) {
|
||||||
{
|
int t = 0;
|
||||||
int t = 0;
|
if (base == 10 && n < 0) {
|
||||||
if (base == 10 && n < 0) {
|
t = print('-');
|
||||||
t = print('-');
|
n = -n;
|
||||||
n = -n;
|
}
|
||||||
}
|
return printNumber(static_cast<unsigned long long>(n), base) + t;
|
||||||
return printNumber(static_cast<unsigned long long>(n), base) + t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(unsigned long long n, int base)
|
size_t Print::print(unsigned long long n, int base) {
|
||||||
{
|
if (base == 0) {
|
||||||
if (base == 0) {
|
return write(n);
|
||||||
return write(n);
|
} else {
|
||||||
} else {
|
return printNumber(n, base);
|
||||||
return printNumber(n, base);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(double n, int digits)
|
size_t Print::print(double n, int digits) {
|
||||||
{
|
return printFloat(n, digits);
|
||||||
return printFloat(n, digits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(const Printable& x)
|
size_t Print::print(const Printable &x) {
|
||||||
{
|
return x.printTo(*this);
|
||||||
return x.printTo(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::print(struct tm * timeinfo, const char * format)
|
size_t Print::print(struct tm *timeinfo, const char *format) {
|
||||||
{
|
const char *f = format;
|
||||||
const char * f = format;
|
if (!f) {
|
||||||
if(!f){
|
f = "%c";
|
||||||
f = "%c";
|
}
|
||||||
}
|
char buf[64];
|
||||||
char buf[64];
|
size_t written = strftime(buf, 64, f, timeinfo);
|
||||||
size_t written = strftime(buf, 64, f, timeinfo);
|
if (written == 0) {
|
||||||
if(written == 0){
|
return written;
|
||||||
return written;
|
}
|
||||||
}
|
return print(buf);
|
||||||
return print(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(void)
|
size_t Print::println(void) {
|
||||||
{
|
return print("\r\n");
|
||||||
return print("\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(const String &s)
|
size_t Print::println(const String &s) {
|
||||||
{
|
size_t n = print(s);
|
||||||
size_t n = print(s);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(const char c[])
|
size_t Print::println(const char c[]) {
|
||||||
{
|
size_t n = print(c);
|
||||||
size_t n = print(c);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(char c)
|
size_t Print::println(char c) {
|
||||||
{
|
size_t n = print(c);
|
||||||
size_t n = print(c);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(unsigned char b, int base)
|
size_t Print::println(unsigned char b, int base) {
|
||||||
{
|
size_t n = print(b, base);
|
||||||
size_t n = print(b, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(int num, int base)
|
size_t Print::println(int num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(unsigned int num, int base)
|
size_t Print::println(unsigned int num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(long num, int base)
|
size_t Print::println(long num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(unsigned long num, int base)
|
size_t Print::println(unsigned long num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(long long num, int base)
|
size_t Print::println(long long num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(unsigned long long num, int base)
|
size_t Print::println(unsigned long long num, int base) {
|
||||||
{
|
size_t n = print(num, base);
|
||||||
size_t n = print(num, base);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(double num, int digits)
|
size_t Print::println(double num, int digits) {
|
||||||
{
|
size_t n = print(num, digits);
|
||||||
size_t n = print(num, digits);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(const Printable& x)
|
size_t Print::println(const Printable &x) {
|
||||||
{
|
size_t n = print(x);
|
||||||
size_t n = print(x);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::println(struct tm * timeinfo, const char * format)
|
size_t Print::println(struct tm *timeinfo, const char *format) {
|
||||||
{
|
size_t n = print(timeinfo, format);
|
||||||
size_t n = print(timeinfo, format);
|
n += println();
|
||||||
n += println();
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private Methods /////////////////////////////////////////////////////////////
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
size_t Print::printNumber(unsigned long n, uint8_t base)
|
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||||
{
|
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
char *str = &buf[sizeof(buf) - 1];
|
||||||
char *str = &buf[sizeof(buf) - 1];
|
|
||||||
|
|
||||||
*str = '\0';
|
*str = '\0';
|
||||||
|
|
||||||
// prevent crash if called with base == 1
|
// prevent crash if called with base == 1
|
||||||
if(base < 2) {
|
if (base < 2) {
|
||||||
base = 10;
|
base = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
char c = n % base;
|
char c = n % base;
|
||||||
n /= base;
|
n /= base;
|
||||||
|
|
||||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
} while (n);
|
} while (n);
|
||||||
|
|
||||||
return write(str);
|
return write(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::printNumber(unsigned long long n, uint8_t base)
|
size_t Print::printNumber(unsigned long long n, uint8_t base) {
|
||||||
{
|
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
char *str = &buf[sizeof(buf) - 1];
|
||||||
char* str = &buf[sizeof(buf) - 1];
|
|
||||||
|
|
||||||
*str = '\0';
|
*str = '\0';
|
||||||
|
|
||||||
// prevent crash if called with base == 1
|
// prevent crash if called with base == 1
|
||||||
if (base < 2) {
|
if (base < 2) {
|
||||||
base = 10;
|
base = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
auto m = n;
|
auto m = n;
|
||||||
n /= base;
|
n /= base;
|
||||||
char c = m - base * n;
|
char c = m - base * n;
|
||||||
|
|
||||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
} while (n);
|
} while (n);
|
||||||
|
|
||||||
return write(str);
|
return write(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Print::printFloat(double number, uint8_t digits)
|
size_t Print::printFloat(double number, uint8_t digits) {
|
||||||
{
|
size_t n = 0;
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
if(isnan(number)) {
|
if (isnan(number)) {
|
||||||
return print("nan");
|
return print("nan");
|
||||||
}
|
}
|
||||||
if(isinf(number)) {
|
if (isinf(number)) {
|
||||||
return print("inf");
|
return print("inf");
|
||||||
}
|
}
|
||||||
if(number > 4294967040.0) {
|
if (number > 4294967040.0) {
|
||||||
return print("ovf"); // constant determined empirically
|
return print("ovf"); // constant determined empirically
|
||||||
}
|
}
|
||||||
if(number < -4294967040.0) {
|
if (number < -4294967040.0) {
|
||||||
return print("ovf"); // constant determined empirically
|
return print("ovf"); // constant determined empirically
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle negative numbers
|
// Handle negative numbers
|
||||||
if(number < 0.0) {
|
if (number < 0.0) {
|
||||||
n += print('-');
|
n += print('-');
|
||||||
number = -number;
|
number = -number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
double rounding = 0.5;
|
double rounding = 0.5;
|
||||||
for(uint8_t i = 0; i < digits; ++i) {
|
for (uint8_t i = 0; i < digits; ++i) {
|
||||||
rounding /= 10.0;
|
rounding /= 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
number += rounding;
|
number += rounding;
|
||||||
|
|
||||||
// Extract the integer part of the number and print it
|
// Extract the integer part of the number and print it
|
||||||
unsigned long int_part = (unsigned long) number;
|
unsigned long int_part = (unsigned long)number;
|
||||||
double remainder = number - (double) int_part;
|
double remainder = number - (double)int_part;
|
||||||
n += print(int_part);
|
n += print(int_part);
|
||||||
|
|
||||||
// Print the decimal point, but only if there are digits beyond
|
// Print the decimal point, but only if there are digits beyond
|
||||||
if(digits > 0) {
|
if (digits > 0) {
|
||||||
n += print(".");
|
n += print(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract digits from the remainder one at a time
|
// Extract digits from the remainder one at a time
|
||||||
while(digits-- > 0) {
|
while (digits-- > 0) {
|
||||||
remainder *= 10.0;
|
remainder *= 10.0;
|
||||||
int toPrint = int(remainder);
|
int toPrint = int(remainder);
|
||||||
n += print(toPrint);
|
n += print(toPrint);
|
||||||
remainder -= toPrint;
|
remainder -= toPrint;
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,89 +32,87 @@
|
||||||
#define OCT 8
|
#define OCT 8
|
||||||
#define BIN 2
|
#define BIN 2
|
||||||
|
|
||||||
class Print
|
class Print {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
int write_error;
|
int write_error;
|
||||||
size_t printNumber(unsigned long, uint8_t);
|
size_t printNumber(unsigned long, uint8_t);
|
||||||
size_t printNumber(unsigned long long, uint8_t);
|
size_t printNumber(unsigned long long, uint8_t);
|
||||||
size_t printFloat(double, uint8_t);
|
size_t printFloat(double, uint8_t);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setWriteError(int err = 1)
|
void setWriteError(int err = 1) {
|
||||||
{
|
write_error = err;
|
||||||
write_error = err;
|
}
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
Print() :
|
Print() : write_error(0) {}
|
||||||
write_error(0)
|
virtual ~Print() {}
|
||||||
{
|
int getWriteError() {
|
||||||
}
|
return write_error;
|
||||||
virtual ~Print() {}
|
}
|
||||||
int getWriteError()
|
void clearWriteError() {
|
||||||
{
|
setWriteError(0);
|
||||||
return write_error;
|
}
|
||||||
}
|
|
||||||
void clearWriteError()
|
virtual size_t write(uint8_t) = 0;
|
||||||
{
|
size_t write(const char *str) {
|
||||||
setWriteError(0);
|
if (str == NULL) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
return write((const uint8_t *)str, strlen(str));
|
||||||
|
}
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
size_t write(const char *buffer, size_t size) {
|
||||||
|
return write((const uint8_t *)buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
virtual size_t write(uint8_t) = 0;
|
size_t vprintf(const char *format, va_list arg);
|
||||||
size_t write(const char *str)
|
|
||||||
{
|
|
||||||
if(str == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return write((const uint8_t *) str, strlen(str));
|
|
||||||
}
|
|
||||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
|
||||||
size_t write(const char *buffer, size_t size)
|
|
||||||
{
|
|
||||||
return write((const uint8_t *) buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t vprintf(const char *format, va_list arg);
|
size_t printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||||
|
size_t printf(const __FlashStringHelper *ifsh, ...);
|
||||||
|
|
||||||
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
// add availableForWrite to make compatible with Arduino Print.h
|
||||||
size_t printf(const __FlashStringHelper *ifsh, ...);
|
// default to zero, meaning "a single write may block"
|
||||||
|
// should be overridden by subclasses with buffering
|
||||||
|
virtual int availableForWrite() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t print(const __FlashStringHelper *ifsh) {
|
||||||
|
return print(reinterpret_cast<const char *>(ifsh));
|
||||||
|
}
|
||||||
|
size_t print(const String &);
|
||||||
|
size_t print(const char[]);
|
||||||
|
size_t print(char);
|
||||||
|
size_t print(unsigned char, int = DEC);
|
||||||
|
size_t print(int, int = DEC);
|
||||||
|
size_t print(unsigned int, int = DEC);
|
||||||
|
size_t print(long, int = DEC);
|
||||||
|
size_t print(unsigned long, int = DEC);
|
||||||
|
size_t print(long long, int = DEC);
|
||||||
|
size_t print(unsigned long long, int = DEC);
|
||||||
|
size_t print(double, int = 2);
|
||||||
|
size_t print(const Printable &);
|
||||||
|
size_t print(struct tm *timeinfo, const char *format = NULL);
|
||||||
|
|
||||||
// add availableForWrite to make compatible with Arduino Print.h
|
size_t println(const __FlashStringHelper *ifsh) {
|
||||||
// default to zero, meaning "a single write may block"
|
return println(reinterpret_cast<const char *>(ifsh));
|
||||||
// should be overriden by subclasses with buffering
|
}
|
||||||
virtual int availableForWrite() { return 0; }
|
size_t println(const String &s);
|
||||||
size_t print(const __FlashStringHelper *ifsh) { return print(reinterpret_cast<const char *>(ifsh)); }
|
size_t println(const char[]);
|
||||||
size_t print(const String &);
|
size_t println(char);
|
||||||
size_t print(const char[]);
|
size_t println(unsigned char, int = DEC);
|
||||||
size_t print(char);
|
size_t println(int, int = DEC);
|
||||||
size_t print(unsigned char, int = DEC);
|
size_t println(unsigned int, int = DEC);
|
||||||
size_t print(int, int = DEC);
|
size_t println(long, int = DEC);
|
||||||
size_t print(unsigned int, int = DEC);
|
size_t println(unsigned long, int = DEC);
|
||||||
size_t print(long, int = DEC);
|
size_t println(long long, int = DEC);
|
||||||
size_t print(unsigned long, int = DEC);
|
size_t println(unsigned long long, int = DEC);
|
||||||
size_t print(long long, int = DEC);
|
size_t println(double, int = 2);
|
||||||
size_t print(unsigned long long, int = DEC);
|
size_t println(const Printable &);
|
||||||
size_t print(double, int = 2);
|
size_t println(struct tm *timeinfo, const char *format = NULL);
|
||||||
size_t print(const Printable&);
|
size_t println(void);
|
||||||
size_t print(struct tm * timeinfo, const char * format = NULL);
|
|
||||||
|
|
||||||
size_t println(const __FlashStringHelper *ifsh) { return println(reinterpret_cast<const char *>(ifsh)); }
|
|
||||||
size_t println(const String &s);
|
|
||||||
size_t println(const char[]);
|
|
||||||
size_t println(char);
|
|
||||||
size_t println(unsigned char, int = DEC);
|
|
||||||
size_t println(int, int = DEC);
|
|
||||||
size_t println(unsigned int, int = DEC);
|
|
||||||
size_t println(long, int = DEC);
|
|
||||||
size_t println(unsigned long, int = DEC);
|
|
||||||
size_t println(long long, int = DEC);
|
|
||||||
size_t println(unsigned long long, int = DEC);
|
|
||||||
size_t println(double, int = 2);
|
|
||||||
size_t println(const Printable&);
|
|
||||||
size_t println(struct tm * timeinfo, const char * format = NULL);
|
|
||||||
size_t println(void);
|
|
||||||
|
|
||||||
virtual void flush() { /* Empty implementation for backward compatibility */ }
|
|
||||||
|
|
||||||
|
virtual void flush() { /* Empty implementation for backward compatibility */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,10 @@ class Print;
|
||||||
Print::print and Print::println methods.
|
Print::print and Print::println methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Printable
|
class Printable {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual ~Printable() {}
|
virtual ~Printable() {}
|
||||||
virtual size_t printTo(Print& p) const = 0;
|
virtual size_t printTo(Print &p) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,342 +26,315 @@
|
||||||
// 32-bit integer manipulation macros (big endian)
|
// 32-bit integer manipulation macros (big endian)
|
||||||
|
|
||||||
#ifndef GET_UINT32_BE
|
#ifndef GET_UINT32_BE
|
||||||
#define GET_UINT32_BE(n,b,i) \
|
#define GET_UINT32_BE(n, b, i) \
|
||||||
{ \
|
{ (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); }
|
||||||
(n) = ((uint32_t) (b)[(i) ] << 24) \
|
|
||||||
| ((uint32_t) (b)[(i) + 1] << 16) \
|
|
||||||
| ((uint32_t) (b)[(i) + 2] << 8) \
|
|
||||||
| ((uint32_t) (b)[(i) + 3] ); \
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PUT_UINT32_BE
|
#ifndef PUT_UINT32_BE
|
||||||
#define PUT_UINT32_BE(n,b,i) \
|
#define PUT_UINT32_BE(n, b, i) \
|
||||||
{ \
|
{ \
|
||||||
(b)[(i) ] = (uint8_t) ((n) >> 24); \
|
(b)[(i)] = (uint8_t)((n) >> 24); \
|
||||||
(b)[(i) + 1] = (uint8_t) ((n) >> 16); \
|
(b)[(i) + 1] = (uint8_t)((n) >> 16); \
|
||||||
(b)[(i) + 2] = (uint8_t) ((n) >> 8); \
|
(b)[(i) + 2] = (uint8_t)((n) >> 8); \
|
||||||
(b)[(i) + 3] = (uint8_t) ((n) ); \
|
(b)[(i) + 3] = (uint8_t)((n)); \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
static const uint8_t sha1_padding[64] =
|
static const uint8_t sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
{
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
|
|
||||||
void SHA1Builder::process(const uint8_t* data)
|
void SHA1Builder::process(const uint8_t *data) {
|
||||||
{
|
uint32_t temp, W[16], A, B, C, D, E;
|
||||||
uint32_t temp, W[16], A, B, C, D, E;
|
|
||||||
|
|
||||||
GET_UINT32_BE(W[ 0], data, 0);
|
GET_UINT32_BE(W[0], data, 0);
|
||||||
GET_UINT32_BE(W[ 1], data, 4);
|
GET_UINT32_BE(W[1], data, 4);
|
||||||
GET_UINT32_BE(W[ 2], data, 8);
|
GET_UINT32_BE(W[2], data, 8);
|
||||||
GET_UINT32_BE(W[ 3], data, 12);
|
GET_UINT32_BE(W[3], data, 12);
|
||||||
GET_UINT32_BE(W[ 4], data, 16);
|
GET_UINT32_BE(W[4], data, 16);
|
||||||
GET_UINT32_BE(W[ 5], data, 20);
|
GET_UINT32_BE(W[5], data, 20);
|
||||||
GET_UINT32_BE(W[ 6], data, 24);
|
GET_UINT32_BE(W[6], data, 24);
|
||||||
GET_UINT32_BE(W[ 7], data, 28);
|
GET_UINT32_BE(W[7], data, 28);
|
||||||
GET_UINT32_BE(W[ 8], data, 32);
|
GET_UINT32_BE(W[8], data, 32);
|
||||||
GET_UINT32_BE(W[ 9], data, 36);
|
GET_UINT32_BE(W[9], data, 36);
|
||||||
GET_UINT32_BE(W[10], data, 40);
|
GET_UINT32_BE(W[10], data, 40);
|
||||||
GET_UINT32_BE(W[11], data, 44);
|
GET_UINT32_BE(W[11], data, 44);
|
||||||
GET_UINT32_BE(W[12], data, 48);
|
GET_UINT32_BE(W[12], data, 48);
|
||||||
GET_UINT32_BE(W[13], data, 52);
|
GET_UINT32_BE(W[13], data, 52);
|
||||||
GET_UINT32_BE(W[14], data, 56);
|
GET_UINT32_BE(W[14], data, 56);
|
||||||
GET_UINT32_BE(W[15], data, 60);
|
GET_UINT32_BE(W[15], data, 60);
|
||||||
|
|
||||||
#define sha1_S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
#define sha1_S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||||
|
|
||||||
#define sha1_R(t) \
|
#define sha1_R(t) (temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ W[t & 0x0F], (W[t & 0x0F] = sha1_S(temp, 1)))
|
||||||
( \
|
|
||||||
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
|
|
||||||
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
|
|
||||||
(W[t & 0x0F] = sha1_S(temp,1)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define sha1_P(a,b,c,d,e,x) \
|
#define sha1_P(a, b, c, d, e, x) \
|
||||||
{ \
|
{ \
|
||||||
e += sha1_S(a,5) + sha1_F(b,c,d) + sha1_K + x; b = sha1_S(b,30); \
|
e += sha1_S(a, 5) + sha1_F(b, c, d) + sha1_K + x; \
|
||||||
}
|
b = sha1_S(b, 30); \
|
||||||
|
}
|
||||||
|
|
||||||
A = state[0];
|
A = state[0];
|
||||||
B = state[1];
|
B = state[1];
|
||||||
C = state[2];
|
C = state[2];
|
||||||
D = state[3];
|
D = state[3];
|
||||||
E = state[4];
|
E = state[4];
|
||||||
|
|
||||||
#define sha1_F(x,y,z) (z ^ (x & (y ^ z)))
|
#define sha1_F(x, y, z) (z ^ (x & (y ^ z)))
|
||||||
#define sha1_K 0x5A827999
|
#define sha1_K 0x5A827999
|
||||||
|
|
||||||
sha1_P(A, B, C, D, E, W[0]);
|
sha1_P(A, B, C, D, E, W[0]);
|
||||||
sha1_P(E, A, B, C, D, W[1]);
|
sha1_P(E, A, B, C, D, W[1]);
|
||||||
sha1_P(D, E, A, B, C, W[2]);
|
sha1_P(D, E, A, B, C, W[2]);
|
||||||
sha1_P(C, D, E, A, B, W[3]);
|
sha1_P(C, D, E, A, B, W[3]);
|
||||||
sha1_P(B, C, D, E, A, W[4]);
|
sha1_P(B, C, D, E, A, W[4]);
|
||||||
sha1_P(A, B, C, D, E, W[5]);
|
sha1_P(A, B, C, D, E, W[5]);
|
||||||
sha1_P(E, A, B, C, D, W[6]);
|
sha1_P(E, A, B, C, D, W[6]);
|
||||||
sha1_P(D, E, A, B, C, W[7]);
|
sha1_P(D, E, A, B, C, W[7]);
|
||||||
sha1_P(C, D, E, A, B, W[8]);
|
sha1_P(C, D, E, A, B, W[8]);
|
||||||
sha1_P(B, C, D, E, A, W[9]);
|
sha1_P(B, C, D, E, A, W[9]);
|
||||||
sha1_P(A, B, C, D, E, W[10]);
|
sha1_P(A, B, C, D, E, W[10]);
|
||||||
sha1_P(E, A, B, C, D, W[11]);
|
sha1_P(E, A, B, C, D, W[11]);
|
||||||
sha1_P(D, E, A, B, C, W[12]);
|
sha1_P(D, E, A, B, C, W[12]);
|
||||||
sha1_P(C, D, E, A, B, W[13]);
|
sha1_P(C, D, E, A, B, W[13]);
|
||||||
sha1_P(B, C, D, E, A, W[14]);
|
sha1_P(B, C, D, E, A, W[14]);
|
||||||
sha1_P(A, B, C, D, E, W[15]);
|
sha1_P(A, B, C, D, E, W[15]);
|
||||||
sha1_P(E, A, B, C, D, sha1_R(16));
|
sha1_P(E, A, B, C, D, sha1_R(16));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(17));
|
sha1_P(D, E, A, B, C, sha1_R(17));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(18));
|
sha1_P(C, D, E, A, B, sha1_R(18));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(19));
|
sha1_P(B, C, D, E, A, sha1_R(19));
|
||||||
|
|
||||||
#undef sha1_K
|
#undef sha1_K
|
||||||
#undef sha1_F
|
#undef sha1_F
|
||||||
|
|
||||||
#define sha1_F(x,y,z) (x ^ y ^ z)
|
#define sha1_F(x, y, z) (x ^ y ^ z)
|
||||||
#define sha1_K 0x6ED9EBA1
|
#define sha1_K 0x6ED9EBA1
|
||||||
|
|
||||||
sha1_P(A, B, C, D, E, sha1_R(20));
|
sha1_P(A, B, C, D, E, sha1_R(20));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(21));
|
sha1_P(E, A, B, C, D, sha1_R(21));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(22));
|
sha1_P(D, E, A, B, C, sha1_R(22));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(23));
|
sha1_P(C, D, E, A, B, sha1_R(23));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(24));
|
sha1_P(B, C, D, E, A, sha1_R(24));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(25));
|
sha1_P(A, B, C, D, E, sha1_R(25));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(26));
|
sha1_P(E, A, B, C, D, sha1_R(26));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(27));
|
sha1_P(D, E, A, B, C, sha1_R(27));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(28));
|
sha1_P(C, D, E, A, B, sha1_R(28));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(29));
|
sha1_P(B, C, D, E, A, sha1_R(29));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(30));
|
sha1_P(A, B, C, D, E, sha1_R(30));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(31));
|
sha1_P(E, A, B, C, D, sha1_R(31));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(32));
|
sha1_P(D, E, A, B, C, sha1_R(32));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(33));
|
sha1_P(C, D, E, A, B, sha1_R(33));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(34));
|
sha1_P(B, C, D, E, A, sha1_R(34));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(35));
|
sha1_P(A, B, C, D, E, sha1_R(35));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(36));
|
sha1_P(E, A, B, C, D, sha1_R(36));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(37));
|
sha1_P(D, E, A, B, C, sha1_R(37));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(38));
|
sha1_P(C, D, E, A, B, sha1_R(38));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(39));
|
sha1_P(B, C, D, E, A, sha1_R(39));
|
||||||
|
|
||||||
#undef sha1_K
|
#undef sha1_K
|
||||||
#undef sha1_F
|
#undef sha1_F
|
||||||
|
|
||||||
#define sha1_F(x,y,z) ((x & y) | (z & (x | y)))
|
#define sha1_F(x, y, z) ((x & y) | (z & (x | y)))
|
||||||
#define sha1_K 0x8F1BBCDC
|
#define sha1_K 0x8F1BBCDC
|
||||||
|
|
||||||
sha1_P(A, B, C, D, E, sha1_R(40));
|
sha1_P(A, B, C, D, E, sha1_R(40));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(41));
|
sha1_P(E, A, B, C, D, sha1_R(41));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(42));
|
sha1_P(D, E, A, B, C, sha1_R(42));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(43));
|
sha1_P(C, D, E, A, B, sha1_R(43));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(44));
|
sha1_P(B, C, D, E, A, sha1_R(44));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(45));
|
sha1_P(A, B, C, D, E, sha1_R(45));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(46));
|
sha1_P(E, A, B, C, D, sha1_R(46));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(47));
|
sha1_P(D, E, A, B, C, sha1_R(47));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(48));
|
sha1_P(C, D, E, A, B, sha1_R(48));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(49));
|
sha1_P(B, C, D, E, A, sha1_R(49));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(50));
|
sha1_P(A, B, C, D, E, sha1_R(50));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(51));
|
sha1_P(E, A, B, C, D, sha1_R(51));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(52));
|
sha1_P(D, E, A, B, C, sha1_R(52));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(53));
|
sha1_P(C, D, E, A, B, sha1_R(53));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(54));
|
sha1_P(B, C, D, E, A, sha1_R(54));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(55));
|
sha1_P(A, B, C, D, E, sha1_R(55));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(56));
|
sha1_P(E, A, B, C, D, sha1_R(56));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(57));
|
sha1_P(D, E, A, B, C, sha1_R(57));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(58));
|
sha1_P(C, D, E, A, B, sha1_R(58));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(59));
|
sha1_P(B, C, D, E, A, sha1_R(59));
|
||||||
|
|
||||||
#undef sha1_K
|
#undef sha1_K
|
||||||
#undef sha1_F
|
#undef sha1_F
|
||||||
|
|
||||||
#define sha1_F(x,y,z) (x ^ y ^ z)
|
#define sha1_F(x, y, z) (x ^ y ^ z)
|
||||||
#define sha1_K 0xCA62C1D6
|
#define sha1_K 0xCA62C1D6
|
||||||
|
|
||||||
sha1_P(A, B, C, D, E, sha1_R(60));
|
sha1_P(A, B, C, D, E, sha1_R(60));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(61));
|
sha1_P(E, A, B, C, D, sha1_R(61));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(62));
|
sha1_P(D, E, A, B, C, sha1_R(62));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(63));
|
sha1_P(C, D, E, A, B, sha1_R(63));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(64));
|
sha1_P(B, C, D, E, A, sha1_R(64));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(65));
|
sha1_P(A, B, C, D, E, sha1_R(65));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(66));
|
sha1_P(E, A, B, C, D, sha1_R(66));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(67));
|
sha1_P(D, E, A, B, C, sha1_R(67));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(68));
|
sha1_P(C, D, E, A, B, sha1_R(68));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(69));
|
sha1_P(B, C, D, E, A, sha1_R(69));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(70));
|
sha1_P(A, B, C, D, E, sha1_R(70));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(71));
|
sha1_P(E, A, B, C, D, sha1_R(71));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(72));
|
sha1_P(D, E, A, B, C, sha1_R(72));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(73));
|
sha1_P(C, D, E, A, B, sha1_R(73));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(74));
|
sha1_P(B, C, D, E, A, sha1_R(74));
|
||||||
sha1_P(A, B, C, D, E, sha1_R(75));
|
sha1_P(A, B, C, D, E, sha1_R(75));
|
||||||
sha1_P(E, A, B, C, D, sha1_R(76));
|
sha1_P(E, A, B, C, D, sha1_R(76));
|
||||||
sha1_P(D, E, A, B, C, sha1_R(77));
|
sha1_P(D, E, A, B, C, sha1_R(77));
|
||||||
sha1_P(C, D, E, A, B, sha1_R(78));
|
sha1_P(C, D, E, A, B, sha1_R(78));
|
||||||
sha1_P(B, C, D, E, A, sha1_R(79));
|
sha1_P(B, C, D, E, A, sha1_R(79));
|
||||||
|
|
||||||
#undef sha1_K
|
#undef sha1_K
|
||||||
#undef sha1_F
|
#undef sha1_F
|
||||||
|
|
||||||
state[0] += A;
|
state[0] += A;
|
||||||
state[1] += B;
|
state[1] += B;
|
||||||
state[2] += C;
|
state[2] += C;
|
||||||
state[3] += D;
|
state[3] += D;
|
||||||
state[4] += E;
|
state[4] += E;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public methods
|
// Public methods
|
||||||
|
|
||||||
void SHA1Builder::begin(void)
|
void SHA1Builder::begin(void) {
|
||||||
{
|
total[0] = 0;
|
||||||
total[0] = 0;
|
total[1] = 0;
|
||||||
total[1] = 0;
|
|
||||||
|
|
||||||
state[0] = 0x67452301;
|
state[0] = 0x67452301;
|
||||||
state[1] = 0xEFCDAB89;
|
state[1] = 0xEFCDAB89;
|
||||||
state[2] = 0x98BADCFE;
|
state[2] = 0x98BADCFE;
|
||||||
state[3] = 0x10325476;
|
state[3] = 0x10325476;
|
||||||
state[4] = 0xC3D2E1F0;
|
state[4] = 0xC3D2E1F0;
|
||||||
|
|
||||||
memset(buffer, 0x00, sizeof(buffer));
|
memset(buffer, 0x00, sizeof(buffer));
|
||||||
memset(hash, 0x00, sizeof(hash));
|
memset(hash, 0x00, sizeof(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Builder::add(const uint8_t* data, size_t len)
|
void SHA1Builder::add(const uint8_t *data, size_t len) {
|
||||||
{
|
size_t fill;
|
||||||
size_t fill;
|
uint32_t left;
|
||||||
uint32_t left;
|
|
||||||
|
|
||||||
if(len == 0)
|
if (len == 0) {
|
||||||
{
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
left = total[0] & 0x3F;
|
left = total[0] & 0x3F;
|
||||||
fill = 64 - left;
|
fill = 64 - left;
|
||||||
|
|
||||||
total[0] += (uint32_t) len;
|
total[0] += (uint32_t)len;
|
||||||
total[0] &= 0xFFFFFFFF;
|
total[0] &= 0xFFFFFFFF;
|
||||||
|
|
||||||
if(total[0] < (uint32_t) len)
|
if (total[0] < (uint32_t)len) {
|
||||||
{
|
total[1]++;
|
||||||
total[1]++;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(left && len >= fill)
|
if (left && len >= fill) {
|
||||||
{
|
memcpy((void *)(buffer + left), data, fill);
|
||||||
memcpy((void *) (buffer + left), data, fill);
|
process(buffer);
|
||||||
process(buffer);
|
data += fill;
|
||||||
data += fill;
|
len -= fill;
|
||||||
len -= fill;
|
left = 0;
|
||||||
left = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while(len >= 64)
|
while (len >= 64) {
|
||||||
{
|
process(data);
|
||||||
process(data);
|
data += 64;
|
||||||
data += 64;
|
len -= 64;
|
||||||
len -= 64;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(len > 0) {
|
if (len > 0) {
|
||||||
memcpy((void *) (buffer + left), data, len);
|
memcpy((void *)(buffer + left), data, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Builder::addHexString(const char * data)
|
void SHA1Builder::addHexString(const char *data) {
|
||||||
{
|
uint16_t len = strlen(data);
|
||||||
uint16_t len = strlen(data);
|
uint8_t *tmp = (uint8_t *)malloc(len / 2);
|
||||||
uint8_t * tmp = (uint8_t*)malloc(len/2);
|
if (tmp == NULL) {
|
||||||
if(tmp == NULL) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
hex2bytes(tmp, len / 2, data);
|
||||||
hex2bytes(tmp, len/2, data);
|
add(tmp, len / 2);
|
||||||
add(tmp, len/2);
|
free(tmp);
|
||||||
free(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHA1Builder::addStream(Stream & stream, const size_t maxLen)
|
bool SHA1Builder::addStream(Stream &stream, const size_t maxLen) {
|
||||||
{
|
const int buf_size = 512;
|
||||||
const int buf_size = 512;
|
int maxLengthLeft = maxLen;
|
||||||
int maxLengthLeft = maxLen;
|
uint8_t *buf = (uint8_t *)malloc(buf_size);
|
||||||
uint8_t * buf = (uint8_t*) malloc(buf_size);
|
|
||||||
|
|
||||||
if(!buf) {
|
if (!buf) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytesAvailable = stream.available();
|
||||||
|
while ((bytesAvailable > 0) && (maxLengthLeft > 0)) {
|
||||||
|
|
||||||
|
// determine number of bytes to read
|
||||||
|
int readBytes = bytesAvailable;
|
||||||
|
if (readBytes > maxLengthLeft) {
|
||||||
|
readBytes = maxLengthLeft; // read only until max_len
|
||||||
|
}
|
||||||
|
if (readBytes > buf_size) {
|
||||||
|
readBytes = buf_size; // not read more the buffer can handle
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytesAvailable = stream.available();
|
// read data and check if we got something
|
||||||
while((bytesAvailable > 0) && (maxLengthLeft > 0)) {
|
int numBytesRead = stream.readBytes(buf, readBytes);
|
||||||
|
if (numBytesRead < 1) {
|
||||||
// determine number of bytes to read
|
free(buf);
|
||||||
int readBytes = bytesAvailable;
|
return false;
|
||||||
if(readBytes > maxLengthLeft) {
|
|
||||||
readBytes = maxLengthLeft ; // read only until max_len
|
|
||||||
}
|
|
||||||
if(readBytes > buf_size) {
|
|
||||||
readBytes = buf_size; // not read more the buffer can handle
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data and check if we got something
|
|
||||||
int numBytesRead = stream.readBytes(buf, readBytes);
|
|
||||||
if(numBytesRead< 1) {
|
|
||||||
free(buf);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update SHA1 with buffer payload
|
|
||||||
add(buf, numBytesRead);
|
|
||||||
|
|
||||||
// update available number of bytes
|
|
||||||
maxLengthLeft -= numBytesRead;
|
|
||||||
bytesAvailable = stream.available();
|
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
return true;
|
// Update SHA1 with buffer payload
|
||||||
|
add(buf, numBytesRead);
|
||||||
|
|
||||||
|
// update available number of bytes
|
||||||
|
maxLengthLeft -= numBytesRead;
|
||||||
|
bytesAvailable = stream.available();
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Builder::calculate(void)
|
void SHA1Builder::calculate(void) {
|
||||||
{
|
uint32_t last, padn;
|
||||||
uint32_t last, padn;
|
uint32_t high, low;
|
||||||
uint32_t high, low;
|
uint8_t msglen[8];
|
||||||
uint8_t msglen[8];
|
|
||||||
|
|
||||||
high = (total[0] >> 29) | (total[1] << 3);
|
high = (total[0] >> 29) | (total[1] << 3);
|
||||||
low = (total[0] << 3);
|
low = (total[0] << 3);
|
||||||
|
|
||||||
PUT_UINT32_BE(high, msglen, 0);
|
PUT_UINT32_BE(high, msglen, 0);
|
||||||
PUT_UINT32_BE(low, msglen, 4);
|
PUT_UINT32_BE(low, msglen, 4);
|
||||||
|
|
||||||
last = total[0] & 0x3F;
|
last = total[0] & 0x3F;
|
||||||
padn = (last < 56) ? (56 - last) : (120 - last);
|
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||||
|
|
||||||
add((uint8_t*)sha1_padding, padn);
|
add((uint8_t *)sha1_padding, padn);
|
||||||
add(msglen, 8);
|
add(msglen, 8);
|
||||||
|
|
||||||
PUT_UINT32_BE(state[0], hash, 0);
|
PUT_UINT32_BE(state[0], hash, 0);
|
||||||
PUT_UINT32_BE(state[1], hash, 4);
|
PUT_UINT32_BE(state[1], hash, 4);
|
||||||
PUT_UINT32_BE(state[2], hash, 8);
|
PUT_UINT32_BE(state[2], hash, 8);
|
||||||
PUT_UINT32_BE(state[3], hash, 12);
|
PUT_UINT32_BE(state[3], hash, 12);
|
||||||
PUT_UINT32_BE(state[4], hash, 16);
|
PUT_UINT32_BE(state[4], hash, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Builder::getBytes(uint8_t * output)
|
void SHA1Builder::getBytes(uint8_t *output) {
|
||||||
{
|
memcpy(output, hash, SHA1_HASH_SIZE);
|
||||||
memcpy(output, hash, SHA1_HASH_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Builder::getChars(char * output)
|
void SHA1Builder::getChars(char *output) {
|
||||||
{
|
bytes2hex(output, SHA1_HASH_SIZE * 2 + 1, hash, SHA1_HASH_SIZE);
|
||||||
bytes2hex(output, SHA1_HASH_SIZE*2+1, hash, SHA1_HASH_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String SHA1Builder::toString(void)
|
String SHA1Builder::toString(void) {
|
||||||
{
|
char out[(SHA1_HASH_SIZE * 2) + 1];
|
||||||
char out[(SHA1_HASH_SIZE * 2) + 1];
|
getChars(out);
|
||||||
getChars(out);
|
return String(out);
|
||||||
return String(out);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,30 +22,29 @@
|
||||||
|
|
||||||
#define SHA1_HASH_SIZE 20
|
#define SHA1_HASH_SIZE 20
|
||||||
|
|
||||||
class SHA1Builder : public HashBuilder
|
class SHA1Builder : public HashBuilder {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
uint32_t total[2]; /* number of bytes processed */
|
uint32_t total[2]; /* number of bytes processed */
|
||||||
uint32_t state[5]; /* intermediate digest state */
|
uint32_t state[5]; /* intermediate digest state */
|
||||||
unsigned char buffer[64]; /* data block being processed */
|
unsigned char buffer[64]; /* data block being processed */
|
||||||
uint8_t hash[SHA1_HASH_SIZE]; /* SHA-1 result */
|
uint8_t hash[SHA1_HASH_SIZE]; /* SHA-1 result */
|
||||||
|
|
||||||
void process(const uint8_t* data);
|
void process(const uint8_t *data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin() override;
|
void begin() override;
|
||||||
|
|
||||||
using HashBuilder::add;
|
using HashBuilder::add;
|
||||||
void add(const uint8_t* data, size_t len) override;
|
void add(const uint8_t *data, size_t len) override;
|
||||||
|
|
||||||
using HashBuilder::addHexString;
|
using HashBuilder::addHexString;
|
||||||
void addHexString(const char* data) override;
|
void addHexString(const char *data) override;
|
||||||
|
|
||||||
bool addStream(Stream& stream, const size_t maxLen) override;
|
bool addStream(Stream &stream, const size_t maxLen) override;
|
||||||
void calculate() override;
|
void calculate() override;
|
||||||
void getBytes(uint8_t* output) override;
|
void getBytes(uint8_t *output) override;
|
||||||
void getChars(char* output) override;
|
void getChars(char *output) override;
|
||||||
String toString() override;
|
String toString() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,9 @@
|
||||||
|
|
||||||
#include "Print.h"
|
#include "Print.h"
|
||||||
|
|
||||||
class Server: public Print
|
class Server : public Print {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void begin(uint16_t port=0) =0;
|
virtual void begin() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue