forked from espressif/esp-idf
Compare commits
968 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a9d14e963 | ||
|
|
c243b7018f | ||
|
|
6eb6745a59 | ||
|
|
a5c8cdd30e | ||
|
|
39e1cd4d74 | ||
|
|
dc237e205a | ||
|
|
231773b28a | ||
|
|
2ce9add5ba | ||
|
|
56019e2c9d | ||
|
|
86c18a8e05 | ||
|
|
89bf6c2799 | ||
|
|
26cad6beaa | ||
|
|
a915420eec | ||
|
|
1503a8951e | ||
|
|
ee79ef9ba1 | ||
|
|
1cd415dfc1 | ||
|
|
637090410b | ||
|
|
0df77d5a69 | ||
|
|
e5dde19f74 | ||
|
|
4de12b3c0c | ||
|
|
eb39527318 | ||
|
|
0a08a35962 | ||
|
|
d15f2629b0 | ||
|
|
f66312d41c | ||
|
|
c55901bf02 | ||
|
|
75ebfacd28 | ||
|
|
8e74a471ea | ||
|
|
caf889f04d | ||
|
|
af839f371f | ||
|
|
2ebd93e1d2 | ||
|
|
caff697a3d | ||
|
|
fe1969dd3b | ||
|
|
0fd913708c | ||
|
|
c14e7c3360 | ||
|
|
38d9958c11 | ||
|
|
026cec78e9 | ||
|
|
5c25689f7f | ||
|
|
5895ecff50 | ||
|
|
90de9f4942 | ||
|
|
f27b37a4f0 | ||
|
|
e24b875621 | ||
|
|
0b56e9d8b3 | ||
|
|
13c40b53d1 | ||
|
|
65f012d612 | ||
|
|
ec50038f84 | ||
|
|
eee46733f0 | ||
|
|
19f43f92fa | ||
|
|
04bf2db720 | ||
|
|
7a9d02a18b | ||
|
|
43175f22e9 | ||
|
|
fc067fda94 | ||
|
|
f8ddcc7d74 | ||
|
|
acfee765f7 | ||
|
|
2c21b0b2b3 | ||
|
|
0c7abb8978 | ||
|
|
bc4b78459a | ||
|
|
db38a4e068 | ||
|
|
795e9136c1 | ||
|
|
58197e9345 | ||
|
|
5f9003aa0a | ||
|
|
caacfd87fa | ||
|
|
c1163e29ee | ||
|
|
49202b7f03 | ||
|
|
3b54469bec | ||
|
|
ce9e4d0918 | ||
|
|
98e183932c | ||
|
|
4a9160a72c | ||
|
|
c604f980d2 | ||
|
|
eed03c5288 | ||
|
|
4a9b258d46 | ||
|
|
6f7f5c4d01 | ||
|
|
414b843755 | ||
|
|
0d120e0429 | ||
|
|
a472052dcf | ||
|
|
25baed5264 | ||
|
|
3d7364f16f | ||
|
|
45120f176e | ||
|
|
1fa08d773f | ||
|
|
f8a7ef99ad | ||
|
|
08caf05cd7 | ||
|
|
a2b063dc4e | ||
|
|
81ebffc0ad | ||
|
|
9583c29f27 | ||
|
|
d001c40425 | ||
|
|
4643ca6ef8 | ||
|
|
da19c94976 | ||
|
|
0037a03106 | ||
|
|
63a544dd3c | ||
|
|
51adc08070 | ||
|
|
3dbdbb4755 | ||
|
|
f222a02518 | ||
|
|
dc7c244055 | ||
|
|
aeebe24196 | ||
|
|
874b18eab8 | ||
|
|
11995d808c | ||
|
|
f0138ffdf6 | ||
|
|
6281b910d1 | ||
|
|
0f72e63b7a | ||
|
|
bf9e676884 | ||
|
|
42869f4912 | ||
|
|
e5d8ae227d | ||
|
|
dc1f72c786 | ||
|
|
511c1cee22 | ||
|
|
69230e2e3b | ||
|
|
e1086b6b6f | ||
|
|
15d39eded5 | ||
|
|
abe93ee7c3 | ||
|
|
ea7372d9aa | ||
|
|
3c0ac69088 | ||
|
|
ce0808c7be | ||
|
|
66790c3560 | ||
|
|
eeeffcafbf | ||
|
|
254dcb755c | ||
|
|
5ddeab1409 | ||
|
|
a988c6bdb6 | ||
|
|
9c1935e24c | ||
|
|
fda11a687d | ||
|
|
886bc21f7f | ||
|
|
7b495db118 | ||
|
|
bdf477e76d | ||
|
|
b57134d21e | ||
|
|
bdb1391eeb | ||
|
|
ecb5370ca6 | ||
|
|
59f2b3f036 | ||
|
|
aaf98c14fd | ||
|
|
491c64e337 | ||
|
|
5693dd69ed | ||
|
|
1b21573901 | ||
|
|
a40b4d7167 | ||
|
|
297146c410 | ||
|
|
3452d579ac | ||
|
|
fcd857e0f1 | ||
|
|
714afdec6d | ||
|
|
3f3c21c966 | ||
|
|
6db5ca3458 | ||
|
|
c2f1cd5bc0 | ||
|
|
b55b6c6abf | ||
|
|
eb3f02a41a | ||
|
|
263c670342 | ||
|
|
34f6bde8bc | ||
|
|
2a7d2a7795 | ||
|
|
448dd7c6ca | ||
|
|
ea7f34df17 | ||
|
|
2df539062f | ||
|
|
8e4a63f2f8 | ||
|
|
53c4c55e72 | ||
|
|
b83749988c | ||
|
|
a3a0d4d2ad | ||
|
|
ab0f6aceac | ||
|
|
e789da12bd | ||
|
|
7e416fec15 | ||
|
|
923cd98b9e | ||
|
|
3b7777e22d | ||
|
|
a9d3b625c4 | ||
|
|
b2fee9a686 | ||
|
|
bccd747028 | ||
|
|
db635956fb | ||
|
|
9f8efed1eb | ||
|
|
644591b0d5 | ||
|
|
0e8f66e017 | ||
|
|
d62bb227b7 | ||
|
|
3914aaac76 | ||
|
|
5f3957a20e | ||
|
|
9463114e27 | ||
|
|
a22a543636 | ||
|
|
adf8131c20 | ||
|
|
8442ec3413 | ||
|
|
d2c80e0e73 | ||
|
|
02687b9b40 | ||
|
|
0193e34c62 | ||
|
|
e22d3dd804 | ||
|
|
287bee03b3 | ||
|
|
1a897da635 | ||
|
|
344c86bc3e | ||
|
|
7a74262858 | ||
|
|
2a6a2bf39f | ||
|
|
1d7c633349 | ||
|
|
b3f58ed2a1 | ||
|
|
393464d45e | ||
|
|
45f6e45de7 | ||
|
|
6916052e6d | ||
|
|
8711e67e44 | ||
|
|
3a9e986a4e | ||
|
|
fd921ea6e5 | ||
|
|
49b2bf2656 | ||
|
|
0446bfe1f4 | ||
|
|
574efdcbeb | ||
|
|
2023f850de | ||
|
|
eecd5efec5 | ||
|
|
a4b21ff6f1 | ||
|
|
09ae962c33 | ||
|
|
ef4c513834 | ||
|
|
d787e2a564 | ||
|
|
3c676171a9 | ||
|
|
6c8f72c062 | ||
|
|
cb025c22bd | ||
|
|
fcc1516fae | ||
|
|
648f25e275 | ||
|
|
ddc59bc7ab | ||
|
|
873c33f990 | ||
|
|
8061659b5f | ||
|
|
f8bcf2f459 | ||
|
|
c1d6c0a5bc | ||
|
|
32f2e7f509 | ||
|
|
887decf42a | ||
|
|
65db2bf87c | ||
|
|
26272b46cb | ||
|
|
b0fce6855a | ||
|
|
a05cc294eb | ||
|
|
f3aa9cc800 | ||
|
|
fa1a19e199 | ||
|
|
b584cecea2 | ||
|
|
3357b475f7 | ||
|
|
9130b255f5 | ||
|
|
42d7524b91 | ||
|
|
2a13317e44 | ||
|
|
e3b5a38cf6 | ||
|
|
7a557368e3 | ||
|
|
87357d8cf3 | ||
|
|
3265b7ce0c | ||
|
|
3a402fa7b2 | ||
|
|
9d557afe26 | ||
|
|
1176d8be6f | ||
|
|
0d0cb3b991 | ||
|
|
b1254618cd | ||
|
|
63feac091d | ||
|
|
3cd682e9f9 | ||
|
|
6ce1bea29a | ||
|
|
99ab26ac32 | ||
|
|
03762d5f65 | ||
|
|
da8103bb59 | ||
|
|
ce44590c8b | ||
|
|
9c051965d2 | ||
|
|
ee84cbdf4e | ||
|
|
48a3f7d716 | ||
|
|
01007698b7 | ||
|
|
e5d7addcf7 | ||
|
|
b8243b5fbe | ||
|
|
a456543b8a | ||
|
|
81c45ffe14 | ||
|
|
09e657460f | ||
|
|
077bd351e4 | ||
|
|
fb4b29e83a | ||
|
|
840a011c01 | ||
|
|
2b5f488d88 | ||
|
|
896ba6a83e | ||
|
|
56afe0fdca | ||
|
|
e94215443b | ||
|
|
7aee8722fe | ||
|
|
d3ac9cc863 | ||
|
|
1d3b83e2c0 | ||
|
|
5067ecaebe | ||
|
|
54e217b8d4 | ||
|
|
e98ff1beb7 | ||
|
|
e41ef9396f | ||
|
|
b4aa4de694 | ||
|
|
ab7e411f4e | ||
|
|
696a9fa0ba | ||
|
|
360b966938 | ||
|
|
7ed6748534 | ||
|
|
eecd2f56ee | ||
|
|
7d8ff31c59 | ||
|
|
2dc1d1b568 | ||
|
|
a1c1175fa7 | ||
|
|
5adc487133 | ||
|
|
eea3e63c39 | ||
|
|
ce07474148 | ||
|
|
cbe8274651 | ||
|
|
700976f709 | ||
|
|
5519afe675 | ||
|
|
f819b7da90 | ||
|
|
47f3be89be | ||
|
|
f4201de05d | ||
|
|
db8ddf050f | ||
|
|
e64f3d43ad | ||
|
|
2bd77056bb | ||
|
|
4be011785e | ||
|
|
5ce96ab227 | ||
|
|
b8d4a53260 | ||
|
|
fc31437236 | ||
|
|
dc63c2e9cb | ||
|
|
d3d4787335 | ||
|
|
ae39c659d0 | ||
|
|
3349c99882 | ||
|
|
90af68bd3c | ||
|
|
093214c86f | ||
|
|
f55cb56380 | ||
|
|
f612a39127 | ||
|
|
ae2cec834e | ||
|
|
31c720602d | ||
|
|
0b4faeb781 | ||
|
|
ef796860d7 | ||
|
|
9742acc33d | ||
|
|
83c87764f4 | ||
|
|
0afad4c7a7 | ||
|
|
dc20fa029d | ||
|
|
cf26a8b0f0 | ||
|
|
fe83420144 | ||
|
|
14098b4832 | ||
|
|
5088758640 | ||
|
|
ca824d0ddf | ||
|
|
d3e562907f | ||
|
|
eb4c8d9991 | ||
|
|
d56892b563 | ||
|
|
b1ee664367 | ||
|
|
ee5604cad0 | ||
|
|
88d8e93223 | ||
|
|
43def55de8 | ||
|
|
62f201b4bd | ||
|
|
2b22f3e853 | ||
|
|
70954c0b3e | ||
|
|
69be477885 | ||
|
|
76f97f3abd | ||
|
|
d0bfde2ceb | ||
|
|
544e9831e8 | ||
|
|
b937de7df2 | ||
|
|
fa952e5d30 | ||
|
|
ca1e5e5bc5 | ||
|
|
23b3d97099 | ||
|
|
0a0f5a3bdc | ||
|
|
ec331b3979 | ||
|
|
73e040e584 | ||
|
|
d1f40c15ac | ||
|
|
7718234acc | ||
|
|
01cd149cb7 | ||
|
|
7dd4923190 | ||
|
|
0b9fc36e62 | ||
|
|
151ddb4cda | ||
|
|
1fab985f63 | ||
|
|
548844b5cc | ||
|
|
9bc71370b7 | ||
|
|
66118ab580 | ||
|
|
fae3bad007 | ||
|
|
48e5dcd9b5 | ||
|
|
d609daf0cd | ||
|
|
eeb9a0359c | ||
|
|
4cdf488de8 | ||
|
|
c56f147d48 | ||
|
|
1d953831bd | ||
|
|
a0a5e367d6 | ||
|
|
a393bb6f1b | ||
|
|
ad565f27f7 | ||
|
|
3bf6c5b604 | ||
|
|
90747cc8b3 | ||
|
|
feeb22bdbe | ||
|
|
91451d31be | ||
|
|
8fe9e4b09f | ||
|
|
910cede38d | ||
|
|
107d927547 | ||
|
|
f023bf52c9 | ||
|
|
dc1db1c4e7 | ||
|
|
db898de8fb | ||
|
|
d657a679a2 | ||
|
|
e451282f18 | ||
|
|
f3ffce3096 | ||
|
|
754a292309 | ||
|
|
00f1ac748b | ||
|
|
b0cff945cf | ||
|
|
ff772e91e8 | ||
|
|
1beac49f3a | ||
|
|
207438f2da | ||
|
|
7f03e70164 | ||
|
|
f3d6fa21c1 | ||
|
|
83e5e6b24c | ||
|
|
6510c6f495 | ||
|
|
b460718954 | ||
|
|
0a05900096 | ||
|
|
b7196d21c9 | ||
|
|
1a307a417d | ||
|
|
f6a9f76401 | ||
|
|
7149a30d0d | ||
|
|
13c9612810 | ||
|
|
aeccf793fe | ||
|
|
6ca302ed3a | ||
|
|
e34aeae1a0 | ||
|
|
43600262a8 | ||
|
|
8fdea83505 | ||
|
|
7e77f67777 | ||
|
|
e1518b4112 | ||
|
|
151638fdbb | ||
|
|
b3a5dc869f | ||
|
|
87947004c4 | ||
|
|
3ce3c4f54c | ||
|
|
b56b7fe655 | ||
|
|
f892937780 | ||
|
|
105e3302a7 | ||
|
|
19fd2b3d93 | ||
|
|
8be97410a4 | ||
|
|
6af16447f8 | ||
|
|
eee568ddc5 | ||
|
|
c119a1a0f4 | ||
|
|
ed6b453346 | ||
|
|
ba69e61ed5 | ||
|
|
6ba62f7b0b | ||
|
|
e155cd7a78 | ||
|
|
13069ecb26 | ||
|
|
7f42d63687 | ||
|
|
ed7664d19f | ||
|
|
da355d39b8 | ||
|
|
3675e3182f | ||
|
|
9edc9674bc | ||
|
|
7a79cc4a5e | ||
|
|
376377ceca | ||
|
|
490a7e682d | ||
|
|
1b9d62ad95 | ||
|
|
8efef29544 | ||
|
|
21601f00f4 | ||
|
|
b330ea88e6 | ||
|
|
81139df91e | ||
|
|
e5c15c068e | ||
|
|
7e2465995f | ||
|
|
aaa0853572 | ||
|
|
878d70d9e6 | ||
|
|
4b43c10490 | ||
|
|
a8916daeb2 | ||
|
|
b7a2516242 | ||
|
|
4a9f339447 | ||
|
|
c1af728239 | ||
|
|
35789eef16 | ||
|
|
4a0d8ef478 | ||
|
|
23c17c4c0d | ||
|
|
2821e99bcc | ||
|
|
a4f2283384 | ||
|
|
b905f2de4d | ||
|
|
c517628c77 | ||
|
|
cbec031c91 | ||
|
|
90c7885f4d | ||
|
|
476d4ba1b7 | ||
|
|
da80efa8bc | ||
|
|
725ecf108f | ||
|
|
d10dec358d | ||
|
|
7b2ece3ac2 | ||
|
|
293a665601 | ||
|
|
c6c1d089cc | ||
|
|
e5fe1c0e68 | ||
|
|
09cf34c9aa | ||
|
|
d76d94549a | ||
|
|
f3e22bc23c | ||
|
|
444ded835d | ||
|
|
57c7a25bb3 | ||
|
|
8c17eb91e2 | ||
|
|
91ec6068e9 | ||
|
|
dab432d7ff | ||
|
|
accef886a9 | ||
|
|
76719b9c37 | ||
|
|
da10a5b7e9 | ||
|
|
901e8338ac | ||
|
|
fbe566ac67 | ||
|
|
381bd7d785 | ||
|
|
c0a68466a7 | ||
|
|
e9786e3038 | ||
|
|
eaf8cfbf8d | ||
|
|
055943e293 | ||
|
|
b34a0874b1 | ||
|
|
0d7f6a54e5 | ||
|
|
100379c4aa | ||
|
|
5d7d46a76d | ||
|
|
eaaad51f81 | ||
|
|
f21762eeef | ||
|
|
e7f57fef55 | ||
|
|
284362d62d | ||
|
|
29b009d6fd | ||
|
|
86e8983499 | ||
|
|
fa42f63226 | ||
|
|
93c9c07e22 | ||
|
|
483fc9be6f | ||
|
|
2ed18dcdd7 | ||
|
|
cb2e328c5f | ||
|
|
267ce80355 | ||
|
|
8b54542a88 | ||
|
|
030f17ae28 | ||
|
|
a8fe057219 | ||
|
|
adc5b2e08f | ||
|
|
0be4deeb22 | ||
|
|
1ffaf8aad9 | ||
|
|
9e7d9ef385 | ||
|
|
88eaa34075 | ||
|
|
b434b8f5d2 | ||
|
|
7e6d1ef4bc | ||
|
|
92dc6a6dde | ||
|
|
8e51f7e236 | ||
|
|
492c682dbe | ||
|
|
3886be23c8 | ||
|
|
814ee9db7f | ||
|
|
ddbce78bff | ||
|
|
a230075447 | ||
|
|
4b5be79c0c | ||
|
|
b80b5dad32 | ||
|
|
ee39083d1b | ||
|
|
38b4d1d70c | ||
|
|
2e85c5b62e | ||
|
|
a820787414 | ||
|
|
cea6908238 | ||
|
|
d81c79d79f | ||
|
|
70c9b1ca22 | ||
|
|
2f8508c7eb | ||
|
|
fd281c11cc | ||
|
|
5328154a01 | ||
|
|
6dd653392b | ||
|
|
dd623febf5 | ||
|
|
106c8813ed | ||
|
|
524308c98d | ||
|
|
553725df84 | ||
|
|
7d3733d255 | ||
|
|
20e66fa815 | ||
|
|
038f51ffa6 | ||
|
|
4e78900fbf | ||
|
|
87215ca0c3 | ||
|
|
f6bfe13eb3 | ||
|
|
294a051538 | ||
|
|
4aa1058e8a | ||
|
|
a08c77ae96 | ||
|
|
df874cd070 | ||
|
|
36fff1d751 | ||
|
|
fe0d45d549 | ||
|
|
6f19193de6 | ||
|
|
8f4e7d2456 | ||
|
|
4156c6ddec | ||
|
|
cb20ba50b1 | ||
|
|
131979e517 | ||
|
|
9d6cace1fd | ||
|
|
a5b007f6bb | ||
|
|
0beb60e8fc | ||
|
|
9294e4d08d | ||
|
|
193b8e93a8 | ||
|
|
8da392aa1d | ||
|
|
c3cee5e3de | ||
|
|
0c13ae6b45 | ||
|
|
306a1173af | ||
|
|
592a4295be | ||
|
|
2549951498 | ||
|
|
b2384dc9ee | ||
|
|
f95826144e | ||
|
|
344cb99d34 | ||
|
|
464df4b788 | ||
|
|
8ff0d986b6 | ||
|
|
225bc0f80a | ||
|
|
96c8343e46 | ||
|
|
d9cdbcdc8b | ||
|
|
3ee11bcafc | ||
|
|
bcb543eb10 | ||
|
|
bb73659c9c | ||
|
|
58bc6be4c0 | ||
|
|
5059c7fac3 | ||
|
|
cf866f23f2 | ||
|
|
faec3211bd | ||
|
|
c7d0df5451 | ||
|
|
7097cb9c9d | ||
|
|
1fcef31195 | ||
|
|
acc882f4dd | ||
|
|
e4c1bcddc5 | ||
|
|
b2455219cc | ||
|
|
de6b7d6520 | ||
|
|
fa40e43c8d | ||
|
|
9f29dbf656 | ||
|
|
b2d61989f1 | ||
|
|
bb518afb59 | ||
|
|
37063ea9b6 | ||
|
|
f6837e6117 | ||
|
|
c4f39094d3 | ||
|
|
2da22620f8 | ||
|
|
f77d0a9cdb | ||
|
|
ddf4991024 | ||
|
|
f8597be435 | ||
|
|
6e5e430ef4 | ||
|
|
065d451e47 | ||
|
|
c8990eb39d | ||
|
|
c90f770599 | ||
|
|
48978c6f2b | ||
|
|
5bb5670d69 | ||
|
|
7197811861 | ||
|
|
892c2be168 | ||
|
|
5c6be8380e | ||
|
|
1d8e1c4ce4 | ||
|
|
1778573dad | ||
|
|
9778549759 | ||
|
|
e5e226a121 | ||
|
|
71845041e0 | ||
|
|
54dff92df5 | ||
|
|
a5bd08a6b6 | ||
|
|
befc74e0f0 | ||
|
|
12bf1017de | ||
|
|
006442cd9d | ||
|
|
25a134afdc | ||
|
|
70811110fc | ||
|
|
b87e440c69 | ||
|
|
f85294b058 | ||
|
|
413b6487fb | ||
|
|
f608afbe6b | ||
|
|
325fca94c0 | ||
|
|
3130b19cf8 | ||
|
|
5d2c23c8ab | ||
|
|
8480e79ae2 | ||
|
|
86052eec78 | ||
|
|
5ede49ca4a | ||
|
|
bbdb236ab7 | ||
|
|
0a0113bcce | ||
|
|
84a534a4a0 | ||
|
|
286202caa3 | ||
|
|
6b4dcd4f5c | ||
|
|
4f62227030 | ||
|
|
9ebaf36c28 | ||
|
|
1ece141c52 | ||
|
|
f49e2afe94 | ||
|
|
17b260d05c | ||
|
|
07fc1d181f | ||
|
|
beb29bc88a | ||
|
|
76c20ab9b3 | ||
|
|
241ba1a6bb | ||
|
|
1fac58deb7 | ||
|
|
78d32f2e8b | ||
|
|
f237b92bc4 | ||
|
|
ccc1263ca8 | ||
|
|
51a44c81de | ||
|
|
1b96cefaf8 | ||
|
|
ef82e8d0bc | ||
|
|
d6bdaed141 | ||
|
|
13018449fe | ||
|
|
b6687e56ed | ||
|
|
6494927766 | ||
|
|
6ce5c7668f | ||
|
|
c97a05c0d5 | ||
|
|
fed772641a | ||
|
|
39d8a89c80 | ||
|
|
62980ae995 | ||
|
|
029a155a71 | ||
|
|
4849d7ae90 | ||
|
|
10b4ddb467 | ||
|
|
288bc2bfca | ||
|
|
8e4ec90dc4 | ||
|
|
0e06b4d653 | ||
|
|
8fe4007dfa | ||
|
|
09f4015300 | ||
|
|
56918682f9 | ||
|
|
6b49a355f7 | ||
|
|
6628fddae6 | ||
|
|
ff99e0ea69 | ||
|
|
b305a96a74 | ||
|
|
fe4e68132f | ||
|
|
e870a0f0f1 | ||
|
|
12643e063c | ||
|
|
a7dc804476 | ||
|
|
7342811c37 | ||
|
|
8e0b0af09b | ||
|
|
e1e82c8949 | ||
|
|
d99d92e170 | ||
|
|
1ca67e98d6 | ||
|
|
f8f0c81077 | ||
|
|
727c2cfa00 | ||
|
|
1d4eeeb464 | ||
|
|
e9a764d9a5 | ||
|
|
b2e4af4ed0 | ||
|
|
66a0b64e54 | ||
|
|
9d48cdb6f3 | ||
|
|
258e9c98be | ||
|
|
35e491856e | ||
|
|
226c790766 | ||
|
|
c0d32f6e48 | ||
|
|
203f75223e | ||
|
|
742f8e7f8a | ||
|
|
7e16a79cf7 | ||
|
|
22dc4898d9 | ||
|
|
f78c96a3d7 | ||
|
|
b4727a8765 | ||
|
|
8bbd99ad9e | ||
|
|
5dcdef0639 | ||
|
|
d651ee3d28 | ||
|
|
34f1c208a8 | ||
|
|
83d7b4591c | ||
|
|
f5096892f9 | ||
|
|
56694fb4b6 | ||
|
|
929542d4fa | ||
|
|
be49c8d841 | ||
|
|
67aefe1011 | ||
|
|
46a3c36343 | ||
|
|
58e49d169c | ||
|
|
a241f95407 | ||
|
|
aaaa491c42 | ||
|
|
91aa35e831 | ||
|
|
113e829552 | ||
|
|
3802fddefb | ||
|
|
bb2eb9adeb | ||
|
|
78116afa01 | ||
|
|
b865e72aec | ||
|
|
f1b2457b6c | ||
|
|
46fa5654a7 | ||
|
|
bf28a1a27b | ||
|
|
b7beefba9e | ||
|
|
0784c52131 | ||
|
|
a7f826750b | ||
|
|
38086ae737 | ||
|
|
6173660ff0 | ||
|
|
79b450cfb4 | ||
|
|
c7fbc6dd85 | ||
|
|
3b5bba1812 | ||
|
|
b4feb67b5f | ||
|
|
578d7902af | ||
|
|
509884c5ac | ||
|
|
8a656f006e | ||
|
|
0f79c72704 | ||
|
|
6d6f71bbae | ||
|
|
332ccd0925 | ||
|
|
2ee1c6fd3e | ||
|
|
6a328992d7 | ||
|
|
b51f109dd7 | ||
|
|
85e8dea26a | ||
|
|
093c7b176d | ||
|
|
30e39631db | ||
|
|
a7ff611b10 | ||
|
|
2e64d2d56e | ||
|
|
3e6b402756 | ||
|
|
5568ca2855 | ||
|
|
30f2371917 | ||
|
|
ebaa944a9a | ||
|
|
d83598a64a | ||
|
|
00d1068869 | ||
|
|
49be9fb836 | ||
|
|
6f0c70daf6 | ||
|
|
219c85cf60 | ||
|
|
524696d59a | ||
|
|
9a229f4077 | ||
|
|
016c8d8b05 | ||
|
|
9914b839aa | ||
|
|
76e4ea7f68 | ||
|
|
3ec0f415a5 | ||
|
|
fa40b3d5d0 | ||
|
|
f742808333 | ||
|
|
51bd64c754 | ||
|
|
b85321be97 | ||
|
|
dcd63f73f6 | ||
|
|
b8f0c32a0a | ||
|
|
8f2e1471af | ||
|
|
a159e58ead | ||
|
|
fe767855df | ||
|
|
1e674fb4ed | ||
|
|
3660ccac4c | ||
|
|
4f9a4e8ed7 | ||
|
|
582bf18789 | ||
|
|
2e3f06ece8 | ||
|
|
c62a20f162 | ||
|
|
ed4d83af8e | ||
|
|
1444868917 | ||
|
|
05ba4f15d6 | ||
|
|
37b7153c0e | ||
|
|
1a53334843 | ||
|
|
fd29b0165f | ||
|
|
9c3262f80b | ||
|
|
900dbfd1f6 | ||
|
|
13a1f4ed78 | ||
|
|
8a69ffc36f | ||
|
|
a437e4dc5c | ||
|
|
741f97da4e | ||
|
|
eae2baa0f1 | ||
|
|
f49f5ff35a | ||
|
|
020b295f06 | ||
|
|
6e14de0fa8 | ||
|
|
95c7f45e84 | ||
|
|
651a08f710 | ||
|
|
18cb87b4ce | ||
|
|
1fedece94d | ||
|
|
137810915c | ||
|
|
bb766355b5 | ||
|
|
807ef53c38 | ||
|
|
e585121011 | ||
|
|
671be20cc5 | ||
|
|
022a9295b0 | ||
|
|
a34d788a5e | ||
|
|
2a47c5c7a4 | ||
|
|
cfc4f74b52 | ||
|
|
43a722f0de | ||
|
|
eff24857bc | ||
|
|
18118a6d5c | ||
|
|
64757c0228 | ||
|
|
bab80ad202 | ||
|
|
76f0dda3a4 | ||
|
|
ce9878ce71 | ||
|
|
403a24ab64 | ||
|
|
d2cf266762 | ||
|
|
cec39b750a | ||
|
|
0420f290a4 | ||
|
|
eb6dbeb15a | ||
|
|
5c9ab21d81 | ||
|
|
bab379faf8 | ||
|
|
fb7cd2a7a7 | ||
|
|
c208a6b451 | ||
|
|
78511c3cc3 | ||
|
|
cd6bbaa727 | ||
|
|
55b8f2ea8c | ||
|
|
ec2f1a6b9a | ||
|
|
26646b5b31 | ||
|
|
1ae9a2ae0b | ||
|
|
28eb488892 | ||
|
|
fcf1dba9cd | ||
|
|
94ed7b8298 | ||
|
|
24fab0b7a9 | ||
|
|
c4c1af114e | ||
|
|
b1ee25afde | ||
|
|
cccaa68467 | ||
|
|
6080767379 | ||
|
|
42b6c4953d | ||
|
|
746e831c19 | ||
|
|
36f9091e03 | ||
|
|
553ba51924 | ||
|
|
929d98538e | ||
|
|
b810b32675 | ||
|
|
00bf376bc3 | ||
|
|
fe19ea977b | ||
|
|
a953f73c64 | ||
|
|
bed50a93f0 | ||
|
|
a80bfc1dcf | ||
|
|
51d846417e | ||
|
|
ca54a5ce2a | ||
|
|
7b1777dd30 | ||
|
|
64b46ff1d9 | ||
|
|
c355d8a88e | ||
|
|
977af32d0f | ||
|
|
f0a6432717 | ||
|
|
c18e86a826 | ||
|
|
b5d53a0eff | ||
|
|
10afc3de77 | ||
|
|
545878d4e9 | ||
|
|
ec7909956d | ||
|
|
d9c3a08813 | ||
|
|
eb9a93f9b7 | ||
|
|
710019a47f | ||
|
|
2d27358f61 | ||
|
|
b80eba8d5a | ||
|
|
7832db7bb3 | ||
|
|
efa70bc8e3 | ||
|
|
31b7db5c38 | ||
|
|
8d02ccd2f7 | ||
|
|
62eb0f4c12 | ||
|
|
155f034b1e | ||
|
|
47dea73b03 | ||
|
|
28fdf96828 | ||
|
|
3969fe0dad | ||
|
|
c70c25afd0 | ||
|
|
d59d9eef4f | ||
|
|
22514e12d8 | ||
|
|
f48ffb37f2 | ||
|
|
0f041ee7bb | ||
|
|
c320a3ee4c | ||
|
|
1f35716ef4 | ||
|
|
358de85eb3 | ||
|
|
84277e5887 | ||
|
|
52a70e0489 | ||
|
|
6523d912f2 | ||
|
|
aa0d2078b7 | ||
|
|
348d6d5d3f | ||
|
|
46228db9a8 | ||
|
|
2cac11f162 | ||
|
|
64eeee4532 | ||
|
|
a9eb37e2c8 | ||
|
|
c7a297195f | ||
|
|
19e96add8a | ||
|
|
a0a0328e4f | ||
|
|
04aebc464c | ||
|
|
30e01847ad | ||
|
|
3f6033d8bd | ||
|
|
45e59a9f56 | ||
|
|
587e6ec93f | ||
|
|
6d00c7fc49 | ||
|
|
c418714ec6 | ||
|
|
19d8c050cd | ||
|
|
cb650382ca | ||
|
|
e5e592e5b6 | ||
|
|
28e20e90e3 | ||
|
|
1c4d9f2aca | ||
|
|
ded8b0102a | ||
|
|
401970495d | ||
|
|
5d46bb596d | ||
|
|
8de9149b11 | ||
|
|
e8b8946e6e | ||
|
|
2c1e3d1ef2 | ||
|
|
bf608b6709 | ||
|
|
24ebdbd3f4 | ||
|
|
fd00d3213b | ||
|
|
c921a5bc4b | ||
|
|
ade85cc850 | ||
|
|
5c8d25b795 | ||
|
|
ac051f0afc | ||
|
|
bb47146710 | ||
|
|
07cb228f64 | ||
|
|
3cfe1c89b5 | ||
|
|
4f805d558c | ||
|
|
f53716d851 | ||
|
|
f8fd922ca5 | ||
|
|
61d07ffbfc | ||
|
|
6b5649190f | ||
|
|
f44507de53 | ||
|
|
88c7a61a63 | ||
|
|
6af90457f7 | ||
|
|
3aafb2cfcf | ||
|
|
8ec0c82c3f | ||
|
|
a338c1b712 | ||
|
|
0b21be508e | ||
|
|
3b4d51bbfa | ||
|
|
60c556eb55 | ||
|
|
9933e37c8b | ||
|
|
67bdc8aaf4 | ||
|
|
44bd6f72bc | ||
|
|
2d67ce3109 | ||
|
|
e85cb6d148 | ||
|
|
7658b8ab62 | ||
|
|
7969a566e3 | ||
|
|
be05b1e654 | ||
|
|
ca51b60033 | ||
|
|
9b3ff1bed0 | ||
|
|
f859f9e25b | ||
|
|
f2ae151dab | ||
|
|
bae0d8a313 | ||
|
|
cfcc0edc33 | ||
|
|
54e6f0793a | ||
|
|
e98f4d2751 | ||
|
|
33cf0faac8 | ||
|
|
7385e71c84 | ||
|
|
7778ce83bd | ||
|
|
0f8070a6fd | ||
|
|
0fcb9056f8 | ||
|
|
5110d4b303 | ||
|
|
fc19954376 | ||
|
|
16d32c58e7 | ||
|
|
3d926da642 | ||
|
|
9bb719dd68 | ||
|
|
536cb0489e | ||
|
|
98c7cb5560 | ||
|
|
4baf333c79 | ||
|
|
79401934a1 | ||
|
|
ec1daf32e1 | ||
|
|
1cac0d2cf2 | ||
|
|
8d1594c339 | ||
|
|
a0f516de0b | ||
|
|
802d94aa35 | ||
|
|
3c3e375d8d | ||
|
|
d57ea422be | ||
|
|
3b3242cbae | ||
|
|
96c2b34eb9 | ||
|
|
6b3a8acdc3 | ||
|
|
a10abd695b | ||
|
|
0f28a51996 | ||
|
|
6681096e55 | ||
|
|
18b65dca26 | ||
|
|
a398116b1c | ||
|
|
331c7c7dc3 | ||
|
|
7bd9559e7e | ||
|
|
e84289077c | ||
|
|
c59c40741b | ||
|
|
f3c1903791 | ||
|
|
2885ec3831 | ||
|
|
a7db0e2291 | ||
|
|
cb98f5a814 | ||
|
|
8725bce5bc | ||
|
|
174b3b89e4 | ||
|
|
8d9d8e27ca | ||
|
|
93f4dc6b32 | ||
|
|
b021bbdc80 | ||
|
|
c9fe4fa13e | ||
|
|
96252c493a | ||
|
|
007a4fcc4e | ||
|
|
dbeb8ae02a | ||
|
|
9921c8b91f | ||
|
|
e16f65f4e6 | ||
|
|
fe0a5b41bf | ||
|
|
1f7c54ae85 | ||
|
|
049bd9fe0a | ||
|
|
167fb50a22 | ||
|
|
5f3b532c8d | ||
|
|
841a6dcd9a |
164
.flake8
164
.flake8
@@ -1,164 +0,0 @@
|
||||
[flake8]
|
||||
|
||||
select =
|
||||
# Full lists are given in order to suppress all errors from other plugins
|
||||
# Full list of pyflakes error codes:
|
||||
F401, # module imported but unused
|
||||
F402, # import module from line N shadowed by loop variable
|
||||
F403, # 'from module import *' used; unable to detect undefined names
|
||||
F404, # future import(s) name after other statements
|
||||
F405, # name may be undefined, or defined from star imports: module
|
||||
F406, # 'from module import *' only allowed at module level
|
||||
F407, # an undefined __future__ feature name was imported
|
||||
F601, # dictionary key name repeated with different values
|
||||
F602, # dictionary key variable name repeated with different values
|
||||
F621, # too many expressions in an assignment with star-unpacking
|
||||
F622, # two or more starred expressions in an assignment (a, *b, *c = d)
|
||||
F631, # assertion test is a tuple, which are always True
|
||||
F701, # a break statement outside of a while or for loop
|
||||
F702, # a continue statement outside of a while or for loop
|
||||
F703, # a continue statement in a finally block in a loop
|
||||
F704, # a yield or yield from statement outside of a function
|
||||
F705, # a return statement with arguments inside a generator
|
||||
F706, # a return statement outside of a function/method
|
||||
F707, # an except: block as not the last exception handler
|
||||
F721, F722, # doctest syntax error syntax error in forward type annotation
|
||||
F811, # redefinition of unused name from line N
|
||||
F812, # list comprehension redefines name from line N
|
||||
F821, # undefined name name
|
||||
F822, # undefined name name in __all__
|
||||
F823, # local variable name referenced before assignment
|
||||
F831, # duplicate argument name in function definition
|
||||
F841, # local variable name is assigned to but never used
|
||||
F901, # raise NotImplemented should be raise NotImplementedError
|
||||
|
||||
# Full list of pycodestyle violations:
|
||||
E101, # indentation contains mixed spaces and tabs
|
||||
E111, # indentation is not a multiple of four
|
||||
E112, # expected an indented block
|
||||
E113, # unexpected indentation
|
||||
E114, # indentation is not a multiple of four (comment)
|
||||
E115, # expected an indented block (comment)
|
||||
E116, # unexpected indentation (comment)
|
||||
E121, # continuation line under-indented for hanging indent
|
||||
E122, # continuation line missing indentation or outdented
|
||||
E123, # closing bracket does not match indentation of opening bracket's line
|
||||
E124, # closing bracket does not match visual indentation
|
||||
E125, # continuation line with same indent as next logical line
|
||||
E126, # continuation line over-indented for hanging indent
|
||||
E127, # continuation line over-indented for visual indent
|
||||
E128, # continuation line under-indented for visual indent
|
||||
E129, # visually indented line with same indent as next logical line
|
||||
E131, # continuation line unaligned for hanging indent
|
||||
E133, # closing bracket is missing indentation
|
||||
E201, # whitespace after '('
|
||||
E202, # whitespace before ')'
|
||||
E203, # whitespace before ':'
|
||||
E211, # whitespace before '('
|
||||
E221, # multiple spaces before operator
|
||||
E222, # multiple spaces after operator
|
||||
E223, # tab before operator
|
||||
E224, # tab after operator
|
||||
E225, # missing whitespace around operator
|
||||
E226, # missing whitespace around arithmetic operator
|
||||
E227, # missing whitespace around bitwise or shift operator
|
||||
E228, # missing whitespace around modulo operator
|
||||
E231, # missing whitespace after ',', ';', or ':'
|
||||
E241, # multiple spaces after ','
|
||||
E242, # tab after ','
|
||||
E251, # unexpected spaces around keyword / parameter equals
|
||||
E261, # at least two spaces before inline comment
|
||||
E262, # inline comment should start with '# '
|
||||
E265, # block comment should start with '# '
|
||||
E266, # too many leading '#' for block comment
|
||||
E271, # multiple spaces after keyword
|
||||
E272, # multiple spaces before keyword
|
||||
E273, # tab after keyword
|
||||
E274, # tab before keyword
|
||||
E275, # missing whitespace after keyword
|
||||
E301, # expected 1 blank line, found 0
|
||||
E302, # expected 2 blank lines, found 0
|
||||
E303, # too many blank lines
|
||||
E304, # blank lines found after function decorator
|
||||
E305, # expected 2 blank lines after end of function or class
|
||||
E306, # expected 1 blank line before a nested definition
|
||||
E401, # multiple imports on one line
|
||||
E402, # module level import not at top of file
|
||||
E501, # line too long (82 > 79 characters)
|
||||
E502, # the backslash is redundant between brackets
|
||||
E701, # multiple statements on one line (colon)
|
||||
E702, # multiple statements on one line (semicolon)
|
||||
E703, # statement ends with a semicolon
|
||||
E704, # multiple statements on one line (def)
|
||||
E711, # comparison to None should be 'if cond is None:'
|
||||
E712, # comparison to True should be 'if cond is True:' or 'if cond:'
|
||||
E713, # test for membership should be 'not in'
|
||||
E714, # test for object identity should be 'is not'
|
||||
E721, # do not compare types, use 'isinstance()'
|
||||
E722, # do not use bare except, specify exception instead
|
||||
E731, # do not assign a lambda expression, use a def
|
||||
E741, # do not use variables named 'l', 'O', or 'I'
|
||||
E742, # do not define classes named 'l', 'O', or 'I'
|
||||
E743, # do not define functions named 'l', 'O', or 'I'
|
||||
E901, # SyntaxError or IndentationError
|
||||
E902, # IOError
|
||||
W191, # indentation contains tabs
|
||||
W291, # trailing whitespace
|
||||
W292, # no newline at end of file
|
||||
W293, # blank line contains whitespace
|
||||
W391, # blank line at end of file
|
||||
W503, # line break before binary operator
|
||||
W504, # line break after binary operator
|
||||
W505, # doc line too long (82 > 79 characters)
|
||||
W601, # .has_key() is deprecated, use 'in'
|
||||
W602, # deprecated form of raising exception
|
||||
W603, # '<>' is deprecated, use '!='
|
||||
W604, # backticks are deprecated, use 'repr()'
|
||||
W605, # invalid escape sequence 'x'
|
||||
W606, # 'async' and 'await' are reserved keywords starting with Python 3.7
|
||||
|
||||
# Full list of flake8 violations
|
||||
E999, # failed to compile a file into an Abstract Syntax Tree for the plugins that require it
|
||||
|
||||
# Full list of mccabe violations
|
||||
C901 # complexity value provided by the user
|
||||
|
||||
ignore =
|
||||
E221, # multiple spaces before operator
|
||||
E231, # missing whitespace after ',', ';', or ':'
|
||||
E241, # multiple spaces after ','
|
||||
W503, # line break before binary operator
|
||||
W504 # line break after binary operator
|
||||
|
||||
max-line-length = 160
|
||||
|
||||
show_source = True
|
||||
|
||||
statistics = True
|
||||
|
||||
exclude =
|
||||
.git,
|
||||
__pycache__,
|
||||
# submodules
|
||||
components/bootloader/subproject/components/micro-ecc/micro-ecc,
|
||||
components/esptool_py/esptool,
|
||||
components/expat/expat,
|
||||
components/json/cJSON,
|
||||
components/libsodium/libsodium,
|
||||
components/mbedtls/mbedtls,
|
||||
components/nghttp/nghttp2,
|
||||
components/bt/host/nimble/nimble,
|
||||
components/unity/unity,
|
||||
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
|
||||
# other third-party libraries
|
||||
tools/kconfig_new/kconfiglib.py,
|
||||
# autogenerated scripts
|
||||
components/protocomm/python/constants_pb2.py,
|
||||
components/protocomm/python/sec0_pb2.py,
|
||||
components/protocomm/python/sec1_pb2.py,
|
||||
components/protocomm/python/session_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_scan_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_config_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_constants_pb2.py,
|
||||
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py,
|
||||
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
|
||||
22
.github/main.workflow
vendored
22
.github/main.workflow
vendored
@@ -1,22 +0,0 @@
|
||||
workflow "Sync issues to JIRA" {
|
||||
on = "issues"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync issue and PR comments to JIRA" {
|
||||
on = "issue_comment"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync PRs to JIRA" {
|
||||
on = "pull_request"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
action "Sync to JIRA" {
|
||||
uses = "espressif/github-actions/sync_issues_to_jira@master"
|
||||
secrets = ["GITHUB_TOKEN", "JIRA_URL", "JIRA_USER", "JIRA_PASS"]
|
||||
env = {
|
||||
JIRA_PROJECT = "IDFGH"
|
||||
}
|
||||
}
|
||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -36,10 +36,6 @@ docs/*/xml_in/
|
||||
docs/*/man/
|
||||
docs/doxygen_sqlite3.db
|
||||
|
||||
# Downloaded font files
|
||||
docs/_static/DejaVuSans.ttf
|
||||
docs/_static/NotoSansSC-Regular.otf
|
||||
|
||||
# Unit test app files
|
||||
tools/unit-test-app/sdkconfig
|
||||
tools/unit-test-app/sdkconfig.old
|
||||
@@ -52,19 +48,23 @@ tools/test_idf_monitor/outputs
|
||||
|
||||
TEST_LOGS
|
||||
|
||||
# AWS IoT Examples require device-specific certs/keys
|
||||
examples/protocols/aws_iot/*/main/certs/*.pem.*
|
||||
|
||||
# gcov coverage reports
|
||||
*.gcda
|
||||
*.gcno
|
||||
coverage.info
|
||||
coverage_report/
|
||||
|
||||
# Windows tools installer build
|
||||
tools/windows/tool_setup/.*
|
||||
tools/windows/tool_setup/input
|
||||
tools/windows/tool_setup/dl
|
||||
tools/windows/tool_setup/keys
|
||||
tools/windows/tool_setup/Output
|
||||
|
||||
test_multi_heap_host
|
||||
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
|
||||
# Results for the checking of the Python coding style
|
||||
flake8_output.txt
|
||||
|
||||
# ESP-IDF library
|
||||
build
|
||||
|
||||
1971
.gitlab-ci.yml
1971
.gitlab-ci.yml
File diff suppressed because it is too large
Load Diff
63
.gitmodules
vendored
63
.gitmodules
vendored
@@ -1,76 +1,63 @@
|
||||
#
|
||||
# All the relative URL paths are intended to be GitHub ones
|
||||
# For Espressif's public projects please use '../../espressif/proj', not a '../proj'
|
||||
#
|
||||
[submodule "components/esp32/lib"]
|
||||
path = components/esp32/lib
|
||||
url = https://github.com/espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/esptool_py/esptool"]
|
||||
path = components/esptool_py/esptool
|
||||
url = ../../espressif/esptool.git
|
||||
url = https://github.com/espressif/esptool.git
|
||||
|
||||
[submodule "components/bt/controller/lib"]
|
||||
path = components/bt/controller/lib
|
||||
url = ../../espressif/esp32-bt-lib.git
|
||||
[submodule "components/bt/lib"]
|
||||
path = components/bt/lib
|
||||
url = https://github.com/espressif/esp32-bt-lib.git
|
||||
|
||||
[submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"]
|
||||
path = components/bootloader/subproject/components/micro-ecc/micro-ecc
|
||||
url = ../../kmackay/micro-ecc.git
|
||||
[submodule "components/micro-ecc/micro-ecc"]
|
||||
path = components/micro-ecc/micro-ecc
|
||||
url = https://github.com/kmackay/micro-ecc.git
|
||||
|
||||
[submodule "components/coap/libcoap"]
|
||||
path = components/coap/libcoap
|
||||
url = ../../obgm/libcoap.git
|
||||
url = https://github.com/obgm/libcoap.git
|
||||
|
||||
[submodule "components/aws_iot/aws-iot-device-sdk-embedded-C"]
|
||||
path = components/aws_iot/aws-iot-device-sdk-embedded-C
|
||||
url = https://github.com/espressif/aws-iot-device-sdk-embedded-C.git
|
||||
|
||||
[submodule "components/nghttp/nghttp2"]
|
||||
path = components/nghttp/nghttp2
|
||||
url = ../../nghttp2/nghttp2.git
|
||||
url = https://github.com/nghttp2/nghttp2.git
|
||||
|
||||
[submodule "components/libsodium/libsodium"]
|
||||
path = components/libsodium/libsodium
|
||||
url = ../../jedisct1/libsodium.git
|
||||
url = https://github.com/jedisct1/libsodium.git
|
||||
|
||||
[submodule "components/spiffs/spiffs"]
|
||||
path = components/spiffs/spiffs
|
||||
url = ../../pellepl/spiffs.git
|
||||
url = https://github.com/pellepl/spiffs.git
|
||||
|
||||
[submodule "components/json/cJSON"]
|
||||
path = components/json/cJSON
|
||||
url = ../../DaveGamble/cJSON.git
|
||||
url = https://github.com/DaveGamble/cJSON.git
|
||||
|
||||
[submodule "components/mbedtls/mbedtls"]
|
||||
path = components/mbedtls/mbedtls
|
||||
url = ../../espressif/mbedtls.git
|
||||
url = https://github.com/espressif/mbedtls.git
|
||||
|
||||
[submodule "components/asio/asio"]
|
||||
path = components/asio/asio
|
||||
url = ../../espressif/asio.git
|
||||
url = https://github.com/espressif/asio.git
|
||||
|
||||
[submodule "components/expat/expat"]
|
||||
path = components/expat/expat
|
||||
url = ../../libexpat/libexpat.git
|
||||
url = https://github.com/libexpat/libexpat.git
|
||||
|
||||
[submodule "components/lwip/lwip"]
|
||||
path = components/lwip/lwip
|
||||
url = ../../espressif/esp-lwip.git
|
||||
url = https://github.com/espressif/esp-lwip.git
|
||||
|
||||
[submodule "components/mqtt/esp-mqtt"]
|
||||
path = components/mqtt/esp-mqtt
|
||||
url = ../../espressif/esp-mqtt.git
|
||||
url = https://github.com/espressif/esp-mqtt.git
|
||||
|
||||
[submodule "components/protobuf-c/protobuf-c"]
|
||||
path = components/protobuf-c/protobuf-c
|
||||
url = ../../protobuf-c/protobuf-c.git
|
||||
|
||||
[submodule "components/unity/unity"]
|
||||
path = components/unity/unity
|
||||
url = ../../ThrowTheSwitch/Unity.git
|
||||
|
||||
[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"]
|
||||
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
|
||||
url = ../../leethomason/tinyxml2.git
|
||||
|
||||
[submodule "components/esp_wifi/lib_esp32"]
|
||||
path = components/esp_wifi/lib_esp32
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/bt/host/nimble/nimble"]
|
||||
path = components/bt/host/nimble/nimble
|
||||
url = ../../espressif/esp-nimble.git
|
||||
url = https://github.com/protobuf-c/protobuf-c
|
||||
|
||||
@@ -15,7 +15,7 @@ python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
# We need to list all the submodules included in documenation build by DOxygen
|
||||
# We need to list all the submodules included in documentation build by Doxygen
|
||||
submodules:
|
||||
include:
|
||||
- components/mqtt/esp-mqtt
|
||||
@@ -1,7 +0,0 @@
|
||||
language: python
|
||||
sudo: false
|
||||
python:
|
||||
- "3.4"
|
||||
script:
|
||||
- pip install flake8
|
||||
- travis_wait 20 python -m flake8 --config=.flake8 .
|
||||
@@ -1,99 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(esp-idf C CXX ASM)
|
||||
|
||||
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
|
||||
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
|
||||
"again.")
|
||||
endif()
|
||||
|
||||
unset(compile_options)
|
||||
unset(c_compile_options)
|
||||
unset(cxx_compile_options)
|
||||
unset(compile_definitions)
|
||||
unset(link_options)
|
||||
|
||||
# Add the following build specifications here, since these seem to be dependent
|
||||
# on config values on the root Kconfig.
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
else()
|
||||
list(APPEND compile_options "-Og")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||
list(APPEND cxx_compile_options "-fexceptions")
|
||||
else()
|
||||
list(APPEND cxx_compile_options "-fno-exceptions")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_RTTI)
|
||||
list(APPEND cxx_compile_options "-frtti")
|
||||
else()
|
||||
list(APPEND cxx_compile_options "-fno-rtti")
|
||||
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
|
||||
list(APPEND compile_options "-Wno-parentheses"
|
||||
"-Wno-sizeof-pointer-memaccess"
|
||||
"-Wno-clobbered")
|
||||
|
||||
# doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before
|
||||
if(GCC_NOT_5_2_0)
|
||||
list(APPEND compile_options "-Wno-format-overflow"
|
||||
"-Wno-stringop-truncation"
|
||||
"-Wno-misleading-indentation"
|
||||
"-Wno-cast-function-type"
|
||||
"-Wno-implicit-fallthrough"
|
||||
"-Wno-unused-const-variable"
|
||||
"-Wno-switch-unreachable"
|
||||
"-Wno-format-truncation"
|
||||
"-Wno-memset-elt-size"
|
||||
"-Wno-int-in-bool-context")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
|
||||
list(APPEND compile_definitions "-DNDEBUG")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM)
|
||||
list(APPEND compile_options "-fstack-protector")
|
||||
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG)
|
||||
list(APPEND compile_options "-fstack-protector-strong")
|
||||
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL)
|
||||
list(APPEND compile_options "-fstack-protector-all")
|
||||
endif()
|
||||
|
||||
list(APPEND link_options "-fno-lto")
|
||||
|
||||
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
|
||||
idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND)
|
||||
|
||||
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
|
||||
|
||||
# Add each component as a subdirectory, processing each component's CMakeLists.txt
|
||||
foreach(component_target ${build_component_targets})
|
||||
__component_get_property(dir ${component_target} COMPONENT_DIR)
|
||||
__component_get_property(_name ${component_target} COMPONENT_NAME)
|
||||
__component_get_property(prefix ${component_target} __PREFIX)
|
||||
__component_get_property(alias ${component_target} COMPONENT_ALIAS)
|
||||
set(COMPONENT_NAME ${_name})
|
||||
set(COMPONENT_DIR ${dir})
|
||||
set(COMPONENT_ALIAS ${alias})
|
||||
set(COMPONENT_PATH ${dir}) # for backward compatibility only, COMPONENT_DIR is preferred
|
||||
idf_build_get_property(build_prefix __PREFIX)
|
||||
set(__idf_component_context 1)
|
||||
if(NOT prefix STREQUAL build_prefix)
|
||||
add_subdirectory(${dir} ${prefix}_${_name})
|
||||
else()
|
||||
add_subdirectory(${dir} ${_name})
|
||||
endif()
|
||||
set(__idf_component_context 0)
|
||||
endforeach()
|
||||
@@ -53,7 +53,6 @@ Related Documents
|
||||
|
||||
style-guide
|
||||
documenting-code
|
||||
add-ons-reference
|
||||
creating-examples
|
||||
../api-reference/template
|
||||
contributor-agreement
|
||||
|
||||
406
Kconfig
406
Kconfig
@@ -4,243 +4,191 @@
|
||||
#
|
||||
mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
# Hidden option to support checking for this specific target in C code and Kconfig files
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
default "n"
|
||||
config IDF_CMAKE
|
||||
bool
|
||||
option env="IDF_CMAKE"
|
||||
|
||||
config IDF_CMAKE
|
||||
bool
|
||||
option env="IDF_CMAKE"
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
default 0x0000
|
||||
|
||||
menu "SDK tool configuration"
|
||||
config TOOLPREFIX
|
||||
string "Compiler toolchain path/prefix"
|
||||
default "xtensa-esp32-elf-"
|
||||
help
|
||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||
a crosstool-ng gcc setup that is in your PATH.
|
||||
|
||||
config PYTHON
|
||||
string "Python 2 interpreter"
|
||||
depends on !IDF_CMAKE
|
||||
default "python"
|
||||
help
|
||||
The executable name/path that is used to run python. On some systems Python 2.x
|
||||
may need to be invoked as python2.
|
||||
|
||||
(Note: This option is used with the GNU Make build system only, not idf.py
|
||||
or CMake-based builds.)
|
||||
|
||||
config MAKE_WARN_UNDEFINED_VARIABLES
|
||||
bool "'make' warns on undefined variables"
|
||||
default "y"
|
||||
help
|
||||
Adds --warn-undefined-variables to MAKEFLAGS. This causes make to
|
||||
print a warning any time an undefined variable is referenced.
|
||||
|
||||
This option helps find places where a variable reference is misspelled
|
||||
or otherwise missing, but it can be unwanted if you have Makefiles which
|
||||
depend on undefined variables expanding to an empty string.
|
||||
|
||||
endmenu # SDK tool configuration
|
||||
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||
|
||||
menu "Compiler options"
|
||||
|
||||
choice OPTIMIZATION_COMPILER
|
||||
prompt "Optimization Level"
|
||||
default OPTIMIZATION_LEVEL_DEBUG
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument).
|
||||
|
||||
- for "Release" setting, -Os flag is added to CFLAGS.
|
||||
- for "Debug" setting, -Og flag is added to CFLAGS.
|
||||
|
||||
"Release" with -Os produces smaller & faster compiled code but it
|
||||
may be harder to correlated code addresses to source files when debugging.
|
||||
|
||||
To add custom optimization settings, set CFLAGS and/or CPPFLAGS
|
||||
in project makefile, before including $(IDF_PATH)/make/project.mk. Note that
|
||||
custom optimization levels may be unsupported.
|
||||
|
||||
config OPTIMIZATION_LEVEL_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config OPTIMIZATION_LEVEL_RELEASE
|
||||
bool "Release (-Os)"
|
||||
endchoice
|
||||
|
||||
choice OPTIMIZATION_ASSERTION_LEVEL
|
||||
prompt "Assertion level"
|
||||
default OPTIMIZATION_ASSERTIONS_ENABLED
|
||||
help
|
||||
Assertions can be:
|
||||
|
||||
- Enabled. Failure will print verbose assertion details. This is the default.
|
||||
|
||||
- Set to "silent" to save code size (failed assertions will abort() but user
|
||||
needs to use the aborting address to find the line number with the failed assertion.)
|
||||
|
||||
- Disabled entirely (not recommended for most configurations.) -DNDEBUG is added
|
||||
to CPPFLAGS in this case.
|
||||
|
||||
config OPTIMIZATION_ASSERTIONS_ENABLED
|
||||
prompt "Enabled"
|
||||
bool
|
||||
help
|
||||
Enable assertions. Assertion content and line number will be printed on failure.
|
||||
|
||||
config OPTIMIZATION_ASSERTIONS_SILENT
|
||||
prompt "Silent (saves code size)"
|
||||
bool
|
||||
help
|
||||
Enable silent assertions. Failed assertions will abort(), user needs to
|
||||
use the aborting address to find the line number with the failed assertion.
|
||||
|
||||
config OPTIMIZATION_ASSERTIONS_DISABLED
|
||||
prompt "Disabled (sets -DNDEBUG)"
|
||||
bool
|
||||
help
|
||||
If assertions are disabled, -DNDEBUG is added to CPPFLAGS.
|
||||
|
||||
endchoice # assertions
|
||||
|
||||
menuconfig CXX_EXCEPTIONS
|
||||
bool "Enable C++ exceptions"
|
||||
default n
|
||||
help
|
||||
Enabling this option compiles all IDF C++ files with exception support enabled.
|
||||
|
||||
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws
|
||||
an exception will abort instead.
|
||||
|
||||
Enabling this option currently adds an additional ~500 bytes of heap overhead
|
||||
when an exception is thrown in user code for the first time.
|
||||
|
||||
config CXX_EXCEPTIONS_EMG_POOL_SIZE
|
||||
int "Emergency Pool Size"
|
||||
default 0
|
||||
depends on CXX_EXCEPTIONS
|
||||
help
|
||||
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
|
||||
memory for thrown exceptions when there is not enough memory on the heap.
|
||||
|
||||
choice STACK_CHECK_MODE
|
||||
prompt "Stack smashing protection mode"
|
||||
default STACK_CHECK_NONE
|
||||
help
|
||||
Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack
|
||||
smashing attacks. This is done by adding a guard variable to functions with vulnerable objects.
|
||||
The guards are initialized when a function is entered and then checked when the function exits.
|
||||
If a guard check fails, program is halted. Protection has the following modes:
|
||||
|
||||
- In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca,
|
||||
and functions with buffers larger than 8 bytes are protected.
|
||||
|
||||
- STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes
|
||||
additional functions to be protected -- those that have local array definitions,
|
||||
or have references to local frame addresses.
|
||||
|
||||
- In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected.
|
||||
|
||||
Modes have the following impact on code performance and coverage:
|
||||
|
||||
- performance: NORMAL > STRONG > OVERALL
|
||||
|
||||
- coverage: NORMAL < STRONG < OVERALL
|
||||
|
||||
|
||||
config IDF_TARGET_ENV
|
||||
# A proxy to get environment variable $IDF_TARGET
|
||||
string
|
||||
option env="IDF_TARGET"
|
||||
config STACK_CHECK_NONE
|
||||
bool "None"
|
||||
config STACK_CHECK_NORM
|
||||
bool "Normal"
|
||||
config STACK_CHECK_STRONG
|
||||
bool "Strong"
|
||||
config STACK_CHECK_ALL
|
||||
bool "Overall"
|
||||
endchoice
|
||||
|
||||
config IDF_TARGET
|
||||
# This option records the IDF target when sdkconfig is generated the first time.
|
||||
# It is not updated if environment variable $IDF_TARGET changes later, and
|
||||
# the build system is responsible for detecting the mismatch between
|
||||
# CONFIG_IDF_TARGET and $IDF_TARGET.
|
||||
string
|
||||
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
|
||||
default IDF_TARGET_ENV
|
||||
config STACK_CHECK
|
||||
bool
|
||||
default !STACK_CHECK_NONE
|
||||
help
|
||||
Stack smashing protection.
|
||||
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
default 0x0000 if IDF_TARGET="esp32"
|
||||
default 0xFFFF
|
||||
config WARN_WRITE_STRINGS
|
||||
bool "Enable -Wwrite-strings warning flag"
|
||||
default "n"
|
||||
help
|
||||
Adds -Wwrite-strings flag for the C/C++ compilers.
|
||||
|
||||
menu "SDK tool configuration"
|
||||
config SDK_TOOLPREFIX
|
||||
string "Compiler toolchain path/prefix"
|
||||
default "xtensa-esp32-elf-"
|
||||
help
|
||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||
a crosstool-ng gcc setup that is in your PATH.
|
||||
For C, this gives string constants the type ``const char[]`` so that
|
||||
copying the address of one into a non-const ``char *`` pointer
|
||||
produces a warning. This warning helps to find at compile time code
|
||||
that tries to write into a string constant.
|
||||
|
||||
config SDK_PYTHON
|
||||
string "Python interpreter"
|
||||
depends on !IDF_CMAKE
|
||||
default "python"
|
||||
help
|
||||
The executable name/path that is used to run python.
|
||||
For C++, this warns about the deprecated conversion from string
|
||||
literals to ``char *``.
|
||||
|
||||
(Note: This option is used with the legacy GNU Make build system only.)
|
||||
|
||||
config SDK_MAKE_WARN_UNDEFINED_VARIABLES
|
||||
bool "'make' warns on undefined variables"
|
||||
depends on !IDF_CMAKE
|
||||
default "y"
|
||||
help
|
||||
Adds --warn-undefined-variables to MAKEFLAGS. This causes make to
|
||||
print a warning any time an undefined variable is referenced.
|
||||
|
||||
This option helps find places where a variable reference is misspelled
|
||||
or otherwise missing, but it can be unwanted if you have Makefiles which
|
||||
depend on undefined variables expanding to an empty string.
|
||||
|
||||
(Note: this option is used with the legacy GNU Make build system only.)
|
||||
|
||||
endmenu # SDK tool configuration
|
||||
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||
|
||||
menu "Compiler options"
|
||||
|
||||
choice COMPILER_OPTIMIZATION
|
||||
prompt "Optimization Level"
|
||||
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument).
|
||||
|
||||
- for "Release" setting, -Os flag is added to CFLAGS.
|
||||
- for "Debug" setting, -Og flag is added to CFLAGS.
|
||||
|
||||
"Release" with -Os produces smaller & faster compiled code but it
|
||||
may be harder to correlated code addresses to source files when debugging.
|
||||
|
||||
To add custom optimization settings, set CFLAGS and/or CPPFLAGS
|
||||
in project makefile, before including $(IDF_PATH)/make/project.mk. Note that
|
||||
custom optimization levels may be unsupported.
|
||||
|
||||
config COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config COMPILER_OPTIMIZATION_LEVEL_RELEASE
|
||||
bool "Release (-Os)"
|
||||
endchoice
|
||||
|
||||
choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
prompt "Assertion level"
|
||||
default COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE
|
||||
help
|
||||
Assertions can be:
|
||||
|
||||
- Enabled. Failure will print verbose assertion details. This is the default.
|
||||
|
||||
- Set to "silent" to save code size (failed assertions will abort() but user
|
||||
needs to use the aborting address to find the line number with the failed assertion.)
|
||||
|
||||
- Disabled entirely (not recommended for most configurations.) -DNDEBUG is added
|
||||
to CPPFLAGS in this case.
|
||||
|
||||
config COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE
|
||||
prompt "Enabled"
|
||||
bool
|
||||
help
|
||||
Enable assertions. Assertion content and line number will be printed on failure.
|
||||
|
||||
config COMPILER_OPTIMIZATION_ASSERTIONS_SILENT
|
||||
prompt "Silent (saves code size)"
|
||||
bool
|
||||
help
|
||||
Enable silent assertions. Failed assertions will abort(), user needs to
|
||||
use the aborting address to find the line number with the failed assertion.
|
||||
|
||||
config COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE
|
||||
prompt "Disabled (sets -DNDEBUG)"
|
||||
bool
|
||||
help
|
||||
If assertions are disabled, -DNDEBUG is added to CPPFLAGS.
|
||||
|
||||
endchoice # assertions
|
||||
|
||||
menuconfig COMPILER_CXX_EXCEPTIONS
|
||||
bool "Enable C++ exceptions"
|
||||
default n
|
||||
help
|
||||
Enabling this option compiles all IDF C++ files with exception support enabled.
|
||||
|
||||
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code
|
||||
which throws an exception will abort instead.
|
||||
|
||||
Enabling this option currently adds an additional ~500 bytes of heap overhead
|
||||
when an exception is thrown in user code for the first time.
|
||||
|
||||
config COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE
|
||||
int "Emergency Pool Size"
|
||||
default 0
|
||||
depends on COMPILER_CXX_EXCEPTIONS
|
||||
help
|
||||
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
|
||||
memory for thrown exceptions when there is not enough memory on the heap.
|
||||
|
||||
config COMPILER_CXX_RTTI
|
||||
# Invisible option, until the toolchain with RTTI support is released.
|
||||
# Use prompt "Enable C++ run-time type info (RTTI)" when updating.
|
||||
bool
|
||||
help
|
||||
Enabling this option compiles all C++ files with RTTI support enabled.
|
||||
This increases binary size (typically by tens of kB) but allows using
|
||||
dynamic_cast conversion and typeid operator.
|
||||
|
||||
choice COMPILER_STACK_CHECK_MODE
|
||||
prompt "Stack smashing protection mode"
|
||||
default COMPILER_STACK_CHECK_MODE_NONE
|
||||
help
|
||||
Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack
|
||||
smashing attacks. This is done by adding a guard variable to functions with vulnerable objects.
|
||||
The guards are initialized when a function is entered and then checked when the function exits.
|
||||
If a guard check fails, program is halted. Protection has the following modes:
|
||||
|
||||
- In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with
|
||||
buffers larger than 8 bytes are protected.
|
||||
|
||||
- STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions
|
||||
to be protected -- those that have local array definitions, or have references to local frame
|
||||
addresses.
|
||||
|
||||
- In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected.
|
||||
|
||||
Modes have the following impact on code performance and coverage:
|
||||
|
||||
- performance: NORMAL > STRONG > OVERALL
|
||||
|
||||
- coverage: NORMAL < STRONG < OVERALL
|
||||
config DISABLE_GCC8_WARNINGS
|
||||
bool "Disable new warnings introduced in GCC 6 - 8"
|
||||
default "n"
|
||||
help
|
||||
Enable this option if using GCC 6 or newer, and wanting to disable warnings which don't appear with GCC 5.
|
||||
|
||||
|
||||
config COMPILER_STACK_CHECK_MODE_NONE
|
||||
bool "None"
|
||||
config COMPILER_STACK_CHECK_MODE_NORM
|
||||
bool "Normal"
|
||||
config COMPILER_STACK_CHECK_MODE_STRONG
|
||||
bool "Strong"
|
||||
config COMPILER_STACK_CHECK_MODE_ALL
|
||||
bool "Overall"
|
||||
endchoice
|
||||
endmenu # Compiler Options
|
||||
|
||||
config COMPILER_STACK_CHECK
|
||||
bool
|
||||
default !COMPILER_STACK_CHECK_MODE_NONE
|
||||
help
|
||||
Stack smashing protection.
|
||||
|
||||
config COMPILER_WARN_WRITE_STRINGS
|
||||
bool "Enable -Wwrite-strings warning flag"
|
||||
default "n"
|
||||
help
|
||||
Adds -Wwrite-strings flag for the C/C++ compilers.
|
||||
|
||||
For C, this gives string constants the type ``const char[]`` so that
|
||||
copying the address of one into a non-const ``char *`` pointer
|
||||
produces a warning. This warning helps to find at compile time code
|
||||
that tries to write into a string constant.
|
||||
|
||||
For C++, this warns about the deprecated conversion from string
|
||||
literals to ``char *``.
|
||||
|
||||
config COMPILER_DISABLE_GCC8_WARNINGS
|
||||
bool "Disable new warnings introduced in GCC 6 - 8"
|
||||
default "n"
|
||||
help
|
||||
Enable this option if using GCC 6 or newer, and wanting to disable warnings which don't appear with
|
||||
GCC 5.
|
||||
|
||||
|
||||
endmenu # Compiler Options
|
||||
|
||||
menu "Component config"
|
||||
source "$COMPONENT_KCONFIGS"
|
||||
endmenu
|
||||
|
||||
menu "Compatibility options"
|
||||
config LEGACY_INCLUDE_COMMON_HEADERS
|
||||
bool "Include headers accross components as before IDF v4.0"
|
||||
default n
|
||||
help
|
||||
Soc, esp32, and driver components, the most common
|
||||
components. Some header of these components are included
|
||||
implicitly by headers of other components before IDF v4.0.
|
||||
It's not required for high-level components, but still
|
||||
included through long header chain everywhere.
|
||||
|
||||
This is harmful to the modularity. So it's changed in IDF
|
||||
v4.0.
|
||||
|
||||
You can still include these headers in a legacy way until it
|
||||
is totally deprecated by enable this option.
|
||||
|
||||
endmenu #Compatibility options
|
||||
menu "Component config"
|
||||
source "$COMPONENT_KCONFIGS"
|
||||
endmenu
|
||||
|
||||
72
README.md
72
README.md
@@ -13,14 +13,6 @@ See setup guides for detailed instructions to set up the ESP-IDF:
|
||||
* [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
|
||||
* [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
|
||||
|
||||
### Non-GitHub forks
|
||||
|
||||
ESP-IDF uses relative locations as its submodules URLs ([.gitmodules](.gitmodules)). So they link to GitHub.
|
||||
If ESP-IDF is forked to a Git repository which is not on GitHub, you will need to run the script
|
||||
[tools/set-submodules-to-github.sh](tools/set-submodules-to-github.sh) after git clone.
|
||||
The script sets absolute URLs for all submodules, allowing `git submodule update --init --recursive` to complete.
|
||||
If cloning ESP-IDF from GitHub, this step is not needed.
|
||||
|
||||
## Finding a Project
|
||||
|
||||
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory.
|
||||
@@ -33,17 +25,9 @@ To start your own project based on an example, copy the example project director
|
||||
|
||||
See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects:
|
||||
|
||||
## Setup Build Environment
|
||||
|
||||
(See Getting Started guide for a full list of required steps with details.)
|
||||
|
||||
* Install host build dependencies mentioned in Getting Started guide.
|
||||
* Add `tools/` directory to the PATH
|
||||
* Run `python -m pip install -r requirements.txt` to install Python dependencies
|
||||
|
||||
## Configuring the Project
|
||||
|
||||
`idf.py menuconfig`
|
||||
`make menuconfig`
|
||||
|
||||
* Opens a text-based configuration menu for the project.
|
||||
* Use up & down arrow keys to navigate the menu.
|
||||
@@ -57,48 +41,76 @@ Once done configuring, press Escape multiple times to exit and say "Yes" to save
|
||||
|
||||
## Compiling the Project
|
||||
|
||||
`idf.py build`
|
||||
`make -j4 all`
|
||||
|
||||
... will compile app, bootloader and generate a partition table based on the config.
|
||||
|
||||
NOTE: The `-j4` option causes `make` to run 4 parallel jobs. This is much faster than the default single job. The recommended number to pass to this option is `-j(number of CPUs + 1)`.
|
||||
|
||||
## Flashing the Project
|
||||
|
||||
When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running:
|
||||
|
||||
`idf.py -p PORT flash`
|
||||
`make -j4 flash`
|
||||
|
||||
Replace PORT with the name of your serial port (like `COM3` on Windows, `/dev/ttyUSB0` on Linux, or `/dev/cu.usbserial-X` on MacOS. If the `-p` option is left out, `idf.py flash` will try to flash the first available serial port.
|
||||
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`.
|
||||
|
||||
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `idf.py menuconfig`.
|
||||
|
||||
You don't need to run `idf.py build` before running `idf.py flash`, `idf.py flash` will automatically rebuild anything which needs it.
|
||||
You don't need to run `make all` before running `make flash`, `make flash` will automatically rebuild anything which needs it.
|
||||
|
||||
## Viewing Serial Output
|
||||
|
||||
The `idf.py monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
|
||||
The `make monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
|
||||
|
||||
Exit the monitor by typing Ctrl-].
|
||||
|
||||
To build, flash and monitor output in one pass, you can run:
|
||||
|
||||
`idf.py flash monitor`
|
||||
`make -j4 flash monitor`
|
||||
|
||||
## Compiling & Flashing Only the App
|
||||
|
||||
After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table:
|
||||
|
||||
* `idf.py app` - build just the app.
|
||||
* `idf.py app-flash` - flash just the app.
|
||||
* `make app` - build just the app.
|
||||
* `make app-flash` - flash just the app.
|
||||
|
||||
`idf.py app-flash` will automatically rebuild the app if any source files have changed.
|
||||
`make app-flash` will automatically rebuild the app if any source files have changed.
|
||||
|
||||
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
|
||||
|
||||
## Parallel Builds
|
||||
|
||||
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to the number of CPU cores in your system, plus one.)
|
||||
|
||||
Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run:
|
||||
|
||||
```
|
||||
make -j5 flash monitor
|
||||
```
|
||||
|
||||
|
||||
## The Partition Table
|
||||
|
||||
Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader.
|
||||
|
||||
A single ESP32's flash can contain multiple apps, as well as many different kinds of data (calibration data, filesystems, parameter storage, etc). For this reason a partition table is flashed to offset 0x8000 in the flash.
|
||||
|
||||
Each entry in the partition table has a name (label), type (app, data, or something else), subtype and the offset in flash where the partition is loaded.
|
||||
|
||||
The simplest way to use the partition table is to `make menuconfig` and choose one of the simple predefined partition tables:
|
||||
|
||||
* "Single factory app, no OTA"
|
||||
* "Factory app, two OTA definitions"
|
||||
|
||||
In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table.
|
||||
|
||||
For more details about partition tables and how to create custom variations, view the [`docs/en/api-guides/partition-tables.rst`](docs/en/api-guides/partition-tables.rst) file.
|
||||
|
||||
## Erasing Flash
|
||||
|
||||
The `idf.py flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `idf.py erase_flash`.
|
||||
The `make flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `make erase_flash`.
|
||||
|
||||
This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table.
|
||||
This can be combined with other targets, ie `make erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table.
|
||||
|
||||
# Resources
|
||||
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
The latest support policy for ESP-IDF can be found at [https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md](https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md)
|
||||
|
||||
Support Period Policy
|
||||
=====================
|
||||
|
||||
Each ESP-IDF major and minor release (V4.0, V4.1, etc) is supported for
|
||||
18 months after the initial stable release date.
|
||||
|
||||
Supported means that the ESP-IDF team will continue to apply bug fixes,
|
||||
security fixes, etc to the release branch on GitHub, and periodically
|
||||
make new bugfix releases as needed.
|
||||
|
||||
Users are encouraged to upgrade to a newer ESP-IDF release before the
|
||||
support period finishes and the release becomes End of Life (EOL). It is
|
||||
our policy to not continue fixing bugs in End of Life releases.
|
||||
|
||||
Pre-release versions (betas, previews, `-rc` and `-dev` versions, etc)
|
||||
are not covered by any support period. Sometimes a particular feature is
|
||||
marked as \"Preview\" in a release, which means it is also not covered
|
||||
by the support period.
|
||||
|
||||
The ESP-IDF Programming Guide has information about the
|
||||
[different versions of ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/versions.html)
|
||||
(major, minor, bugfix, etc).
|
||||
|
||||
Long Term Support releases
|
||||
--------------------------
|
||||
|
||||
Some releases (starting with ESP-IDF V3.3) are designated Long Term
|
||||
Support (LTS). LTS releases are supported for 30 months (2.5 years)
|
||||
after the initial stable release date.
|
||||
|
||||
A new LTS release will be made at least every 18 months. This means
|
||||
there will always be a period of at least 12 months to upgrade from the
|
||||
previous LTS release to the following LTS release.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
ESP-IDF V3.3 was released in September 2019 and is a Long Term Support
|
||||
(LTS) release, meaning it will be supported for 30 months until February
|
||||
2022.
|
||||
|
||||
- The first V3.3 release was `v3.3` in September 2019.
|
||||
- The ESP-IDF team continues to backport bug fixes, security fixes,
|
||||
etc to the release branch `release/v3.3`.
|
||||
- Periodically stable bugfix releases are created from the release
|
||||
branch. For example `v3.3.1`, `v3.3.2`, etc. Users are encouraged to
|
||||
always update to the latest bugfix release.
|
||||
- V3.3 bugfix releases continue until February 2022, when all V3.3.x
|
||||
releases become End of Life.
|
||||
|
||||
Existing Releases
|
||||
-----------------
|
||||
|
||||
ESP-IDF release V3.3 and all newer releases will follow this support
|
||||
period policy. The support period for each release will be announced
|
||||
when the release is made.
|
||||
|
||||
For releases made before the support period policy was announced,
|
||||
the following support periods apply:
|
||||
|
||||
- ESP-IDF V3.1.x and V3.2.x will both be supported until October 2020.
|
||||
- ESP-IDF V3.0.9 (planned for October 2019) will be the last V3.0
|
||||
bugfix release. ESP-IDF V3.0.x is End of Life from October 2019.
|
||||
- ESP-IDF versions before V3.0 are already End of Life.
|
||||
@@ -9,7 +9,7 @@
|
||||
if [ -z ${IDF_PATH} ]; then
|
||||
echo "IDF_PATH must be set before including this script."
|
||||
else
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/esptool_py/esptool"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/"
|
||||
|
||||
@@ -1,36 +1,28 @@
|
||||
set(srcs
|
||||
"app_trace.c"
|
||||
"app_trace_util.c"
|
||||
"host_file_io.c"
|
||||
"gcov/gcov_rtio.c")
|
||||
|
||||
set(include_dirs "include")
|
||||
set(COMPONENT_SRCS "app_trace.c"
|
||||
"app_trace_util.c"
|
||||
"host_file_io.c"
|
||||
"gcov/gcov_rtio.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||
|
||||
if(CONFIG_SYSVIEW_ENABLE)
|
||||
list(APPEND include_dirs
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS
|
||||
sys_view/Config
|
||||
sys_view/SEGGER
|
||||
sys_view/Sample/OS)
|
||||
|
||||
list(APPEND srcs
|
||||
"sys_view/SEGGER/SEGGER_SYSVIEW.c"
|
||||
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
|
||||
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
|
||||
"sys_view/esp32/SEGGER_RTT_esp32.c"
|
||||
"sys_view/ext/heap_trace_module.c"
|
||||
"sys_view/ext/logging.c")
|
||||
list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c"
|
||||
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
|
||||
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
|
||||
"sys_view/esp32/SEGGER_RTT_esp32.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_HEAP_TRACING_TOHOST)
|
||||
list(APPEND srcs "heap_trace_tohost.c")
|
||||
endif()
|
||||
set(COMPONENT_REQUIRES)
|
||||
set(COMPONENT_PRIV_REQUIRES xtensa-debug-module)
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_REQUIRES soc
|
||||
LDFRAGMENTS linker.lf)
|
||||
register_component()
|
||||
|
||||
# disable --coverage for this component, as it is used as transport
|
||||
# for gcov
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC gcov ${LIBC} ${LIBM} gcc)
|
||||
component_compile_options("-fno-profile-arcs" "-fno-test-coverage")
|
||||
|
||||
target_link_libraries(app_trace gcov)
|
||||
|
||||
@@ -1,218 +1,202 @@
|
||||
menu "Application Level Tracing"
|
||||
|
||||
choice ESP32_APPTRACE_DESTINATION
|
||||
prompt "Data Destination"
|
||||
default ESP32_APPTRACE_DEST_NONE
|
||||
help
|
||||
Select destination for application trace: trace memory or none (to disable).
|
||||
choice ESP32_APPTRACE_DESTINATION
|
||||
prompt "Data Destination"
|
||||
default ESP32_APPTRACE_DEST_NONE
|
||||
help
|
||||
Select destination for application trace: trace memory or none (to disable).
|
||||
|
||||
config ESP32_APPTRACE_DEST_TRAX
|
||||
bool "Trace memory"
|
||||
select ESP32_APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_DEST_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
config ESP32_APPTRACE_DEST_TRAX
|
||||
bool "Trace memory"
|
||||
select ESP32_APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_DEST_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
|
||||
config ESP32_APPTRACE_ENABLE
|
||||
bool
|
||||
depends on !ESP32_TRAX
|
||||
select ESP32_MEMMAP_TRACEMEM
|
||||
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module.
|
||||
config ESP32_APPTRACE_ENABLE
|
||||
bool
|
||||
depends on !ESP32_TRAX
|
||||
select MEMMAP_TRACEMEM
|
||||
select MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module.
|
||||
|
||||
config ESP32_APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !SYSVIEW_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
config ESP32_APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !SYSVIEW_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
|
||||
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
|
||||
config ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
config ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
|
||||
config ESP32_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
int "Size of the pending data buffer"
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
default 0
|
||||
help
|
||||
Size of the buffer for events in bytes. It is useful for buffering events from
|
||||
the time critical code (scheduler, ISRs etc). If this parameter is 0 then
|
||||
events will be discarded when main HW buffer is full.
|
||||
config ESP32_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
int "Size of the pending data buffer"
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
default 0
|
||||
help
|
||||
Size of the buffer for events in bytes. It is useful for buffering events from
|
||||
the time critical code (scheduler, ISRs etc). If this parameter is 0 then
|
||||
events will be discarded when main HW buffer is full.
|
||||
|
||||
menu "FreeRTOS SystemView Tracing"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
config SYSVIEW_ENABLE
|
||||
bool "SystemView Tracing Enable"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables supporrt for SEGGER SystemView tracing functionality.
|
||||
menu "FreeRTOS SystemView Tracing"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
config SYSVIEW_ENABLE
|
||||
bool "SystemView Tracing Enable"
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables supporrt for SEGGER SystemView tracing functionality.
|
||||
|
||||
choice SYSVIEW_TS_SOURCE
|
||||
prompt "Timer to use as timestamp source"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_CCOUNT if FREERTOS_UNICORE && !PM_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_TIMER_00 if !FREERTOS_UNICORE && !PM_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_ESP_TIMER if PM_ENABLE
|
||||
help
|
||||
SystemView needs to use a hardware timer as the source of timestamps
|
||||
when tracing. This option selects the timer for it.
|
||||
choice SYSVIEW_TS_SOURCE
|
||||
prompt "Timer to use as timestamp source"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_CCOUNT if FREERTOS_UNICORE && !PM_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_TIMER_00 if !FREERTOS_UNICORE && !PM_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_ESP_TIMER if PM_ENABLE
|
||||
help
|
||||
SystemView needs to use a hardware timer as the source of timestamps
|
||||
when tracing. This option selects the timer for it.
|
||||
|
||||
config SYSVIEW_TS_SOURCE_CCOUNT
|
||||
bool "CPU cycle counter (CCOUNT)"
|
||||
depends on FREERTOS_UNICORE && !PM_ENABLE
|
||||
config SYSVIEW_TS_SOURCE_CCOUNT
|
||||
bool "CPU cycle counter (CCOUNT)"
|
||||
depends on FREERTOS_UNICORE && !PM_ENABLE
|
||||
|
||||
config SYSVIEW_TS_SOURCE_TIMER_00
|
||||
bool "Timer 0, Group 0"
|
||||
depends on !PM_ENABLE
|
||||
config SYSVIEW_TS_SOURCE_TIMER_00
|
||||
bool "Timer 0, Group 0"
|
||||
depends on !PM_ENABLE
|
||||
|
||||
config SYSVIEW_TS_SOURCE_TIMER_01
|
||||
bool "Timer 1, Group 0"
|
||||
depends on !PM_ENABLE
|
||||
config SYSVIEW_TS_SOURCE_TIMER_01
|
||||
bool "Timer 1, Group 0"
|
||||
depends on !PM_ENABLE
|
||||
|
||||
config SYSVIEW_TS_SOURCE_TIMER_10
|
||||
bool "Timer 0, Group 1"
|
||||
depends on !PM_ENABLE
|
||||
config SYSVIEW_TS_SOURCE_TIMER_10
|
||||
bool "Timer 0, Group 1"
|
||||
depends on !PM_ENABLE
|
||||
|
||||
config SYSVIEW_TS_SOURCE_TIMER_11
|
||||
bool "Timer 1, Group 1"
|
||||
depends on !PM_ENABLE
|
||||
config SYSVIEW_TS_SOURCE_TIMER_11
|
||||
bool "Timer 1, Group 1"
|
||||
depends on !PM_ENABLE
|
||||
|
||||
config SYSVIEW_TS_SOURCE_ESP_TIMER
|
||||
bool "esp_timer high resolution timer"
|
||||
config SYSVIEW_TS_SOURCE_ESP_TIMER
|
||||
bool "esp_timer high resolution timer"
|
||||
|
||||
endchoice
|
||||
endchoice
|
||||
|
||||
config SYSVIEW_MAX_TASKS
|
||||
int "Maximum supported tasks"
|
||||
depends on SYSVIEW_ENABLE
|
||||
range 1 64
|
||||
default 16
|
||||
help
|
||||
Configures maximum supported tasks in sysview debug
|
||||
config SYSVIEW_EVT_OVERFLOW_ENABLE
|
||||
bool "Trace Buffer Overflow Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Trace Buffer Overflow" event.
|
||||
|
||||
config SYSVIEW_BUF_WAIT_TMO
|
||||
int "Trace buffer wait timeout"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default 500
|
||||
help
|
||||
Configures timeout (in us) to wait for free space in trace buffer.
|
||||
Set to -1 to wait forever and avoid lost events.
|
||||
config SYSVIEW_EVT_ISR_ENTER_ENABLE
|
||||
bool "ISR Enter Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Enter" event.
|
||||
|
||||
config SYSVIEW_EVT_OVERFLOW_ENABLE
|
||||
bool "Trace Buffer Overflow Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Trace Buffer Overflow" event.
|
||||
config SYSVIEW_EVT_ISR_EXIT_ENABLE
|
||||
bool "ISR Exit Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Exit" event.
|
||||
|
||||
config SYSVIEW_EVT_ISR_ENTER_ENABLE
|
||||
bool "ISR Enter Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Enter" event.
|
||||
config SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE
|
||||
bool "ISR Exit to Scheduler Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR to Scheduler" event.
|
||||
|
||||
config SYSVIEW_EVT_ISR_EXIT_ENABLE
|
||||
bool "ISR Exit Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Exit" event.
|
||||
config SYSVIEW_EVT_TASK_START_EXEC_ENABLE
|
||||
bool "Task Start Execution Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Execution" event.
|
||||
|
||||
config SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE
|
||||
bool "ISR Exit to Scheduler Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR to Scheduler" event.
|
||||
config SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE
|
||||
bool "Task Stop Execution Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Execution" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_START_EXEC_ENABLE
|
||||
bool "Task Start Execution Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Execution" event.
|
||||
config SYSVIEW_EVT_TASK_START_READY_ENABLE
|
||||
bool "Task Start Ready State Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Ready State" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE
|
||||
bool "Task Stop Execution Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Execution" event.
|
||||
config SYSVIEW_EVT_TASK_STOP_READY_ENABLE
|
||||
bool "Task Stop Ready State Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Ready State" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_START_READY_ENABLE
|
||||
bool "Task Start Ready State Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Ready State" event.
|
||||
config SYSVIEW_EVT_TASK_CREATE_ENABLE
|
||||
bool "Task Create Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Create" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_STOP_READY_ENABLE
|
||||
bool "Task Stop Ready State Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Ready State" event.
|
||||
config SYSVIEW_EVT_TASK_TERMINATE_ENABLE
|
||||
bool "Task Terminate Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Terminate" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_CREATE_ENABLE
|
||||
bool "Task Create Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Create" event.
|
||||
config SYSVIEW_EVT_IDLE_ENABLE
|
||||
bool "System Idle Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "System Idle" event.
|
||||
|
||||
config SYSVIEW_EVT_TASK_TERMINATE_ENABLE
|
||||
bool "Task Terminate Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Terminate" event.
|
||||
config SYSVIEW_EVT_TIMER_ENTER_ENABLE
|
||||
bool "Timer Enter Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Enter" event.
|
||||
|
||||
config SYSVIEW_EVT_IDLE_ENABLE
|
||||
bool "System Idle Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "System Idle" event.
|
||||
|
||||
config SYSVIEW_EVT_TIMER_ENTER_ENABLE
|
||||
bool "Timer Enter Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Enter" event.
|
||||
|
||||
config SYSVIEW_EVT_TIMER_EXIT_ENABLE
|
||||
bool "Timer Exit Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Exit" event.
|
||||
|
||||
endmenu
|
||||
|
||||
config ESP32_GCOV_ENABLE
|
||||
bool "GCOV to Host Enable"
|
||||
depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables support for GCOV data transfer to host.
|
||||
config SYSVIEW_EVT_TIMER_EXIT_ENABLE
|
||||
bool "Timer Exit Event"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Exit" event.
|
||||
|
||||
endmenu
|
||||
|
||||
config ESP32_GCOV_ENABLE
|
||||
bool "GCOV to Host Enable"
|
||||
depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables support for GCOV data transfer to host.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
// |<------------------------------------------->|TRAX_CTRL_REGS|<---->|
|
||||
// ----------------
|
||||
|
||||
// In general tracing goes in the following way. User application requests tracing module to send some data by calling esp_apptrace_buffer_get(),
|
||||
// In general tracing goes in the following way. User aplication requests tracing module to send some data by calling esp_apptrace_buffer_get(),
|
||||
// module allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put().
|
||||
// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts.
|
||||
// While target application fills one TRAX block host reads another one via JTAG.
|
||||
@@ -62,7 +62,7 @@
|
||||
// 21..15 bits - trace memory block transfer ID. Block counter. It can overflow. Updated by target, host should not modify it. Actually can be 2 bits;
|
||||
// 22 bit - 'host data present' flag. If set to one there is data from host, otherwise - no host data;
|
||||
// 23 bit - 'host connected' flag. If zero then host is not connected and tracing module works in post-mortem mode, otherwise in streaming mode;
|
||||
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then current CPU is changing TRAX registers and
|
||||
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then currentlly CPU is changing TRAX registers and
|
||||
// this register holds address of the instruction which application will execute when it finishes with those registers modifications.
|
||||
// See 'Targets Connection' setion for details.
|
||||
|
||||
@@ -75,8 +75,7 @@
|
||||
// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them.
|
||||
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
|
||||
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
|
||||
// CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH
|
||||
// which controls the threshold for flushing data in case of panic.
|
||||
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
|
||||
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
|
||||
@@ -88,7 +87,7 @@
|
||||
// 4.1 Trace Memory Blocks
|
||||
// -----------------------
|
||||
|
||||
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data available.
|
||||
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data avalable.
|
||||
// When current input memory block is filled it is exposed to host and 'block_len' and 'block_id' fields are updated in the control register.
|
||||
// Host reads new register value and according to it's value starts reading data from exposed block. Meanwhile target starts filling another trace block.
|
||||
// When host finishes reading the block it clears 'block_len' field in control register indicating to the target that it is ready to accept the next one.
|
||||
@@ -103,9 +102,9 @@
|
||||
// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation
|
||||
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
|
||||
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
|
||||
// which reads application traces reports error when it reads incomplete user data block.
|
||||
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
|
||||
// containing length of host data following the header.
|
||||
// which reads application traces reports error when it reads incompleted user data block.
|
||||
// Data which are transfered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
|
||||
// containing length of host data following the heder.
|
||||
|
||||
// 4.3 Data Buffering
|
||||
// ------------------
|
||||
@@ -142,25 +141,28 @@
|
||||
// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU.
|
||||
// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another.
|
||||
// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting
|
||||
// on internal locks and for host to complete previous block reading, so if timeout value exceeds watchdog's one it can lead to the system reboot.
|
||||
// on internal locks and for host to complete previous block reading, so if timeout value exceedes watchdog's one it can lead to the system reboot.
|
||||
|
||||
// 6. Timeouts
|
||||
// ===========
|
||||
|
||||
// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in microseconds.
|
||||
// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in micorseconds.
|
||||
// There are two situations when task/ISR can be delayed by tracing API call. Timeout mechanism takes into account both conditions:
|
||||
// - Trace data are locked by another task/ISR. When wating on trace data lock.
|
||||
// - Current TRAX memory input block is full when working in streaming mode (host is connected). When waiting for host to complete previous block reading.
|
||||
// When wating for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed
|
||||
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
|
||||
|
||||
// ALSO SEE example usage of application tracing module in 'components/app_trace/README.rst'
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "eri.h"
|
||||
#include "trax.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
@@ -170,6 +172,7 @@
|
||||
|
||||
#define ESP_APPTRACE_PRINT_LOCK 0
|
||||
|
||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
@@ -929,9 +932,6 @@ esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size,
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (buf == NULL || size == NULL || *size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
//TODO: callback system
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
@@ -966,10 +966,8 @@ uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size,
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return NULL;
|
||||
}
|
||||
if (size == NULL || *size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ESP_APPTRACE_LOGE("esp_apptrace_down_buffer_get %d", *size);
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return hw->get_down_buffer(size, &tmo);
|
||||
}
|
||||
@@ -990,9 +988,6 @@ esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, u
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return hw->put_down_buffer(ptr, &tmo);
|
||||
@@ -1015,9 +1010,6 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (data == NULL || size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
ptr = hw->get_up_buffer(size, &tmo);
|
||||
@@ -1051,9 +1043,6 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (fmt == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
ESP_APPTRACE_LOGD("fmt %x", fmt);
|
||||
@@ -1115,9 +1104,6 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return NULL;
|
||||
}
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return hw->get_up_buffer(size, &tmo);
|
||||
@@ -1139,9 +1125,6 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return hw->put_up_buffer(ptr, &tmo);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp32/clk.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
|
||||
@@ -23,10 +23,7 @@ COMPONENT_SRCDIRS += \
|
||||
sys_view/SEGGER \
|
||||
sys_view/Sample/OS \
|
||||
sys_view/Sample/Config \
|
||||
sys_view/esp32 \
|
||||
sys_view/ext
|
||||
sys_view/esp32
|
||||
else
|
||||
COMPONENT_SRCDIRS += gcov
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFRAGMENTS += linker.lf
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "esp_dbg_stubs.h"
|
||||
|
||||
#if CONFIG_ESP32_GCOV_ENABLE
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 <sdkconfig.h>
|
||||
|
||||
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
|
||||
#include "esp_heap_trace.h"
|
||||
#undef HEAP_TRACE_SRCFILE
|
||||
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_sysview_trace.h"
|
||||
#endif
|
||||
|
||||
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
|
||||
#ifdef CONFIG_HEAP_TRACING_TOHOST
|
||||
|
||||
#if !CONFIG_SYSVIEW_ENABLE
|
||||
#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature.
|
||||
#endif
|
||||
|
||||
static bool s_tracing;
|
||||
|
||||
esp_err_t heap_trace_init_tohost()
|
||||
{
|
||||
if (s_tracing) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
||||
{
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
s_tracing = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_stop(void)
|
||||
{
|
||||
esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
ret = esp_sysview_heap_trace_stop();
|
||||
#endif
|
||||
s_tracing = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_resume(void)
|
||||
{
|
||||
return heap_trace_start(HEAP_TRACE_ALL);
|
||||
}
|
||||
|
||||
size_t heap_trace_get_count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void heap_trace_dump(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a new allocation to the heap trace records */
|
||||
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
|
||||
{
|
||||
if (!s_tracing) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* record a free event in the heap trace log
|
||||
|
||||
For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
|
||||
For HEAP_TRACE_LEAKS, this means removing the record from the log.
|
||||
*/
|
||||
static IRAM_ATTR void record_free(void *p, void **callers)
|
||||
{
|
||||
if (!s_tracing) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
esp_sysview_heap_trace_free(p, callers);
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "heap_trace.inc"
|
||||
|
||||
#endif /*CONFIG_HEAP_TRACING_TOHOST*/
|
||||
|
||||
@@ -145,9 +145,6 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
|
||||
esp_apptrace_fopen_args_t cmd_args;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);
|
||||
if (path == NULL || mode == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_args.path = path;
|
||||
cmd_args.path_len = strlen(path) + 1;
|
||||
@@ -216,10 +213,6 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_args.buf = (void *)ptr;
|
||||
cmd_args.size = size * nmemb;
|
||||
cmd_args.file = stream;
|
||||
@@ -255,10 +248,6 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_args.size = size * nmemb;
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
|
||||
|
||||
@@ -51,7 +51,7 @@ void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
|
||||
*
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param size Size of data to write to trace buffer.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
@@ -63,7 +63,7 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32
|
||||
*
|
||||
* @param dest Indicates HW interface to send data. Should be identical to the same parameter in call to esp_apptrace_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_buffer_get.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param data Address of data to write to trace buffer.
|
||||
* @param size Size of data to write to trace buffer.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
@@ -85,7 +85,7 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
|
||||
* @brief vprintf-like function to sent log messages to host via specified HW interface.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
* @param fmt Address of format string.
|
||||
* @param ap List of arguments.
|
||||
*
|
||||
@@ -107,7 +107,7 @@ int esp_apptrace_vprintf(const char *fmt, va_list ap);
|
||||
* @brief Flushes remaining data in trace buffer to host.
|
||||
*
|
||||
* @param dest Indicates HW interface to flush data on.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
@@ -119,7 +119,7 @@ esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo);
|
||||
*
|
||||
* @param dest Indicates HW interface to flush data on.
|
||||
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
@@ -131,31 +131,31 @@ esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, u
|
||||
* @param dest Indicates HW interface to read the data on.
|
||||
* @param data Address of buffer to put data from trace buffer.
|
||||
* @param size Pointer to store size of read data. Before call to this function pointed memory must hold requested size of data
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *data, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Retrieves incoming data buffer if any.
|
||||
* @brief Rertrieves incoming data buffer if any.
|
||||
* After data in buffer are processed esp_apptrace_down_buffer_put must be called to indicate it.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data.
|
||||
* @param size Address to store size of available data in down buffer. Must be initialized with requested value.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param size Address to store size of available data in down buffer. Must be initializaed with requested value.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Indicates that the data in down buffer are processed.
|
||||
* @brief Indicates that the data in down buffer are processesd.
|
||||
* This function is a counterpart of and must be preceeded by esp_apptrace_down_buffer_get.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data. Should be identical to the same parameter in call to esp_apptrace_down_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_down_buffer_get.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
@@ -247,7 +247,7 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream);
|
||||
|
||||
/**
|
||||
* @brief Indicates to the host that all file operations are completed.
|
||||
* This function should be called after all file operations are finished and
|
||||
* This function should be called after all file operations are finished and
|
||||
* indicate to the host that it can perform cleanup operations (close open files etc.).
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 ESP_SYSVIEW_TRACE_H_
|
||||
#define ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
/**
|
||||
* @brief Flushes remaining data in SystemView trace buffer to host.
|
||||
*
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK.
|
||||
*/
|
||||
static inline esp_err_t esp_sysview_flush(uint32_t tmo)
|
||||
{
|
||||
SEGGER_RTT_ESP32_Flush(0, tmo);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief vprintf-like function to sent log messages to the host.
|
||||
*
|
||||
* @param format Address of format string.
|
||||
* @param args List of arguments.
|
||||
*
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
int esp_sysview_vprintf(const char * format, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Starts SystemView heap tracing.
|
||||
*
|
||||
* @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever.
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out.
|
||||
*/
|
||||
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Stops SystemView heap tracing.
|
||||
*
|
||||
* @return ESP_OK.
|
||||
*/
|
||||
esp_err_t esp_sysview_heap_trace_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Sends heap allocation event to the host.
|
||||
*
|
||||
* @param addr Address of allocated block.
|
||||
* @param size Size of allocated block.
|
||||
* @param callers Pointer to array with callstack addresses.
|
||||
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||
*/
|
||||
void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers);
|
||||
|
||||
/**
|
||||
* @brief Sends heap de-allocation event to the host.
|
||||
*
|
||||
* @param addr Address of de-allocated block.
|
||||
* @param callers Pointer to array with callstack addresses.
|
||||
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||
*/
|
||||
void esp_sysview_heap_trace_free(void *addr, const void *callers);
|
||||
|
||||
#endif //ESP_SYSVIEW_TRACE_H_
|
||||
@@ -1,18 +0,0 @@
|
||||
[mapping:app_trace]
|
||||
archive: libapp_trace.a
|
||||
entries:
|
||||
app_trace (noflash)
|
||||
app_trace_util (noflash)
|
||||
SEGGER_SYSVIEW (noflash)
|
||||
SEGGER_RTT_esp32 (noflash)
|
||||
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
|
||||
SEGGER_SYSVIEW_FreeRTOS (noflash)
|
||||
|
||||
[mapping:driver]
|
||||
archive: libdriver.a
|
||||
entries:
|
||||
if SYSVIEW_TS_SOURCE_TIMER_00 = y || SYSVIEW_TS_SOURCE_TIMER_01 = y
|
||||
|| SYSVIEW_TS_SOURCE_TIMER_10 = y || SYSVIEW_TS_SOURCE_TIMER_11 = y:
|
||||
timer (noflash)
|
||||
else:
|
||||
* (default)
|
||||
@@ -1,23 +0,0 @@
|
||||
# idf_create_lcov_report
|
||||
#
|
||||
# Create coverage report.
|
||||
function(idf_create_coverage_report report_dir)
|
||||
set(gcov_tool ${CONFIG_SDK_TOOLPREFIX}gcov)
|
||||
idf_build_get_property(project_name PROJECT_NAME)
|
||||
|
||||
add_custom_target(lcov-report
|
||||
COMMENT "Generating coverage report in: ${report_dir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Using gcov: ${gcov_tool}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${report_dir}/html
|
||||
COMMAND lcov --gcov-tool ${gcov_tool} -c -d ${CMAKE_CURRENT_BINARY_DIR} -o ${report_dir}/${project_name}.info
|
||||
COMMAND genhtml -o ${report_dir}/html ${report_dir}/${project_name}.info)
|
||||
endfunction()
|
||||
|
||||
# idf_clean_coverage_report
|
||||
#
|
||||
# Clean coverage report.
|
||||
function(idf_clean_coverage_report report_dir)
|
||||
add_custom_target(cov-data-clean
|
||||
COMMENT "Clean coverage report in: ${report_dir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${report_dir})
|
||||
endfunction()
|
||||
@@ -1,4 +0,0 @@
|
||||
# sdkconfig replacement configurations for deprecated options formatted as
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
@@ -166,11 +166,10 @@ Revision: $Rev: 5927 $
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() SEGGER_SYSVIEW_X_GetInterruptId() // Get the currently active interrupt Id from the user-provided function.
|
||||
#endif
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock();
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state);
|
||||
// to be recursive save IRQ status on the stack of the caller
|
||||
#define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
#define SEGGER_SYSVIEW_UNLOCK() SEGGER_SYSVIEW_X_SysView_Unlock(_SYSVIEW_int_state)
|
||||
void SEGGER_SYSVIEW_X_SysView_Lock();
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock();
|
||||
#define SEGGER_SYSVIEW_LOCK() SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
#define SEGGER_SYSVIEW_UNLOCK() SEGGER_SYSVIEW_X_SysView_Unlock()
|
||||
|
||||
#endif // SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
|
||||
@@ -160,7 +160,6 @@ unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const voi
|
||||
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
||||
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo);
|
||||
void SEGGER_RTT_ESP32_Flush (unsigned long min_sz, unsigned long tmo);
|
||||
//
|
||||
// Function macro for performance optimization
|
||||
//
|
||||
|
||||
@@ -1689,10 +1689,6 @@ void SEGGER_SYSVIEW_Stop(void) {
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
U8 SEGGER_SYSVIEW_Started(void) {
|
||||
return _SYSVIEW_Globals.EnableState;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_GetSysDesc()
|
||||
@@ -2372,7 +2368,7 @@ void SEGGER_SYSVIEW_RegisterModule(SEGGER_SYSVIEW_MODULE* pModule) {
|
||||
_pFirstModule = pModule;
|
||||
_NumModules++;
|
||||
}
|
||||
SEGGER_SYSVIEW_SendModule(_NumModules-1);
|
||||
SEGGER_SYSVIEW_SendModule(0);
|
||||
if (pModule->pfSendModuleDesc) {
|
||||
pModule->pfSendModuleDesc();
|
||||
}
|
||||
@@ -2682,7 +2678,7 @@ void SEGGER_SYSVIEW_ErrorfTarget(const char* s, ...) {
|
||||
void SEGGER_SYSVIEW_Print(const char* s) {
|
||||
U8* pPayload;
|
||||
U8* pPayloadStart;
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN + 3/*1 or 3 bytes for string length*/);
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
//
|
||||
pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG);
|
||||
|
||||
@@ -230,8 +230,6 @@ void SEGGER_SYSVIEW_GetSysDesc (void);
|
||||
void SEGGER_SYSVIEW_SendTaskList (void);
|
||||
void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo);
|
||||
void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc);
|
||||
// Checks whether tracing has been started
|
||||
U8 SEGGER_SYSVIEW_Started(void);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
|
||||
@@ -63,11 +63,11 @@ Revision: $Rev: 3734 $
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp32/clk.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
@@ -337,18 +337,15 @@ void SEGGER_SYSVIEW_X_RTT_Unlock()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
void SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
|
||||
esp_apptrace_lock_take(&s_sys_view_lock, &tmo);
|
||||
// to be recursive save IRQ status on the stack of the caller to keep it from overwriting
|
||||
return s_sys_view_lock.int_state;
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state)
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock()
|
||||
{
|
||||
s_sys_view_lock.int_state = int_state;
|
||||
esp_apptrace_lock_give(&s_sys_view_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ Notes:
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#endif
|
||||
|
||||
#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_SYSVIEW_MAX_TASKS
|
||||
#define SYSVIEW_FREERTOS_MAX_NOF_TASKS 16
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
@@ -244,10 +244,8 @@ Notes:
|
||||
#define traceQUEUE_SEND( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
|
||||
#endif
|
||||
#define traceQUEUE_SEND_FAILED( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
|
||||
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||
#define traceQUEUE_GIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
|
||||
#if( portSTACK_GROWTH < 0 )
|
||||
#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
@@ -28,12 +27,8 @@ const static char *TAG = "segger_rtt";
|
||||
|
||||
// size of down channel data buf
|
||||
#define SYSVIEW_DOWN_BUF_SIZE 32
|
||||
#define SEGGER_HOST_WAIT_TMO 500 //us
|
||||
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
||||
#if CONFIG_SYSVIEW_BUF_WAIT_TMO == -1
|
||||
#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
|
||||
#else
|
||||
#define SEGGER_HOST_WAIT_TMO CONFIG_SYSVIEW_BUF_WAIT_TMO
|
||||
#endif
|
||||
|
||||
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
|
||||
static uint16_t s_events_buf_filled;
|
||||
@@ -62,12 +57,9 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
|
||||
*/
|
||||
void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
||||
{
|
||||
esp_err_t res;
|
||||
if (s_events_buf_filled > 0) {
|
||||
res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
|
||||
}
|
||||
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
|
||||
}
|
||||
// flush even if we failed to write buffered events, because no new events will be sent after STOP
|
||||
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo);
|
||||
@@ -77,27 +69,6 @@ void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
||||
s_events_buf_filled = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ESP32_Flush()
|
||||
*
|
||||
* Function description
|
||||
* Flushes buffered events.
|
||||
*
|
||||
* Parameters
|
||||
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* Return value
|
||||
* None.
|
||||
*/
|
||||
void SEGGER_RTT_ESP32_Flush(unsigned long min_sz, unsigned long tmo)
|
||||
{
|
||||
SEGGER_SYSVIEW_LOCK();
|
||||
SEGGER_RTT_ESP32_FlushNoLock(min_sz, tmo);
|
||||
SEGGER_SYSVIEW_UNLOCK();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ReadNoLock()
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 <stdint.h>
|
||||
#include <sdkconfig.h>
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "sysview_heap_trace";
|
||||
|
||||
#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
#else
|
||||
#define CALLSTACK_SIZE 0
|
||||
#endif
|
||||
|
||||
static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
|
||||
.sModule = "ESP32 SystemView Heap Tracing Module",
|
||||
.NumEvents = 2,
|
||||
};
|
||||
|
||||
static bool s_mod_registered;
|
||||
|
||||
|
||||
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
|
||||
{
|
||||
uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||
do {
|
||||
if (tmo != (uint32_t)-1) {
|
||||
// Currently timeout implementation is simple and has granularity of 1 OS tick,
|
||||
// so just count down the number of times to call vTaskDelay
|
||||
if (tmo_ticks-- == 0) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
vTaskDelay(1);
|
||||
} while(!SEGGER_SYSVIEW_Started());
|
||||
|
||||
SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
|
||||
s_mod_registered = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sysview_heap_trace_stop(void)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||
SEGGER_RTT_ESP32_Flush(0, ESP_APPTRACE_TMO_INFINITE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
|
||||
{
|
||||
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||
U32 *calls = (U32 *)callers;
|
||||
|
||||
if (!s_mod_registered) {
|
||||
return;
|
||||
}
|
||||
ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size);
|
||||
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||
}
|
||||
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0);
|
||||
}
|
||||
|
||||
void esp_sysview_heap_trace_free(const void *addr, const void *callers)
|
||||
{
|
||||
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||
U32 *calls = (U32 *)callers;
|
||||
|
||||
if (!s_mod_registered) {
|
||||
return;
|
||||
}
|
||||
ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||
}
|
||||
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sdkconfig.h>
|
||||
#include "SEGGER_SYSVIEW_Int.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
int esp_sysview_vprintf(const char * format, va_list args)
|
||||
{
|
||||
static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN];
|
||||
|
||||
portENTER_CRITICAL(&s_log_mutex);
|
||||
size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args);
|
||||
if (len > sizeof(log_buffer) - 1) {
|
||||
log_buffer[sizeof(log_buffer - 1)] = 0;
|
||||
}
|
||||
SEGGER_SYSVIEW_Print(log_buffer);
|
||||
portEXIT_CRITICAL(&s_log_mutex);
|
||||
return len;
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity)
|
||||
set(COMPONENT_SRCDIRS ".")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
set(COMPONENT_REQUIRES unity)
|
||||
|
||||
register_component()
|
||||
@@ -1,57 +1,17 @@
|
||||
idf_component_register(SRCS "esp_ota_ops.c"
|
||||
"esp_app_desc.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES spi_flash partition_table bootloader_support)
|
||||
set(COMPONENT_SRCS "esp_ota_ops.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||
|
||||
# esp_app_desc structure is added as an undefined symbol because otherwise the
|
||||
# linker will ignore this structure as it has no other files depending on it.
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc")
|
||||
set(COMPONENT_REQUIRES spi_flash partition_table)
|
||||
set(COMPONENT_PRIV_REQUIRES bootloader_support)
|
||||
|
||||
# cut PROJECT_VER and PROJECT_NAME to required 32 characters.
|
||||
idf_build_get_property(project_ver PROJECT_VER)
|
||||
idf_build_get_property(project_name PROJECT_NAME)
|
||||
string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT)
|
||||
string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT)
|
||||
register_component()
|
||||
|
||||
set_source_files_properties(
|
||||
SOURCE "esp_app_desc.c"
|
||||
PROPERTIES COMPILE_DEFINITIONS
|
||||
"PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"")
|
||||
# Add custom target for generating empty otadata partition for flashing
|
||||
if(${OTADATA_PARTITION_OFFSET})
|
||||
add_custom_command(OUTPUT "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}"
|
||||
COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/gen_empty_partition.py
|
||||
--size ${OTADATA_PARTITION_SIZE} "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}")
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
partition_table_get_partition_info(otadata_offset "--partition-type data --partition-subtype ota" "offset")
|
||||
partition_table_get_partition_info(otadata_size "--partition-type data --partition-subtype ota" "size")
|
||||
|
||||
# Add custom target for generating empty otadata partition for flashing
|
||||
if(otadata_size AND otadata_offset)
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
set(blank_otadata_file ${build_dir}/ota_data_initial.bin)
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(python PYTHON)
|
||||
add_custom_command(OUTPUT ${blank_otadata_file}
|
||||
COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
|
||||
${otadata_size} ${blank_otadata_file})
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
add_dependencies(flash blank_ota_data)
|
||||
|
||||
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
|
||||
|
||||
set(esptool_args --esptool-args before=${CONFIG_ESPTOOLPY_BEFORE} after=${CONFIG_ESPTOOLPY_AFTER})
|
||||
|
||||
add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}"
|
||||
COMMAND ${otatool_py} ${esptool_args}
|
||||
--partition-table-file ${PARTITION_CSV_PATH}
|
||||
--partition-table-offset ${PARTITION_TABLE_OFFSET}
|
||||
read_otadata)
|
||||
|
||||
add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}"
|
||||
COMMAND ${otatool_py} ${esptool_args}
|
||||
--partition-table-file ${PARTITION_CSV_PATH}
|
||||
--partition-table-offset ${PARTITION_TABLE_OFFSET}
|
||||
erase_otadata)
|
||||
|
||||
esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT)
|
||||
endif()
|
||||
add_custom_target(blank_ota_data ALL DEPENDS "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}")
|
||||
add_dependencies(flash blank_ota_data)
|
||||
endif()
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
menu "Application manager"
|
||||
|
||||
config APP_COMPILE_TIME_DATE
|
||||
bool "Use time/date stamp for app"
|
||||
default y
|
||||
help
|
||||
If set, then the app will be built with the current time/date stamp. It is stored in the app description
|
||||
structure. If not set, time/date stamp will be excluded from app image. This can be useful for getting the
|
||||
same binary image files made from the same source, but at different times.
|
||||
|
||||
config APP_EXCLUDE_PROJECT_VER_VAR
|
||||
bool "Exclude PROJECT_VER from firmware image"
|
||||
default n
|
||||
help
|
||||
The PROJECT_VER variable from the build system will not affect the firmware image.
|
||||
This value will not be contained in the esp_app_desc structure.
|
||||
|
||||
config APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
bool "Exclude PROJECT_NAME from firmware image"
|
||||
default n
|
||||
help
|
||||
The PROJECT_NAME variable from the build system will not affect the firmware image.
|
||||
This value will not be contained in the esp_app_desc structure.
|
||||
|
||||
config APP_RETRIEVE_LEN_ELF_SHA
|
||||
int "The length of APP ELF SHA is stored in RAM(chars)"
|
||||
default 16
|
||||
range 8 64
|
||||
help
|
||||
At startup, the app will read this many hex characters from the embedded APP ELF SHA-256 hash value
|
||||
and store it in static RAM. This ensures the app ELF SHA-256 value is always available
|
||||
if it needs to be printed by the panic handler code.
|
||||
Changing this value will change the size of a static buffer, in bytes.
|
||||
|
||||
endmenu # "Application manager"
|
||||
@@ -1,54 +1,60 @@
|
||||
# Generate partition binary
|
||||
#
|
||||
.PHONY: blank_ota_data erase_otadata read_otadata
|
||||
.PHONY: dump_otadata erase_ota blank_ota_data
|
||||
|
||||
OTATOOL_PY := $(PYTHON) $(COMPONENT_PATH)/otatool.py
|
||||
PARTTOOL_PY := $(PYTHON) $(IDF_PATH)/components/partition_table/parttool.py
|
||||
|
||||
# Generate blank partition file
|
||||
GEN_EMPTY_PART := $(PYTHON) $(COMPONENT_PATH)/gen_empty_partition.py
|
||||
BLANK_OTA_DATA_FILE = $(BUILD_DIR_BASE)/ota_data_initial.bin
|
||||
|
||||
# Copy PARTITION_TABLE_CSV_PATH definition here from $IDF_PATH/components/partition_table/Makefile.projbuild
|
||||
# to avoid undefined variables warning for PARTITION_TABLE_CSV_PATH
|
||||
ifndef PARTITION_TABLE_CSV_PATH
|
||||
PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(IDF_PATH)/components/partition_table))
|
||||
PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(call dequote,$(CONFIG_PARTITION_TABLE_FILENAME))))
|
||||
endif
|
||||
PARTITION_TABLE_LEN := 0xC00
|
||||
OTADATA_LEN := 0x2000
|
||||
|
||||
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies
|
||||
$(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
|
||||
$(PYTHON) $(IDF_PATH)/components/partition_table/gen_empty_partition.py $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE); \
|
||||
fi; )
|
||||
$(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
|
||||
echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) )
|
||||
PARTITION_TABLE_ONCHIP_BIN_PATH := $(call dequote,$(abspath $(BUILD_DIR_BASE)))
|
||||
PARTITION_TABLE_ONCHIP_BIN_NAME := "onchip_partition.bin"
|
||||
OTADATA_ONCHIP_BIN_NAME := "onchip_otadata.bin"
|
||||
|
||||
blank_ota_data: $(BLANK_OTA_DATA_FILE)
|
||||
PARTITION_TABLE_ONCHIP_BIN := $(PARTITION_TABLE_ONCHIP_BIN_PATH)/$(call dequote,$(PARTITION_TABLE_ONCHIP_BIN_NAME))
|
||||
OTADATA_ONCHIP_BIN := $(PARTITION_TABLE_ONCHIP_BIN_PATH)/$(call dequote,$(OTADATA_ONCHIP_BIN_NAME))
|
||||
|
||||
PARTITION_TABLE_GET_BIN_CMD = $(ESPTOOLPY_SERIAL) read_flash $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_LEN) $(PARTITION_TABLE_ONCHIP_BIN)
|
||||
OTADATA_GET_BIN_CMD = $(ESPTOOLPY_SERIAL) read_flash $(OTADATA_OFFSET) $(OTADATA_LEN) $(OTADATA_ONCHIP_BIN)
|
||||
|
||||
GEN_OTADATA = $(IDF_PATH)/components/app_update/dump_otadata.py
|
||||
ERASE_OTADATA_CMD = $(ESPTOOLPY_SERIAL) erase_region $(OTADATA_OFFSET) $(OTADATA_LEN)
|
||||
|
||||
# If there is no otadata partition, both OTA_DATA_OFFSET and BLANK_OTA_DATA_FILE
|
||||
# expand to empty values.
|
||||
ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE)
|
||||
|
||||
ESPTOOL_ARGS := --esptool-args port=$(CONFIG_ESPTOOLPY_PORT) baud=$(CONFIG_ESPTOOLPY_BAUD) before=$(CONFIG_ESPTOOLPY_BEFORE) after=$(CONFIG_ESPTOOLPY_AFTER)
|
||||
$(PARTITION_TABLE_ONCHIP_BIN):
|
||||
$(PARTITION_TABLE_GET_BIN_CMD)
|
||||
|
||||
erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
|
||||
--partition-table-offset $(PARTITION_TABLE_OFFSET) \
|
||||
erase_otadata
|
||||
onchip_otadata_get_info: $(PARTITION_TABLE_ONCHIP_BIN)
|
||||
$(eval OTADATA_OFFSET:=$(shell $(GET_PART_INFO) --type data --subtype ota --offset $(PARTITION_TABLE_ONCHIP_BIN)))
|
||||
@echo $(if $(OTADATA_OFFSET), $(shell export OTADATA_OFFSET), $(shell rm -f $(PARTITION_TABLE_ONCHIP_BIN));$(error "ERROR: ESP32 does not have otadata partition."))
|
||||
|
||||
read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
|
||||
--partition-table-offset $(partition_table_offset) \
|
||||
read_otadata
|
||||
$(OTADATA_ONCHIP_BIN):
|
||||
$(OTADATA_GET_BIN_CMD)
|
||||
|
||||
dump_otadata: onchip_otadata_get_info $(OTADATA_ONCHIP_BIN) $(PARTITION_TABLE_ONCHIP_BIN)
|
||||
@echo "otadata retrieved. Contents:"
|
||||
@echo $(SEPARATOR)
|
||||
$(GEN_OTADATA) $(OTADATA_ONCHIP_BIN)
|
||||
@echo $(SEPARATOR)
|
||||
rm -f $(PARTITION_TABLE_ONCHIP_BIN)
|
||||
rm -f $(OTADATA_ONCHIP_BIN)
|
||||
|
||||
$(BLANK_OTA_DATA_FILE): partition_table_get_info
|
||||
$(GEN_EMPTY_PART) --size $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE)
|
||||
$(eval BLANK_OTA_DATA_FILE = $(shell if [ $(OTA_DATA_SIZE) != 0 ]; then echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) )
|
||||
|
||||
blank_ota_data: $(BLANK_OTA_DATA_FILE)
|
||||
|
||||
erase_ota: partition_table_get_info | check_python_dependencies
|
||||
@echo $(if $(OTA_DATA_OFFSET), "Erase ota_data [addr=$(OTA_DATA_OFFSET) size=$(OTA_DATA_SIZE)] ...", $(error "ERROR: Partition table does not have ota_data partition."))
|
||||
$(ESPTOOLPY_SERIAL) erase_region $(OTA_DATA_OFFSET) $(OTA_DATA_SIZE)
|
||||
|
||||
all: blank_ota_data
|
||||
flash: blank_ota_data
|
||||
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
encrypted-flash: blank_ota_data
|
||||
endif
|
||||
|
||||
TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt
|
||||
export TMP_DEFINES
|
||||
|
||||
clean:
|
||||
rm -f $(BLANK_OTA_DATA_FILE)
|
||||
rm -f $(TMP_DEFINES)
|
||||
|
||||
@@ -3,54 +3,3 @@
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
# esp_app_desc structure is added as an undefined symbol because otherwise the
|
||||
# linker will ignore this structure as it has no other files depending on it.
|
||||
COMPONENT_ADD_LDFLAGS += -u esp_app_desc
|
||||
|
||||
ifndef IS_BOOTLOADER_BUILD
|
||||
GET_PROJECT_VER ?=
|
||||
ifeq ("${PROJECT_VER}", "")
|
||||
ifeq ("$(wildcard ${PROJECT_PATH}/version.txt)","")
|
||||
|
||||
GET_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty 2> /dev/null)
|
||||
ifeq ("${GET_PROJECT_VER}", "")
|
||||
GET_PROJECT_VER := "1"
|
||||
$(info Project is not inside a git repository, will not use 'git describe' to determine PROJECT_VER.)
|
||||
endif
|
||||
|
||||
else
|
||||
# read from version.txt
|
||||
GET_PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt)
|
||||
endif
|
||||
endif
|
||||
# If ``PROJECT_VER`` variable set in project Makefile file, its value will be used.
|
||||
# Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``.
|
||||
# Else, if the project is located inside a Git repository, the output of git describe will be used.
|
||||
# Otherwise, ``PROJECT_VER`` will be "1".
|
||||
|
||||
ifeq ("${PROJECT_VER}", "")
|
||||
PROJECT_VER:= $(GET_PROJECT_VER)
|
||||
else
|
||||
PROJECT_VER:= $(PROJECT_VER)
|
||||
endif
|
||||
|
||||
# cut PROJECT_VER and PROJECT_NAME to required 32 characters.
|
||||
PROJECT_VER_CUT := $(shell echo "$(PROJECT_VER)" | cut -c 1-31)
|
||||
PROJECT_NAME_CUT := $(shell echo "$(PROJECT_NAME)" | cut -c 1-31)
|
||||
|
||||
$(info App "$(PROJECT_NAME_CUT)" version: $(PROJECT_VER_CUT))
|
||||
|
||||
NEW_DEFINES:= "$(PROJECT_VER_CUT) $(PROJECT_NAME_CUT) $(IDF_VER)"
|
||||
ifeq ("$(wildcard ${TMP_DEFINES})","")
|
||||
OLD_DEFINES:= ""
|
||||
else
|
||||
OLD_DEFINES:= "$(shell cat $(TMP_DEFINES))"
|
||||
endif
|
||||
|
||||
# If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc.
|
||||
ifneq (${NEW_DEFINES}, ${OLD_DEFINES})
|
||||
$(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;)
|
||||
endif
|
||||
|
||||
esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\""$(PROJECT_VER_CUT)"\" -D PROJECT_NAME=\""$(PROJECT_NAME_CUT)"\"
|
||||
endif
|
||||
|
||||
88
components/app_update/dump_otadata.py
Executable file
88
components/app_update/dump_otadata.py
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# gen_otadata prints info about the otadata partition.
|
||||
#
|
||||
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
#
|
||||
# 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.
|
||||
from __future__ import print_function, division
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import hashlib
|
||||
import binascii
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
quiet = False
|
||||
|
||||
def status(msg):
|
||||
""" Print status message to stderr """
|
||||
if not quiet:
|
||||
critical(msg)
|
||||
|
||||
def critical(msg):
|
||||
""" Print critical message to stderr """
|
||||
if not quiet:
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
|
||||
def little_endian(buff, offset):
|
||||
data = buff[offset:offset+4]
|
||||
data.reverse()
|
||||
data = ''.join(data)
|
||||
return data
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
parser = argparse.ArgumentParser(description='Prints otadata partition in human readable form.')
|
||||
|
||||
parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true')
|
||||
|
||||
search_type = parser.add_mutually_exclusive_group()
|
||||
|
||||
parser.add_argument('input', help='Path to binary file containing otadata partition to parse.',
|
||||
type=argparse.FileType('rb'))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
quiet = args.quiet
|
||||
|
||||
input = args.input.read()
|
||||
|
||||
hex_input_0 = binascii.hexlify(input)
|
||||
hex_input_0 = map(''.join, zip(*[iter(hex_input_0)]*2))
|
||||
hex_input_1 = binascii.hexlify(input[4096:])
|
||||
hex_input_1 = map(''.join, zip(*[iter(hex_input_1)]*2))
|
||||
|
||||
print("\t%11s\t%8s |\t%8s\t%8s" %("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
|
||||
print("Firmware: 0x%s \t 0x%s |\t0x%s \t 0x%s" % (little_endian(hex_input_0, 0), little_endian(hex_input_0, 28), \
|
||||
little_endian(hex_input_1, 0), little_endian(hex_input_1, 28)))
|
||||
class InputError(RuntimeError):
|
||||
def __init__(self, e):
|
||||
super(InputError, self).__init__(e)
|
||||
|
||||
class ValidationError(InputError):
|
||||
def __init__(self, partition, message):
|
||||
super(ValidationError, self).__init__(
|
||||
"Partition %s invalid: %s" % (partition.name, message))
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
r = main()
|
||||
sys.exit(r)
|
||||
except InputError as e:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
@@ -1,107 +0,0 @@
|
||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 <assert.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_attr.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// Application version info
|
||||
const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
|
||||
.magic_word = ESP_APP_DESC_MAGIC_WORD,
|
||||
#ifdef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
|
||||
.version = "",
|
||||
#else
|
||||
.version = PROJECT_VER,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
.project_name = "",
|
||||
#else
|
||||
.project_name = PROJECT_NAME,
|
||||
#endif
|
||||
.idf_ver = IDF_VER,
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
|
||||
.secure_version = CONFIG_BOOTLOADER_APP_SECURE_VERSION,
|
||||
#else
|
||||
.secure_version = 0,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||
.time = __TIME__,
|
||||
.date = __DATE__,
|
||||
#else
|
||||
.time = "",
|
||||
.date = "",
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
|
||||
_Static_assert(sizeof(PROJECT_VER) <= sizeof(esp_app_desc.version), "PROJECT_VER is longer than version field in structure");
|
||||
#endif
|
||||
_Static_assert(sizeof(IDF_VER) <= sizeof(esp_app_desc.idf_ver), "IDF_VER is longer than idf_ver field in structure");
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
_Static_assert(sizeof(PROJECT_NAME) <= sizeof(esp_app_desc.project_name), "PROJECT_NAME is longer than project_name field in structure");
|
||||
#endif
|
||||
|
||||
const esp_app_desc_t *esp_ota_get_app_description(void)
|
||||
{
|
||||
return &esp_app_desc;
|
||||
}
|
||||
|
||||
/* The following two functions may be called from the panic handler
|
||||
* or core dump, hence IRAM_ATTR.
|
||||
*/
|
||||
|
||||
static inline char IRAM_ATTR to_hex_digit(unsigned val)
|
||||
{
|
||||
return (val < 10) ? ('0' + val) : ('a' + val - 10);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void)
|
||||
{
|
||||
esp_ota_get_app_elf_sha256(NULL, 0);
|
||||
}
|
||||
|
||||
/* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled.
|
||||
* But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and
|
||||
* can lead to a complete lock-up of the CPU.
|
||||
* For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256()
|
||||
* and keep it in the static s_app_elf_sha256 value.
|
||||
*/
|
||||
int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size)
|
||||
{
|
||||
static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2];
|
||||
static bool first_call = true;
|
||||
if (first_call) {
|
||||
first_call = false;
|
||||
const uint8_t* src = esp_app_desc.app_elf_sha256;
|
||||
for (size_t i = 0; i < sizeof(s_app_elf_sha256); ++i) {
|
||||
s_app_elf_sha256[i] = src[i];
|
||||
}
|
||||
}
|
||||
if (dst == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t n = MIN((size - 1) / 2, sizeof(s_app_elf_sha256));
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
dst[2*i] = to_hex_digit(s_app_elf_sha256[i] >> 4);
|
||||
dst[2*i + 1] = to_hex_digit(s_app_elf_sha256[i] & 0xf);
|
||||
}
|
||||
dst[2*n] = 0;
|
||||
return 2*n + 1;
|
||||
}
|
||||
@@ -32,16 +32,14 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_ota_ops.h"
|
||||
#include "sys/queue.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "rom/queue.h"
|
||||
#include "rom/crc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "sys/param.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
|
||||
#define OTA_MAX(a,b) ((a) >= (b) ? (a) : (b))
|
||||
#define OTA_MIN(a,b) ((a) <= (b) ? (a) : (b))
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
|
||||
typedef struct ota_ops_entry_ {
|
||||
@@ -54,10 +52,19 @@ typedef struct ota_ops_entry_ {
|
||||
LIST_ENTRY(ota_ops_entry_) entries;
|
||||
} ota_ops_entry_t;
|
||||
|
||||
/* OTA selection structure (two copies in the OTA data partition.)
|
||||
Size of 32 bytes is friendly to flash encryption */
|
||||
typedef struct {
|
||||
uint32_t ota_seq;
|
||||
uint8_t seq_label[24];
|
||||
uint32_t crc; /* CRC32 of ota_seq field only */
|
||||
} ota_select;
|
||||
|
||||
static LIST_HEAD(ota_ops_entries_head, ota_ops_entry_) s_ota_ops_entries_head =
|
||||
LIST_HEAD_INITIALIZER(s_ota_ops_entries_head);
|
||||
|
||||
static uint32_t s_ota_ops_last_handle = 0;
|
||||
static ota_select s_ota_select[2];
|
||||
|
||||
const static char *TAG = "esp_ota_ops";
|
||||
|
||||
@@ -70,56 +77,6 @@ static bool is_ota_partition(const esp_partition_t *p)
|
||||
&& p->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MAX);
|
||||
}
|
||||
|
||||
// Read otadata partition and fill array from two otadata structures.
|
||||
// Also return pointer to otadata info partition.
|
||||
static const esp_partition_t *read_otadata(esp_ota_select_entry_t *two_otadata)
|
||||
{
|
||||
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
|
||||
if (otadata_partition == NULL) {
|
||||
ESP_LOGE(TAG, "not found otadata");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spi_flash_mmap_handle_t ota_data_map;
|
||||
const void *result = NULL;
|
||||
esp_err_t err = esp_partition_mmap(otadata_partition, 0, otadata_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "mmap otadata filed. Err=0x%8x", err);
|
||||
return NULL;
|
||||
} else {
|
||||
memcpy(&two_otadata[0], result, sizeof(esp_ota_select_entry_t));
|
||||
memcpy(&two_otadata[1], result + SPI_FLASH_SEC_SIZE, sizeof(esp_ota_select_entry_t));
|
||||
spi_flash_munmap(ota_data_map);
|
||||
}
|
||||
return otadata_partition;
|
||||
}
|
||||
|
||||
static esp_err_t image_validate(const esp_partition_t *partition, esp_image_load_mode_t load_mode)
|
||||
{
|
||||
esp_image_metadata_t data;
|
||||
const esp_partition_pos_t part_pos = {
|
||||
.offset = partition->address,
|
||||
.size = partition->size,
|
||||
};
|
||||
|
||||
if (esp_image_verify(load_mode, &part_pos, &data) != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_ota_img_states_t set_new_state_otadata(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
ESP_LOGD(TAG, "Monitoring the first boot of the app is enabled.");
|
||||
return ESP_OTA_IMG_NEW;
|
||||
#else
|
||||
return ESP_OTA_IMG_UNDEFINED;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
|
||||
{
|
||||
ota_ops_entry_t *new_entry;
|
||||
@@ -138,27 +95,15 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
if (partition == running_partition) {
|
||||
if (partition == esp_ota_get_running_partition()) {
|
||||
return ESP_ERR_OTA_PARTITION_CONFLICT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
esp_ota_img_states_t ota_state_running_part;
|
||||
if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
|
||||
if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||
ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
|
||||
return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
@@ -211,7 +156,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
|
||||
/* check if we have partially written data from earlier */
|
||||
if (it->partial_bytes != 0) {
|
||||
copy_len = MIN(16 - it->partial_bytes, size);
|
||||
copy_len = OTA_MIN(16 - it->partial_bytes, size);
|
||||
memcpy(it->partial_data + it->partial_bytes, data_bytes, copy_len);
|
||||
it->partial_bytes += copy_len;
|
||||
if (it->partial_bytes != 16) {
|
||||
@@ -301,19 +246,31 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
|
||||
static uint32_t ota_select_crc(const ota_select *s)
|
||||
{
|
||||
if (two_otadata == NULL || sec_id > 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return crc32_le(UINT32_MAX, (uint8_t *)&s->ota_seq, 4);
|
||||
}
|
||||
|
||||
two_otadata[sec_id].ota_seq = seq;
|
||||
two_otadata[sec_id].crc = bootloader_common_ota_select_crc(&two_otadata[sec_id]);
|
||||
esp_err_t ret = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
static bool ota_select_valid(const ota_select *s)
|
||||
{
|
||||
return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
|
||||
}
|
||||
|
||||
static esp_err_t rewrite_ota_seq(uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
if (sec_id == 0 || sec_id == 1) {
|
||||
s_ota_select[sec_id].ota_seq = seq;
|
||||
s_ota_select[sec_id].crc = ota_select_crc(&s_ota_select[sec_id]);
|
||||
ret = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
} else {
|
||||
return esp_partition_write(ota_data_partition, SPI_FLASH_SEC_SIZE * sec_id, &s_ota_select[sec_id].ota_seq, sizeof(ota_select));
|
||||
}
|
||||
} else {
|
||||
return esp_partition_write(ota_data_partition, SPI_FLASH_SEC_SIZE * sec_id, &two_otadata[sec_id], sizeof(esp_ota_select_entry_t));
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,88 +286,119 @@ static uint8_t get_ota_partition_count(void)
|
||||
|
||||
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
const esp_partition_t *otadata_partition = read_otadata(otadata);
|
||||
if (otadata_partition == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
esp_err_t ret;
|
||||
const esp_partition_t *find_partition = NULL;
|
||||
uint16_t ota_app_count = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t seq;
|
||||
spi_flash_mmap_handle_t ota_data_map;
|
||||
const void *result = NULL;
|
||||
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
//esp32_idf use two sector for store information about which partition is running
|
||||
//it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
|
||||
//named data in first sector as otadata[0], second sector data as otadata[1]
|
||||
//e.g.
|
||||
//if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
//if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
//for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
|
||||
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
//we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
//if A=(B - C)%D
|
||||
//then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
//seq will add (x + n*1 + 1 - seq)%n
|
||||
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
if (active_otadata != -1) {
|
||||
uint32_t seq = otadata[active_otadata].ota_seq;
|
||||
uint32_t i = 0;
|
||||
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
if (find_partition != NULL) {
|
||||
ota_app_count = get_ota_partition_count();
|
||||
//esp32_idf use two sector for store information about which partition is running
|
||||
//it defined the two sector as ota data partition,two structure ota_select is saved in the two sector
|
||||
//named data in first sector as s_ota_select[0], second sector data as s_ota_select[1]
|
||||
//e.g.
|
||||
//if s_ota_select[0].ota_seq == s_ota_select[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
//if s_ota_select[0].ota_seq != 0 and s_ota_select[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
//for example, if s_ota_select[0].ota_seq = 4, s_ota_select[1].ota_seq = 5, and there are 8 ota application,
|
||||
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
//we should add s_ota_select[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
//if A=(B - C)%D
|
||||
//then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
//seq will add (x + n*1 + 1 - seq)%n
|
||||
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
int next_otadata = (~active_otadata)&1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, next_otadata, otadata_partition);
|
||||
|
||||
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
|
||||
if (ret != ESP_OK) {
|
||||
result = NULL;
|
||||
return ret;
|
||||
} else {
|
||||
memcpy(&s_ota_select[0], result, sizeof(ota_select));
|
||||
memcpy(&s_ota_select[1], result + SPI_FLASH_SEC_SIZE, sizeof(ota_select));
|
||||
spi_flash_munmap(ota_data_map);
|
||||
}
|
||||
|
||||
if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
|
||||
seq = OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq);
|
||||
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (s_ota_select[0].ota_seq >= s_ota_select[1].ota_seq) {
|
||||
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
|
||||
} else {
|
||||
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
|
||||
}
|
||||
|
||||
} else if (ota_select_valid(&s_ota_select[0])) {
|
||||
while (s_ota_select[0].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
}
|
||||
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
|
||||
|
||||
} else if (ota_select_valid(&s_ota_select[1])) {
|
||||
while (s_ota_select[1].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
}
|
||||
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
|
||||
|
||||
} else {
|
||||
/* Both OTA slots are invalid, probably because unformatted... */
|
||||
return rewrite_ota_seq(SUB_TYPE_ID(subtype) + 1, 0, find_partition);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Both OTA slots are invalid, probably because unformatted... */
|
||||
int next_otadata = 0;
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, SUB_TYPE_ID(subtype) + 1, next_otadata, otadata_partition);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
|
||||
{
|
||||
const esp_partition_t *find_partition = NULL;
|
||||
if (partition == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (image_validate(partition, ESP_IMAGE_VERIFY) != ESP_OK) {
|
||||
esp_image_metadata_t data;
|
||||
const esp_partition_pos_t part_pos = {
|
||||
.offset = partition->address,
|
||||
.size = partition->size,
|
||||
};
|
||||
if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE
|
||||
esp_err_t ret = esp_secure_boot_verify_signature(partition->address, data.image_len);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
#endif
|
||||
// if set boot partition to factory bin ,just format ota info partition
|
||||
if (partition->type == ESP_PARTITION_TYPE_APP) {
|
||||
if (partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
|
||||
const esp_partition_t *find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
if (find_partition != NULL) {
|
||||
return esp_partition_erase_range(find_partition, 0, find_partition->size);
|
||||
} else {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
} else {
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
esp_app_desc_t partition_app_desc;
|
||||
esp_err_t err = esp_ota_get_partition_description(partition, &partition_app_desc);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
// try to find this partition in flash,if not find it ,return error
|
||||
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
if (find_partition != NULL) {
|
||||
return esp_rewrite_ota_data(partition->subtype);
|
||||
} else {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (esp_efuse_check_secure_version(partition_app_desc.secure_version) == false) {
|
||||
ESP_LOGE(TAG, "This a new partition can not be booted due to a secure version is lower than stored in efuse. Partition will be erased.");
|
||||
esp_err_t err = esp_partition_erase_range(partition, 0, partition->size);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
return ESP_ERR_OTA_SMALL_SEC_VER;
|
||||
}
|
||||
#endif
|
||||
return esp_rewrite_ota_data(partition->subtype);
|
||||
}
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -447,30 +435,58 @@ static const esp_partition_t *find_default_boot_partition(void)
|
||||
|
||||
const esp_partition_t *esp_ota_get_boot_partition(void)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
const esp_partition_t *otadata_partition = read_otadata(otadata);
|
||||
if (otadata_partition == NULL) {
|
||||
esp_err_t ret;
|
||||
const esp_partition_t *find_partition = NULL;
|
||||
spi_flash_mmap_handle_t ota_data_map;
|
||||
const void *result = NULL;
|
||||
uint16_t ota_app_count = 0;
|
||||
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
|
||||
if (find_partition == NULL) {
|
||||
ESP_LOGE(TAG, "not found ota data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
|
||||
if (ret != ESP_OK) {
|
||||
spi_flash_munmap(ota_data_map);
|
||||
ESP_LOGE(TAG, "mmap ota data filed");
|
||||
return NULL;
|
||||
} else {
|
||||
memcpy(&s_ota_select[0], result, sizeof(ota_select));
|
||||
memcpy(&s_ota_select[1], result + 0x1000, sizeof(ota_select));
|
||||
spi_flash_munmap(ota_data_map);
|
||||
}
|
||||
ota_app_count = get_ota_partition_count();
|
||||
|
||||
ESP_LOGD(TAG, "found ota app max = %d", ota_app_count);
|
||||
|
||||
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
ota_app_count == 0) {
|
||||
ESP_LOGD(TAG, "finding factory app...");
|
||||
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
|
||||
ESP_LOGD(TAG, "finding factory app......");
|
||||
return find_default_boot_partition();
|
||||
} else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
|
||||
ESP_LOGD(TAG, "finding ota_%d app......", \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count));
|
||||
|
||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count), NULL);
|
||||
} else if (ota_select_valid(&s_ota_select[0])) {
|
||||
ESP_LOGD(TAG, "finding ota_%d app......", \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count);
|
||||
|
||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count, NULL);
|
||||
|
||||
} else if (ota_select_valid(&s_ota_select[1])) {
|
||||
ESP_LOGD(TAG, "finding ota_%d app......", \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count);
|
||||
|
||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
|
||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count, NULL);
|
||||
|
||||
} else {
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
if (active_otadata != -1) {
|
||||
int ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count; // Actual OTA partition selection
|
||||
ESP_LOGD(TAG, "finding ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
|
||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
|
||||
return find_default_boot_partition();
|
||||
}
|
||||
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
|
||||
return find_default_boot_partition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,265 +575,3 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *
|
||||
return default_ota;
|
||||
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc)
|
||||
{
|
||||
if (partition == NULL || app_desc == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if(partition->type != ESP_PARTITION_TYPE_APP) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_read(partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), app_desc, sizeof(esp_app_desc_t));
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
static esp_err_t esp_ota_set_anti_rollback(void) {
|
||||
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
|
||||
return esp_efuse_update_secure_version(app_desc->secure_version);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Checks applications on the slots which can be booted in case of rollback.
|
||||
// Returns true if the slots have at least one app (except the running app).
|
||||
bool esp_ota_check_rollback_is_possible(void)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
if (read_otadata(otadata) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
if (ota_app_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid_otadata[2];
|
||||
valid_otadata[0] = bootloader_common_ota_select_valid(&otadata[0]);
|
||||
valid_otadata[1] = bootloader_common_ota_select_valid(&otadata[1]);
|
||||
|
||||
int active_ota = bootloader_common_select_otadata(otadata, valid_otadata, true);
|
||||
if (active_ota == -1) {
|
||||
return false;
|
||||
}
|
||||
int last_active_ota = (~active_ota)&1;
|
||||
|
||||
const esp_partition_t *partition = NULL;
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
if (valid_otadata[last_active_ota] == false) {
|
||||
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
||||
if (partition != NULL) {
|
||||
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (valid_otadata[last_active_ota] == true) {
|
||||
int slot = (otadata[last_active_ota].ota_seq - 1) % ota_app_count;
|
||||
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + slot, NULL);
|
||||
if (partition != NULL) {
|
||||
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
esp_app_desc_t app_desc;
|
||||
if (esp_ota_get_partition_description(partition, &app_desc) == ESP_OK &&
|
||||
esp_efuse_check_secure_version(app_desc.secure_version) == true) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// if valid == false - will done rollback with reboot. After reboot will boot previous OTA[x] or Factory partition.
|
||||
// if valid == true - it confirm that current OTA[x] is workable. Reboot will not happen.
|
||||
static esp_err_t esp_ota_current_ota_is_workable(bool valid)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
const esp_partition_t *otadata_partition = read_otadata(otadata);
|
||||
if (otadata_partition == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
if (active_otadata != -1 && get_ota_partition_count() != 0) {
|
||||
if (valid == true && otadata[active_otadata].ota_state != ESP_OTA_IMG_VALID) {
|
||||
otadata[active_otadata].ota_state = ESP_OTA_IMG_VALID;
|
||||
ESP_LOGD(TAG, "OTA[current] partition is marked as VALID");
|
||||
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
if (err == ESP_OK) {
|
||||
return esp_ota_set_anti_rollback();
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
} else if (valid == false) {
|
||||
if (esp_ota_check_rollback_is_possible() == false) {
|
||||
ESP_LOGE(TAG, "Rollback is not possible, do not have any suitable apps in slots");
|
||||
return ESP_ERR_OTA_ROLLBACK_FAILED;
|
||||
}
|
||||
ESP_LOGD(TAG, "OTA[current] partition is marked as INVALID");
|
||||
otadata[active_otadata].ota_state = ESP_OTA_IMG_INVALID;
|
||||
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
ESP_LOGI(TAG, "Rollback to previously worked partition. Restart.");
|
||||
esp_restart();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Running firmware is factory");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(true);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(false);
|
||||
}
|
||||
|
||||
static bool check_invalid_otadata (const esp_ota_select_entry_t *s) {
|
||||
return s->ota_seq != UINT32_MAX &&
|
||||
s->crc == bootloader_common_ota_select_crc(s) &&
|
||||
(s->ota_state == ESP_OTA_IMG_INVALID ||
|
||||
s->ota_state == ESP_OTA_IMG_ABORTED);
|
||||
}
|
||||
|
||||
static int get_last_invalid_otadata(const esp_ota_select_entry_t *two_otadata)
|
||||
{
|
||||
|
||||
bool invalid_otadata[2];
|
||||
invalid_otadata[0] = check_invalid_otadata(&two_otadata[0]);
|
||||
invalid_otadata[1] = check_invalid_otadata(&two_otadata[1]);
|
||||
int num_invalid_otadata = bootloader_common_select_otadata(two_otadata, invalid_otadata, false);
|
||||
ESP_LOGD(TAG, "Invalid otadata[%d]", num_invalid_otadata);
|
||||
return num_invalid_otadata;
|
||||
}
|
||||
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition()
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
if (read_otadata(otadata) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int invalid_otadata = get_last_invalid_otadata(otadata);
|
||||
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
if (invalid_otadata != -1 && ota_app_count != 0) {
|
||||
int ota_slot = (otadata[invalid_otadata].ota_seq - 1) % ota_app_count;
|
||||
ESP_LOGD(TAG, "Find invalid ota_%d app", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
|
||||
|
||||
const esp_partition_t* invalid_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
|
||||
if (invalid_partition != NULL) {
|
||||
if (image_validate(invalid_partition, ESP_IMAGE_VERIFY_SILENT) != ESP_OK) {
|
||||
ESP_LOGD(TAG, "Last invalid partition has corrupted app");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return invalid_partition;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state)
|
||||
{
|
||||
if (partition == NULL || ota_state == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!is_ota_partition(partition)) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
if (read_otadata(otadata) == NULL || ota_app_count == 0) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int req_ota_slot = partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_MIN;
|
||||
bool not_found = true;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
int ota_slot = (otadata[i].ota_seq - 1) % ota_app_count;
|
||||
if (ota_slot == req_ota_slot && otadata[i].crc == bootloader_common_ota_select_crc(&otadata[i])) {
|
||||
*ota_state = otadata[i].ota_state;
|
||||
not_found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (not_found) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_erase_last_boot_app_partition(void)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
const esp_partition_t* ota_data_partition = read_otadata(otadata);
|
||||
if (ota_data_partition == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
int ota_app_count = get_ota_partition_count();
|
||||
if (active_otadata == -1 || ota_app_count == 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int inactive_otadata = (~active_otadata)&1;
|
||||
if (otadata[inactive_otadata].ota_seq == UINT32_MAX || otadata[inactive_otadata].crc != bootloader_common_ota_select_crc(&otadata[inactive_otadata])) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int ota_slot = (otadata[inactive_otadata].ota_seq - 1) % ota_app_count; // Actual OTA partition selection
|
||||
ESP_LOGD(TAG, "finding last_boot_app_partition ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
|
||||
|
||||
const esp_partition_t* last_boot_app_partition_from_otadata = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
|
||||
if (last_boot_app_partition_from_otadata == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
if (running_partition == NULL || last_boot_app_partition_from_otadata == running_partition) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_erase_range(last_boot_app_partition_from_otadata, 0, last_boot_app_partition_from_otadata->size);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int sec_id = inactive_otadata;
|
||||
err = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
32
components/partition_table/gen_empty_partition.py → components/app_update/gen_empty_partition.py
Normal file → Executable file
32
components/partition_table/gen_empty_partition.py → components/app_update/gen_empty_partition.py
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# generates an empty binary file
|
||||
#
|
||||
#
|
||||
# This tool generates an empty binary file of the required size.
|
||||
#
|
||||
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
@@ -20,12 +20,27 @@
|
||||
from __future__ import print_function, division
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import hashlib
|
||||
import binascii
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
quiet = False
|
||||
|
||||
def status(msg):
|
||||
""" Print status message to stderr """
|
||||
if not quiet:
|
||||
critical(msg)
|
||||
|
||||
def critical(msg):
|
||||
""" Print critical message to stderr """
|
||||
if not quiet:
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
|
||||
def generate_blanked_file(size, output_path):
|
||||
output = b"\xFF" * size
|
||||
@@ -36,25 +51,28 @@ def generate_blanked_file(size, output_path):
|
||||
with stdout_binary if output_path == '-' else open(output_path, 'wb') as f:
|
||||
f.write(output)
|
||||
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
parser = argparse.ArgumentParser(description='Generates an empty binary file of the required size.')
|
||||
parser.add_argument('size', help='Size of generated the file', type=str)
|
||||
|
||||
parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true')
|
||||
|
||||
parser.add_argument('--size', help='Size of generated the file', type=str, required=True)
|
||||
|
||||
parser.add_argument('output', help='Path for binary file.', nargs='?', default='-')
|
||||
args = parser.parse_args()
|
||||
|
||||
quiet = args.quiet
|
||||
|
||||
size = int(args.size, 0)
|
||||
if size > 0:
|
||||
if size > 0 :
|
||||
generate_blanked_file(size, args.output)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
class InputError(RuntimeError):
|
||||
def __init__(self, e):
|
||||
super(InputError, self).__init__(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
r = main()
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@@ -34,10 +32,6 @@ extern "C"
|
||||
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< Error if request was to write or erase the current running partition */
|
||||
#define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< Error if OTA data partition contains invalid content */
|
||||
#define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< Error if OTA app image is invalid */
|
||||
#define ESP_ERR_OTA_SMALL_SEC_VER (ESP_ERR_OTA_BASE + 0x04) /*!< Error if the firmware has a secure version less than the running firmware. */
|
||||
#define ESP_ERR_OTA_ROLLBACK_FAILED (ESP_ERR_OTA_BASE + 0x05) /*!< Error if flash does not have valid firmware in passive partition and hence rollback is not possible */
|
||||
#define ESP_ERR_OTA_ROLLBACK_INVALID_STATE (ESP_ERR_OTA_BASE + 0x06) /*!< Error if current active firmware is still marked in pending validation state (ESP_OTA_IMG_PENDING_VERIFY), essentially first boot of firmware image post upgrade and hence firmware upgrade is not possible */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for an application OTA update
|
||||
@@ -47,24 +41,6 @@ extern "C"
|
||||
*/
|
||||
typedef uint32_t esp_ota_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Return esp_app_desc structure. This structure includes app version.
|
||||
*
|
||||
* Return description for running app.
|
||||
* @return Pointer to esp_app_desc structure.
|
||||
*/
|
||||
const esp_app_desc_t *esp_ota_get_app_description(void);
|
||||
|
||||
/**
|
||||
* @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated.
|
||||
* If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator,
|
||||
* the largest possible number of bytes will be written followed by a null.
|
||||
* @param dst Destination buffer
|
||||
* @param size Size of the buffer
|
||||
* @return Number of bytes written to dst (including null terminator)
|
||||
*/
|
||||
int esp_ota_get_app_elf_sha256(char* dst, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Commence an OTA update writing to the specified partition.
|
||||
|
||||
@@ -76,10 +52,6 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size);
|
||||
* On success, this function allocates memory that remains in use
|
||||
* until esp_ota_end() is called with the returned handle.
|
||||
*
|
||||
* Note: If the rollback option is enabled and the running application has the ESP_OTA_IMG_PENDING_VERIFY state then
|
||||
* it will lead to the ESP_ERR_OTA_ROLLBACK_INVALID_STATE error. Confirm the running app before to run download a new app,
|
||||
* use esp_ota_mark_app_valid_cancel_rollback() function for it (this should be done as early as possible when you first download a new application).
|
||||
*
|
||||
* @param partition Pointer to info for partition which will receive the OTA update. Required.
|
||||
* @param image_size Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.
|
||||
* @param out_handle On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
|
||||
@@ -93,7 +65,6 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size);
|
||||
* - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
|
||||
* - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size.
|
||||
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
|
||||
* - ESP_ERR_OTA_ROLLBACK_INVALID_STATE: If the running app has not confirmed state. Before performing an update, the application must be valid.
|
||||
*/
|
||||
esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle);
|
||||
|
||||
@@ -199,83 +170,6 @@ const esp_partition_t* esp_ota_get_running_partition(void);
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition Pointer to app partition. (only app partition)
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
* @return
|
||||
* - ESP_OK Successful.
|
||||
* - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect.
|
||||
* - ESP_ERR_NOT_SUPPORTED Partition is not application.
|
||||
* - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size.
|
||||
* - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition.
|
||||
* - or one of error codes from lower-level flash driver.
|
||||
*/
|
||||
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief This function is called to indicate that the running app is working well.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: if successful.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback();
|
||||
|
||||
/**
|
||||
* @brief This function is called to roll back to the previously workable app with reboot.
|
||||
*
|
||||
* If rollback is successful then device will reset else API will return with error code.
|
||||
* Checks applications on a flash drive that can be booted in case of rollback.
|
||||
* If the flash does not have at least one app (except the running app) then rollback is not possible.
|
||||
* @return
|
||||
* - ESP_FAIL: if not successful.
|
||||
* - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
|
||||
/**
|
||||
* @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
|
||||
*
|
||||
* @return partition.
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition();
|
||||
|
||||
/**
|
||||
* @brief Returns state for given partition.
|
||||
*
|
||||
* @param[in] partition Pointer to partition.
|
||||
* @param[out] ota_state state of partition (if this partition has a record in otadata).
|
||||
* @return
|
||||
* - ESP_OK: Successful.
|
||||
* - ESP_ERR_INVALID_ARG: partition or ota_state arguments were NULL.
|
||||
* - ESP_ERR_NOT_SUPPORTED: partition is not ota.
|
||||
* - ESP_ERR_NOT_FOUND: Partition table does not have otadata or state was not found for given partition.
|
||||
*/
|
||||
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state);
|
||||
|
||||
/**
|
||||
* @brief Erase previous boot app partition and corresponding otadata select for this partition.
|
||||
*
|
||||
* When current app is marked to as valid then you can erase previous app partition.
|
||||
* @return
|
||||
* - ESP_OK: Successful, otherwise ESP_ERR.
|
||||
*/
|
||||
esp_err_t esp_ota_erase_last_boot_app_partition(void);
|
||||
|
||||
/**
|
||||
* @brief Checks applications on the slots which can be booted in case of rollback.
|
||||
*
|
||||
* These applications should be valid (marked in otadata as not UNDEFINED, INVALID or ABORTED and crc is good) and be able booted,
|
||||
* and secure_version of app >= secure_version of efuse (if anti-rollback is enabled).
|
||||
*
|
||||
* @return
|
||||
* - True: Returns true if the slots have at least one app (except the running app).
|
||||
* - False: The rollback is not possible.
|
||||
*/
|
||||
bool esp_ota_check_rollback_is_possible(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# otatool is used to perform ota-level operations - flashing ota partition
|
||||
# erasing ota partition and switching ota partition
|
||||
#
|
||||
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
#
|
||||
# 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.
|
||||
from __future__ import print_function, division
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import binascii
|
||||
import tempfile
|
||||
import collections
|
||||
import struct
|
||||
|
||||
try:
|
||||
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
|
||||
except ImportError:
|
||||
COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components"))
|
||||
PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, "partition_table")
|
||||
|
||||
sys.path.append(PARTTOOL_DIR)
|
||||
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
|
||||
|
||||
__version__ = '2.0'
|
||||
|
||||
SPI_FLASH_SEC_SIZE = 0x2000
|
||||
|
||||
quiet = False
|
||||
|
||||
|
||||
def status(msg):
|
||||
if not quiet:
|
||||
print(msg)
|
||||
|
||||
|
||||
class OtatoolTarget():
|
||||
|
||||
OTADATA_PARTITION = PartitionType("data", "ota")
|
||||
|
||||
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
|
||||
spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[],
|
||||
esptool_read_args=[], esptool_erase_args=[]):
|
||||
self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args,
|
||||
esptool_write_args, esptool_read_args, esptool_erase_args)
|
||||
self.spi_flash_sec_size = spi_flash_sec_size
|
||||
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
temp_file.close()
|
||||
try:
|
||||
self.target.read_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
|
||||
with open(temp_file.name, "rb") as f:
|
||||
self.otadata = f.read()
|
||||
except Exception:
|
||||
self.otadata = None
|
||||
finally:
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
def _check_otadata_partition(self):
|
||||
if not self.otadata:
|
||||
raise Exception("No otadata partition found")
|
||||
|
||||
def erase_otadata(self):
|
||||
self._check_otadata_partition()
|
||||
self.target.erase_partition(OtatoolTarget.OTADATA_PARTITION)
|
||||
|
||||
def _get_otadata_info(self):
|
||||
info = []
|
||||
|
||||
otadata_info = collections.namedtuple("otadata_info", "seq crc")
|
||||
|
||||
for i in range(2):
|
||||
start = i * (self.spi_flash_sec_size >> 1)
|
||||
|
||||
seq = bytearray(self.otadata[start:start + 4])
|
||||
crc = bytearray(self.otadata[start + 28:start + 32])
|
||||
|
||||
seq = struct.unpack('>I', seq)
|
||||
crc = struct.unpack('>I', crc)
|
||||
|
||||
info.append(otadata_info(seq[0], crc[0]))
|
||||
|
||||
return info
|
||||
|
||||
def _get_partition_id_from_ota_id(self, ota_id):
|
||||
if isinstance(ota_id, int):
|
||||
return PartitionType("app", "ota_" + str(ota_id))
|
||||
else:
|
||||
return PartitionName(ota_id)
|
||||
|
||||
def switch_ota_partition(self, ota_id):
|
||||
self._check_otadata_partition()
|
||||
|
||||
sys.path.append(PARTTOOL_DIR)
|
||||
import gen_esp32part as gen
|
||||
|
||||
def is_otadata_info_valid(status):
|
||||
seq = status.seq % (1 << 32)
|
||||
crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32))
|
||||
return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc
|
||||
|
||||
partition_table = self.target.partition_table
|
||||
|
||||
ota_partitions = list()
|
||||
|
||||
for i in range(gen.NUM_PARTITION_SUBTYPE_APP_OTA):
|
||||
ota_partition = filter(lambda p: p.subtype == (gen.MIN_PARTITION_SUBTYPE_APP_OTA + i), partition_table)
|
||||
|
||||
try:
|
||||
ota_partitions.append(list(ota_partition)[0])
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype)
|
||||
|
||||
if not ota_partitions:
|
||||
raise Exception("No ota app partitions found")
|
||||
|
||||
# Look for the app partition to switch to
|
||||
ota_partition_next = None
|
||||
|
||||
try:
|
||||
if isinstance(ota_id, int):
|
||||
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions)
|
||||
else:
|
||||
ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions)
|
||||
|
||||
ota_partition_next = list(ota_partition_next)[0]
|
||||
except IndexError:
|
||||
raise Exception("Partition to switch to not found")
|
||||
|
||||
otadata_info = self._get_otadata_info()
|
||||
|
||||
# Find the copy to base the computation for ota sequence number on
|
||||
otadata_compute_base = -1
|
||||
|
||||
# Both are valid, take the max as computation base
|
||||
if is_otadata_info_valid(otadata_info[0]) and is_otadata_info_valid(otadata_info[1]):
|
||||
if otadata_info[0].seq >= otadata_info[1].seq:
|
||||
otadata_compute_base = 0
|
||||
else:
|
||||
otadata_compute_base = 1
|
||||
# Only one copy is valid, use that
|
||||
elif is_otadata_info_valid(otadata_info[0]):
|
||||
otadata_compute_base = 0
|
||||
elif is_otadata_info_valid(otadata_info[1]):
|
||||
otadata_compute_base = 1
|
||||
# Both are invalid (could be initial state - all 0xFF's)
|
||||
else:
|
||||
pass
|
||||
|
||||
ota_seq_next = 0
|
||||
ota_partitions_num = len(ota_partitions)
|
||||
|
||||
target_seq = (ota_partition_next.subtype & 0x0F) + 1
|
||||
|
||||
# Find the next ota sequence number
|
||||
if otadata_compute_base == 0 or otadata_compute_base == 1:
|
||||
base_seq = otadata_info[otadata_compute_base].seq % (1 << 32)
|
||||
|
||||
i = 0
|
||||
while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num:
|
||||
i += 1
|
||||
|
||||
ota_seq_next = target_seq % ota_partitions_num + i * ota_partitions_num
|
||||
else:
|
||||
ota_seq_next = target_seq
|
||||
|
||||
# Create binary data from computed values
|
||||
ota_seq_next = struct.pack("I", ota_seq_next)
|
||||
ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32)
|
||||
ota_seq_crc_next = struct.pack("I", ota_seq_crc_next)
|
||||
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
temp_file.close()
|
||||
|
||||
try:
|
||||
with open(temp_file.name, "wb") as otadata_next_file:
|
||||
start = (1 if otadata_compute_base == 0 else 0) * (self.spi_flash_sec_size >> 1)
|
||||
|
||||
otadata_next_file.write(self.otadata)
|
||||
|
||||
otadata_next_file.seek(start)
|
||||
otadata_next_file.write(ota_seq_next)
|
||||
|
||||
otadata_next_file.seek(start + 28)
|
||||
otadata_next_file.write(ota_seq_crc_next)
|
||||
|
||||
otadata_next_file.flush()
|
||||
|
||||
self.target.write_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
|
||||
finally:
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
def read_ota_partition(self, ota_id, output):
|
||||
self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output)
|
||||
|
||||
def write_ota_partition(self, ota_id, input):
|
||||
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input)
|
||||
|
||||
def erase_ota_partition(self, ota_id):
|
||||
self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id))
|
||||
|
||||
|
||||
def _read_otadata(target):
|
||||
target._check_otadata_partition()
|
||||
|
||||
otadata_info = target._get_otadata_info()
|
||||
|
||||
print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
|
||||
print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
|
||||
otadata_info[1].seq, otadata_info[1].crc))
|
||||
|
||||
|
||||
def _erase_otadata(target):
|
||||
target.erase_otadata()
|
||||
status("Erased ota_data partition contents")
|
||||
|
||||
|
||||
def _switch_ota_partition(target, ota_id):
|
||||
target.switch_ota_partition(ota_id)
|
||||
|
||||
|
||||
def _read_ota_partition(target, ota_id, output):
|
||||
target.read_ota_partition(ota_id, output)
|
||||
status("Read ota partition contents to file {}".format(output))
|
||||
|
||||
|
||||
def _write_ota_partition(target, ota_id, input):
|
||||
target.write_ota_partition(ota_id, input)
|
||||
status("Written contents of file {} to ota partition".format(input))
|
||||
|
||||
|
||||
def _erase_ota_partition(target, ota_id):
|
||||
target.erase_ota_partition(ota_id)
|
||||
status("Erased contents of ota partition")
|
||||
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
|
||||
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")
|
||||
|
||||
parser.add_argument("--quiet", "-q", help="suppress stderr messages", action="store_true")
|
||||
parser.add_argument("--esptool-args", help="additional main arguments for esptool", nargs="+")
|
||||
parser.add_argument("--esptool-write-args", help="additional subcommand arguments for esptool write_flash", nargs="+")
|
||||
parser.add_argument("--esptool-read-args", help="additional subcommand arguments for esptool read_flash", nargs="+")
|
||||
parser.add_argument("--esptool-erase-args", help="additional subcommand arguments for esptool erase_region", nargs="+")
|
||||
|
||||
# There are two possible sources for the partition table: a device attached to the host
|
||||
# or a partition table CSV/binary file. These sources are mutually exclusive.
|
||||
parser.add_argument("--port", "-p", help="port where the device to read the partition table from is attached")
|
||||
|
||||
parser.add_argument("--baud", "-b", help="baudrate to use", type=int)
|
||||
|
||||
parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", type=str)
|
||||
|
||||
parser.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from; \
|
||||
overrides device attached to specified port as the partition table source when defined")
|
||||
|
||||
subparsers = parser.add_subparsers(dest="operation", help="run otatool -h for additional help")
|
||||
|
||||
spi_flash_sec_size = argparse.ArgumentParser(add_help=False)
|
||||
spi_flash_sec_size.add_argument("--spi-flash-sec-size", help="value of SPI_FLASH_SEC_SIZE macro", type=str)
|
||||
|
||||
# Specify the supported operations
|
||||
subparsers.add_parser("read_otadata", help="read otadata partition", parents=[spi_flash_sec_size])
|
||||
subparsers.add_parser("erase_otadata", help="erase otadata partition")
|
||||
|
||||
slot_or_name_parser = argparse.ArgumentParser(add_help=False)
|
||||
slot_or_name_parser_args = slot_or_name_parser.add_mutually_exclusive_group()
|
||||
slot_or_name_parser_args.add_argument("--slot", help="slot number of the ota partition", type=int)
|
||||
slot_or_name_parser_args.add_argument("--name", help="name of the ota partition")
|
||||
|
||||
subparsers.add_parser("switch_ota_partition", help="switch otadata partition", parents=[slot_or_name_parser, spi_flash_sec_size])
|
||||
|
||||
read_ota_partition_subparser = subparsers.add_parser("read_ota_partition", help="read contents of an ota partition", parents=[slot_or_name_parser])
|
||||
read_ota_partition_subparser.add_argument("--output", help="file to write the contents of the ota partition to")
|
||||
|
||||
write_ota_partition_subparser = subparsers.add_parser("write_ota_partition", help="write contents to an ota partition", parents=[slot_or_name_parser])
|
||||
write_ota_partition_subparser.add_argument("--input", help="file whose contents to write to the ota partition")
|
||||
|
||||
subparsers.add_parser("erase_ota_partition", help="erase contents of an ota partition", parents=[slot_or_name_parser])
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
quiet = args.quiet
|
||||
|
||||
# No operation specified, display help and exit
|
||||
if args.operation is None:
|
||||
if not quiet:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
target_args = {}
|
||||
|
||||
if args.port:
|
||||
target_args["port"] = args.port
|
||||
|
||||
if args.partition_table_file:
|
||||
target_args["partition_table_file"] = args.partition_table_file
|
||||
|
||||
if args.partition_table_offset:
|
||||
target_args["partition_table_offset"] = int(args.partition_table_offset, 0)
|
||||
|
||||
try:
|
||||
if args.spi_flash_sec_size:
|
||||
target_args["spi_flash_sec_size"] = int(args.spi_flash_sec_size, 0)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if args.esptool_args:
|
||||
target_args["esptool_args"] = args.esptool_args
|
||||
|
||||
if args.esptool_write_args:
|
||||
target_args["esptool_write_args"] = args.esptool_write_args
|
||||
|
||||
if args.esptool_read_args:
|
||||
target_args["esptool_read_args"] = args.esptool_read_args
|
||||
|
||||
if args.esptool_erase_args:
|
||||
target_args["esptool_erase_args"] = args.esptool_erase_args
|
||||
|
||||
if args.baud:
|
||||
target_args["baud"] = args.baud
|
||||
|
||||
target = OtatoolTarget(**target_args)
|
||||
|
||||
# Create the operation table and execute the operation
|
||||
common_args = {'target':target}
|
||||
|
||||
ota_id = []
|
||||
|
||||
try:
|
||||
if args.name is not None:
|
||||
ota_id = ["name"]
|
||||
else:
|
||||
if args.slot is not None:
|
||||
ota_id = ["slot"]
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
otatool_ops = {
|
||||
'read_otadata':(_read_otadata, []),
|
||||
'erase_otadata':(_erase_otadata, []),
|
||||
'switch_ota_partition':(_switch_ota_partition, ota_id),
|
||||
'read_ota_partition':(_read_ota_partition, ["output"] + ota_id),
|
||||
'write_ota_partition':(_write_ota_partition, ["input"] + ota_id),
|
||||
'erase_ota_partition':(_erase_ota_partition, ota_id)
|
||||
}
|
||||
|
||||
(op, op_args) = otatool_ops[args.operation]
|
||||
|
||||
for op_arg in op_args:
|
||||
common_args.update({op_arg:vars(args)[op_arg]})
|
||||
|
||||
try:
|
||||
common_args['ota_id'] = common_args.pop('name')
|
||||
except KeyError:
|
||||
try:
|
||||
common_args['ota_id'] = common_args.pop('slot')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if quiet:
|
||||
# If exceptions occur, suppress and exit quietly
|
||||
try:
|
||||
op(**common_args)
|
||||
except Exception:
|
||||
sys.exit(2)
|
||||
else:
|
||||
op(**common_args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
8
components/app_update/project_include.cmake
Normal file
8
components/app_update/project_include.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
# Set empty otadata partition file for flashing, if OTA data partition in
|
||||
# partition table
|
||||
# (NB: because of component dependency, we know partition_table
|
||||
# project_include.cmake has already been included.)
|
||||
if(${OTADATA_PARTITION_OFFSET})
|
||||
set(BLANK_OTADATA_FILE "ota_data_initial.bin")
|
||||
endif()
|
||||
@@ -1,3 +1,6 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash)
|
||||
set(COMPONENT_SRCDIRS ".")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
set(COMPONENT_REQUIRES unity app_update bootloader_support nvs_flash)
|
||||
|
||||
register_component()
|
||||
@@ -1,50 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "esp_ota_ops.h"
|
||||
#include "unity.h"
|
||||
|
||||
TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]")
|
||||
{
|
||||
const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA;
|
||||
char dst[sha256_hex_len + 2];
|
||||
const char fill = 0xcc;
|
||||
int res;
|
||||
size_t len;
|
||||
|
||||
char ref_sha256[sha256_hex_len + 1];
|
||||
const esp_app_desc_t* desc = esp_ota_get_app_description();
|
||||
for (int i = 0; i < sizeof(ref_sha256) / 2; ++i) {
|
||||
snprintf(ref_sha256 + 2*i, 3, "%02x", desc->app_elf_sha256[i]);
|
||||
}
|
||||
ref_sha256[sha256_hex_len] = 0;
|
||||
|
||||
printf("Ref: %s\n", ref_sha256);
|
||||
|
||||
memset(dst, fill, sizeof(dst));
|
||||
len = sizeof(dst);
|
||||
res = esp_ota_get_app_elf_sha256(dst, len);
|
||||
printf("%d: %s (%d)\n", len, dst, res);
|
||||
TEST_ASSERT_EQUAL(sha256_hex_len + 1, res);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
|
||||
TEST_ASSERT_EQUAL_HEX(0, dst[sha256_hex_len]);
|
||||
TEST_ASSERT_EQUAL_HEX(fill, dst[sha256_hex_len + 1]);
|
||||
|
||||
memset(dst, fill, sizeof(dst));
|
||||
len = 9;
|
||||
res = esp_ota_get_app_elf_sha256(dst, len);
|
||||
printf("%d: %s (%d)\n", len, dst, res);
|
||||
TEST_ASSERT_EQUAL(9, res);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
|
||||
TEST_ASSERT_EQUAL_HEX(0, dst[8]);
|
||||
TEST_ASSERT_EQUAL_HEX(fill, dst[9]);
|
||||
|
||||
memset(dst, fill, sizeof(dst));
|
||||
len = 8;
|
||||
res = esp_ota_get_app_elf_sha256(dst, len);
|
||||
printf("%d: %s (%d)\n", len, dst, res);
|
||||
// should output even number of characters plus '\0'
|
||||
TEST_ASSERT_EQUAL(7, res);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
|
||||
TEST_ASSERT_EQUAL_HEX(0, dst[6]);
|
||||
TEST_ASSERT_EQUAL_HEX(fill, dst[7]);
|
||||
TEST_ASSERT_EQUAL_HEX(fill, dst[8]);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <unity.h>
|
||||
#include <test_utils.h>
|
||||
#include <esp_ota_ops.h>
|
||||
#include "bootloader_common.h"
|
||||
|
||||
|
||||
/* These OTA tests currently don't assume an OTA partition exists
|
||||
on the device, so they're a bit limited
|
||||
@@ -84,26 +84,3 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
|
||||
TEST_ASSERT_EQUAL_PTR(ota_0, p);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_ota_get_partition_description ", "[ota]")
|
||||
{
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
TEST_ASSERT_NOT_NULL(running);
|
||||
esp_app_desc_t app_desc1, app_desc2;
|
||||
TEST_ESP_OK(esp_ota_get_partition_description(running, &app_desc1));
|
||||
const esp_partition_pos_t running_pos = {
|
||||
.offset = running->address,
|
||||
.size = running->size
|
||||
};
|
||||
TEST_ESP_OK(bootloader_common_get_partition_description(&running_pos, &app_desc2));
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE((uint8_t *)&app_desc1, (uint8_t *)&app_desc2, sizeof(app_desc1), "must be the same");
|
||||
|
||||
const esp_partition_t *not_app = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
TEST_ASSERT_NOT_NULL(not_app);
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_partition_description(not_app, &app_desc1));
|
||||
const esp_partition_pos_t not_app_pos = {
|
||||
.offset = not_app->address,
|
||||
.size = not_app->size
|
||||
};
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, bootloader_common_get_partition_description(¬_app_pos, &app_desc1));
|
||||
}
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -29,8 +28,8 @@
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
RTC_DATA_ATTR static int boot_count = 0;
|
||||
static const char *TAG = "ota_test";
|
||||
@@ -238,12 +237,6 @@ static void reset_output_pin(uint32_t num_pin)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mark_app_valid(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
#endif
|
||||
}
|
||||
|
||||
/* @brief Checks and prepares the partition so that the factory app is launched after that.
|
||||
*/
|
||||
@@ -269,18 +262,15 @@ static void test_flow1(void)
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 5:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
mark_app_valid();
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
erase_ota_data();
|
||||
break;
|
||||
@@ -296,7 +286,7 @@ static void test_flow1(void)
|
||||
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
|
||||
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
|
||||
|
||||
static void test_flow2(void)
|
||||
{
|
||||
@@ -312,7 +302,6 @@ static void test_flow2(void)
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
corrupt_ota_data(CORR_CRC_1_SECTOR_OTA_DATA);
|
||||
reboot_as_deep_sleep();
|
||||
@@ -333,7 +322,7 @@ static void test_flow2(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
|
||||
|
||||
static void test_flow3(void)
|
||||
{
|
||||
@@ -349,13 +338,11 @@ static void test_flow3(void)
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
corrupt_ota_data(CORR_CRC_2_SECTOR_OTA_DATA);
|
||||
reboot_as_deep_sleep();
|
||||
@@ -377,7 +364,7 @@ static void test_flow3(void)
|
||||
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
|
||||
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
|
||||
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
||||
#define STORAGE_NAMESPACE "update_ota"
|
||||
@@ -387,7 +374,7 @@ static void test_flow4(void)
|
||||
boot_count++;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
nvs_handle_t handle = 0;
|
||||
nvs_handle handle = 0;
|
||||
int boot_count_nvs = 0;
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
@@ -407,7 +394,7 @@ static void test_flow4(void)
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
|
||||
TEST_ESP_OK(nvs_get_i32(handle, "boot_count", &boot_count_nvs));
|
||||
@@ -489,245 +476,3 @@ static void test_flow5(void)
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
#endif
|
||||
|
||||
static const esp_partition_t* app_update(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_NULL(update_partition);
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
copy_app_partition(update_handle, cur_app);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
|
||||
return update_partition;
|
||||
}
|
||||
|
||||
|
||||
static void test_rollback1(void)
|
||||
{
|
||||
boot_count++;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
esp_ota_img_states_t ota_state = 0x5555AAAA;
|
||||
const esp_partition_t* update_partition = NULL;
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
update_partition = app_update();
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
|
||||
#endif
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
|
||||
#endif
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
|
||||
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
|
||||
break;
|
||||
default:
|
||||
erase_ota_data();
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_rollback1_1(void)
|
||||
{
|
||||
boot_count = 5;
|
||||
esp_ota_img_states_t ota_state = 0x5555AAAA;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
|
||||
const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
|
||||
const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_NULL(invalid_partition);
|
||||
TEST_ASSERT_NOT_NULL(next_update_partition);
|
||||
TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
|
||||
|
||||
erase_ota_data();
|
||||
}
|
||||
|
||||
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
|
||||
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
|
||||
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
|
||||
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
|
||||
|
||||
static void test_rollback2(void)
|
||||
{
|
||||
boot_count++;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
esp_ota_img_states_t ota_state = 0x5555AAAA;
|
||||
const esp_partition_t* update_partition = NULL;
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
update_partition = app_update();
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
|
||||
#endif
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
|
||||
#endif
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
|
||||
update_partition = app_update();
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
|
||||
#endif
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
|
||||
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
|
||||
reboot_as_deep_sleep();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
erase_ota_data();
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_rollback2_1(void)
|
||||
{
|
||||
boot_count = 5;
|
||||
esp_ota_img_states_t ota_state = 0x5555AAAA;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
|
||||
const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, invalid_partition->subtype);
|
||||
const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_NULL(invalid_partition);
|
||||
TEST_ASSERT_NOT_NULL(next_update_partition);
|
||||
TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
|
||||
#else
|
||||
TEST_ASSERT_EQUAL(ESP_OTA_IMG_ABORTED, ota_state);
|
||||
#endif
|
||||
erase_ota_data();
|
||||
}
|
||||
|
||||
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
|
||||
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
|
||||
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
|
||||
|
||||
static void test_erase_last_app_flow(void)
|
||||
{
|
||||
boot_count++;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
app_update();
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
app_update();
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
TEST_ESP_OK(esp_ota_erase_last_boot_app_partition());
|
||||
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
default:
|
||||
erase_ota_data();
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_erase_last_app_rollback(void)
|
||||
{
|
||||
boot_count = 5;
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
ESP_LOGI(TAG, "erase_last_app");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
TEST_ESP_ERR(ESP_FAIL, esp_ota_erase_last_boot_app_partition());
|
||||
erase_ota_data();
|
||||
}
|
||||
|
||||
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
|
||||
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
|
||||
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
idf_component_register(SRCS "asio/asio/src/asio.cpp"
|
||||
INCLUDE_DIRS "asio/asio/include" "port/include"
|
||||
REQUIRES lwip)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS asio/asio/include port/include)
|
||||
set(COMPONENT_SRCS "asio/asio/src/asio.cpp")
|
||||
|
||||
set(COMPONENT_REQUIRES lwip)
|
||||
|
||||
register_component()
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
// Enabling exceptions only when they are enabled in menuconfig
|
||||
//
|
||||
# include <sdkconfig.h>
|
||||
# ifndef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
# ifndef CONFIG_CXX_EXCEPTIONS
|
||||
# define ASIO_NO_EXCEPTIONS
|
||||
# endif // CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
# endif // CONFIG_CXX_EXCEPTIONS
|
||||
|
||||
//
|
||||
// LWIP compatifility inet and address macros/functions
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//
|
||||
// This exception stub is enabled only if exceptions are disabled in menuconfig
|
||||
//
|
||||
#if !defined(CONFIG_COMPILER_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS)
|
||||
#if !defined(CONFIG_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS)
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -34,6 +34,6 @@ void throw_exception(const Exception& e)
|
||||
abort();
|
||||
}
|
||||
}}
|
||||
#endif // CONFIG_COMPILER_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS)
|
||||
#endif // CONFIG_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS)
|
||||
|
||||
#endif // _ESP_EXCEPTION_H_
|
||||
|
||||
30
components/aws_iot/CMakeLists.txt
Normal file
30
components/aws_iot/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
if(CONFIG_AWS_IOT_SDK)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "include aws-iot-device-sdk-embedded-C/include")
|
||||
set(aws_sdk_dir aws-iot-device-sdk-embedded-C/src)
|
||||
set(COMPONENT_SRCS "${aws_sdk_dir}/aws_iot_jobs_interface.c"
|
||||
"${aws_sdk_dir}/aws_iot_jobs_json.c"
|
||||
"${aws_sdk_dir}/aws_iot_jobs_topics.c"
|
||||
"${aws_sdk_dir}/aws_iot_jobs_types.c"
|
||||
"${aws_sdk_dir}/aws_iot_json_utils.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_common_internal.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_connect.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_publish.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_subscribe.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_unsubscribe.c"
|
||||
"${aws_sdk_dir}/aws_iot_mqtt_client_yield.c"
|
||||
"${aws_sdk_dir}/aws_iot_shadow.c"
|
||||
"${aws_sdk_dir}/aws_iot_shadow_actions.c"
|
||||
"${aws_sdk_dir}/aws_iot_shadow_json.c"
|
||||
"${aws_sdk_dir}/aws_iot_shadow_records.c"
|
||||
"port/network_mbedtls_wrapper.c"
|
||||
"port/threads_freertos.c"
|
||||
"port/timer.c")
|
||||
else()
|
||||
message(STATUS "Building empty aws_iot component due to configuration")
|
||||
endif()
|
||||
|
||||
set(COMPONENT_REQUIRES "mbedtls")
|
||||
set(COMPONENT_PRIV_REQUIRES "jsmn")
|
||||
|
||||
register_component()
|
||||
159
components/aws_iot/Kconfig
Normal file
159
components/aws_iot/Kconfig
Normal file
@@ -0,0 +1,159 @@
|
||||
menuconfig AWS_IOT_SDK
|
||||
bool "Amazon Web Services IoT Platform"
|
||||
help
|
||||
Select this option to enable support for the AWS IoT platform,
|
||||
via the esp-idf component for the AWS IoT Device C SDK.
|
||||
|
||||
config AWS_IOT_MQTT_HOST
|
||||
string "AWS IoT Endpoint Hostname"
|
||||
depends on AWS_IOT_SDK
|
||||
default ""
|
||||
help
|
||||
Default endpoint host name to connect to AWS IoT MQTT/S gateway
|
||||
|
||||
This is the custom endpoint hostname and is specific to an AWS
|
||||
IoT account. You can find it by logging into your AWS IoT
|
||||
Console and clicking the Settings button. The endpoint hostname
|
||||
is shown under the "Custom Endpoint" heading on this page.
|
||||
|
||||
If you need per-device hostnames for different regions or
|
||||
accounts, you can override the default hostname in your app.
|
||||
|
||||
config AWS_IOT_MQTT_PORT
|
||||
int "AWS IoT MQTT Port"
|
||||
depends on AWS_IOT_SDK
|
||||
default 8883
|
||||
range 0 65535
|
||||
help
|
||||
Default port number to connect to AWS IoT MQTT/S gateway
|
||||
|
||||
If you need per-device port numbers for different regions, you can
|
||||
override the default port number in your app.
|
||||
|
||||
|
||||
config AWS_IOT_MQTT_TX_BUF_LEN
|
||||
int "MQTT TX Buffer Length"
|
||||
depends on AWS_IOT_SDK
|
||||
default 512
|
||||
range 32 65536
|
||||
help
|
||||
Maximum MQTT transmit buffer size. This is the maximum MQTT
|
||||
message length (including protocol overhead) which can be sent.
|
||||
|
||||
Sending longer messages will fail.
|
||||
|
||||
config AWS_IOT_MQTT_RX_BUF_LEN
|
||||
int "MQTT RX Buffer Length"
|
||||
depends on AWS_IOT_SDK
|
||||
default 512
|
||||
range 32 65536
|
||||
help
|
||||
Maximum MQTT receive buffer size. This is the maximum MQTT
|
||||
message length (including protocol overhead) which can be
|
||||
received.
|
||||
|
||||
Longer messages are dropped.
|
||||
|
||||
|
||||
|
||||
config AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS
|
||||
int "Maximum MQTT Topic Filters"
|
||||
depends on AWS_IOT_SDK
|
||||
default 5
|
||||
range 1 100
|
||||
help
|
||||
Maximum number of concurrent MQTT topic filters.
|
||||
|
||||
|
||||
config AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
|
||||
int "Auto reconnect initial interval (ms)"
|
||||
depends on AWS_IOT_SDK
|
||||
default 1000
|
||||
range 10 3600000
|
||||
help
|
||||
Initial delay before making first reconnect attempt, if the AWS IoT connection fails.
|
||||
Client will perform exponential backoff, starting from this value.
|
||||
|
||||
config AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
|
||||
int "Auto reconnect maximum interval (ms)"
|
||||
depends on AWS_IOT_SDK
|
||||
default 128000
|
||||
range 10 3600000
|
||||
help
|
||||
Maximum delay between reconnection attempts. If the exponentially increased delay
|
||||
interval reaches this value, the client will stop automatically attempting to reconnect.
|
||||
|
||||
menu "Thing Shadow"
|
||||
depends on AWS_IOT_SDK
|
||||
|
||||
config AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER
|
||||
bool "Override Shadow RX buffer size"
|
||||
depends on AWS_IOT_SDK
|
||||
default n
|
||||
help
|
||||
Allows setting a different Thing Shadow RX buffer
|
||||
size. This is the maximum size of a Thing Shadow
|
||||
message in bytes, plus one.
|
||||
|
||||
If not overridden, the default value is the MQTT RX Buffer length plus one. If overriden, do not set higher than the default value.
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER
|
||||
int "Maximum RX Buffer (bytes)"
|
||||
depends on AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER
|
||||
default 513
|
||||
range 32 65536
|
||||
help
|
||||
Allows setting a different Thing Shadow RX buffer size.
|
||||
This is the maximum size of a Thing Shadow message in bytes,
|
||||
plus one.
|
||||
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES
|
||||
int "Maximum unique client ID size (bytes)"
|
||||
depends on AWS_IOT_SDK
|
||||
default 80
|
||||
range 4 1000
|
||||
help
|
||||
Maximum size of the Unique Client Id.
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS
|
||||
int "Maximum simultaneous responses"
|
||||
depends on AWS_IOT_SDK
|
||||
default 10
|
||||
range 1 100
|
||||
help
|
||||
At any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES
|
||||
int "Maximum simultaneous Thing Name operations"
|
||||
depends on AWS_IOT_SDK
|
||||
default 10
|
||||
range 1 100
|
||||
help
|
||||
We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED
|
||||
int "Maximum expected JSON tokens"
|
||||
depends on AWS_IOT_SDK
|
||||
default 120
|
||||
help
|
||||
These are the max tokens that is expected to be in the Shadow JSON document. Includes the metadata which is published
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME
|
||||
int "Maximum topic length (not including Thing Name)"
|
||||
depends on AWS_IOT_SDK
|
||||
default 60
|
||||
range 10 1000
|
||||
help
|
||||
All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name
|
||||
|
||||
config AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME
|
||||
int "Maximum Thing Name length"
|
||||
depends on AWS_IOT_SDK
|
||||
default 20
|
||||
range 4 1000
|
||||
help
|
||||
Maximum length of a Thing Name.
|
||||
|
||||
endmenu # Thing Shadow
|
||||
|
||||
1
components/aws_iot/aws-iot-device-sdk-embedded-C
Submodule
1
components/aws_iot/aws-iot-device-sdk-embedded-C
Submodule
Submodule components/aws_iot/aws-iot-device-sdk-embedded-C added at 299183238f
20
components/aws_iot/component.mk
Normal file
20
components/aws_iot/component.mk
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
|
||||
ifdef CONFIG_AWS_IOT_SDK
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := include aws-iot-device-sdk-embedded-C/include
|
||||
|
||||
COMPONENT_SRCDIRS := aws-iot-device-sdk-embedded-C/src port
|
||||
|
||||
# Check the submodule is initialised
|
||||
COMPONENT_SUBMODULES := aws-iot-device-sdk-embedded-C
|
||||
|
||||
|
||||
else
|
||||
# Disable AWS IoT support
|
||||
COMPONENT_ADD_INCLUDEDIRS :=
|
||||
COMPONENT_ADD_LDFLAGS :=
|
||||
COMPONENT_SRCDIRS :=
|
||||
endif
|
||||
65
components/aws_iot/include/aws_iot_config.h
Normal file
65
components/aws_iot/include/aws_iot_config.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. 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.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file aws_iot_config.h
|
||||
* @brief AWS IoT specific configuration file
|
||||
*/
|
||||
|
||||
#ifndef _AWS_IOT_CONFIG_H_
|
||||
#define _AWS_IOT_CONFIG_H_
|
||||
|
||||
#include "aws_iot_log.h"
|
||||
|
||||
// This configuration macro needs to be available globally to enable threading
|
||||
#define _ENABLE_THREAD_SUPPORT_
|
||||
|
||||
// These values are defined in the menuconfig of the AWS IoT component.
|
||||
// However, you can override these constants from your own code.
|
||||
#define AWS_IOT_MQTT_HOST CONFIG_AWS_IOT_MQTT_HOST ///< Customer specific MQTT HOST. The same will be used for Thing Shadow
|
||||
#define AWS_IOT_MQTT_PORT CONFIG_AWS_IOT_MQTT_PORT ///< default port for MQTT/S
|
||||
|
||||
// These values are defaults and are used for ShadowConnectParametersDefault.
|
||||
// You should override them from your own code.
|
||||
#define AWS_IOT_MQTT_CLIENT_ID "ESP32" ///< MQTT client ID should be unique for every device
|
||||
#define AWS_IOT_MY_THING_NAME "ESP32" ///< Thing Name of the Shadow this device is associated with
|
||||
|
||||
// MQTT PubSub
|
||||
#define AWS_IOT_MQTT_TX_BUF_LEN CONFIG_AWS_IOT_MQTT_TX_BUF_LEN ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow
|
||||
#define AWS_IOT_MQTT_RX_BUF_LEN CONFIG_AWS_IOT_MQTT_RX_BUF_LEN ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped.
|
||||
#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow
|
||||
|
||||
// Thing Shadow specific configs
|
||||
#ifdef CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER
|
||||
#define SHADOW_MAX_SIZE_OF_RX_BUFFER CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER ///< Maximum size of the SHADOW buffer to store the received Shadow message, including NULL terminating byte
|
||||
#else
|
||||
#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN + 1)
|
||||
#endif
|
||||
|
||||
#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments"
|
||||
#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE (MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10) ///< This is size of the extra sequence number that will be appended to the Unique client Id
|
||||
#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE (MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20) ///< This is size of the the total clientToken key and value pair in the JSON
|
||||
#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested
|
||||
#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time
|
||||
#define MAX_JSON_TOKEN_EXPECTED CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published
|
||||
#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME ///< All shadow actions have to be published or subscribed to a topic which is of the formablogt $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name
|
||||
#define MAX_SIZE_OF_THING_NAME CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger
|
||||
#define MAX_SHADOW_TOPIC_LENGTH_BYTES (MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME) ///< This size includes the length of topic with Thing Name
|
||||
|
||||
// Auto Reconnect specific config
|
||||
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
|
||||
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
|
||||
|
||||
#endif /* _AWS_IOT_CONFIG_H_ */
|
||||
44
components/aws_iot/include/aws_iot_log.h
Normal file
44
components/aws_iot/include/aws_iot_log.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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
|
||||
|
||||
/* (these two headers aren't used here, but AWS IoT SDK code relies on them
|
||||
being included from here...) */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
/* This is a stub replacement for the aws_iot_log.h header in the AWS IoT SDK,
|
||||
which redirects their logging framework into the esp-idf logging framework.
|
||||
|
||||
The current (2.1.1) upstream AWS IoT SDK doesn't allow this as some of its
|
||||
headers include aws_iot_log.h, but our modified fork does.
|
||||
*/
|
||||
|
||||
// redefine the AWS IoT log functions to call into the IDF log layer
|
||||
#define IOT_DEBUG(format, ...) ESP_LOGD("aws_iot", format, ##__VA_ARGS__)
|
||||
#define IOT_INFO(format, ...) ESP_LOGI("aws_iot", format, ##__VA_ARGS__)
|
||||
#define IOT_WARN(format, ...) ESP_LOGW("aws_iot", format, ##__VA_ARGS__)
|
||||
#define IOT_ERROR(format, ...) ESP_LOGE("aws_iot", format, ##__VA_ARGS__)
|
||||
|
||||
/* Function tracing macros used in AWS IoT SDK,
|
||||
mapped to "verbose" level output
|
||||
*/
|
||||
#define FUNC_ENTRY ESP_LOGV("aws_iot", "FUNC_ENTRY: %s L#%d \n", __func__, __LINE__)
|
||||
#define FUNC_EXIT_RC(x) \
|
||||
do { \
|
||||
ESP_LOGV("aws_iot", "FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \
|
||||
return x; \
|
||||
} while(0)
|
||||
64
components/aws_iot/include/network_platform.h
Normal file
64
components/aws_iot/include/network_platform.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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 IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/certs.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/timing.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief TLS Connection Parameters
|
||||
*
|
||||
* Defines a type containing TLS specific parameters to be passed down to the
|
||||
* TLS networking layer to create a TLS secured socket.
|
||||
*/
|
||||
typedef struct _TLSDataParams {
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
uint32_t flags;
|
||||
mbedtls_x509_crt cacert;
|
||||
mbedtls_x509_crt clicert;
|
||||
mbedtls_pk_context pkey;
|
||||
mbedtls_net_context server_fd;
|
||||
}TLSDataParams;
|
||||
|
||||
#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
|
||||
45
components/aws_iot/include/threads_platform.h
Normal file
45
components/aws_iot/include/threads_platform.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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 "threads_interface.h"
|
||||
|
||||
#ifndef AWS_IOTSDK_THREADS_PLATFORM_H
|
||||
#define AWS_IOTSDK_THREADS_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
/**
|
||||
* @brief Mutex Type
|
||||
*
|
||||
* definition of the Mutex struct. Platform specific
|
||||
*
|
||||
*/
|
||||
struct _IoT_Mutex_t {
|
||||
SemaphoreHandle_t mutex;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AWS_IOTSDK_THREADS_PLATFORM_H */
|
||||
|
||||
|
||||
40
components/aws_iot/include/timer_platform.h
Normal file
40
components/aws_iot/include/timer_platform.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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 AWS_IOT_PLATFORM_H
|
||||
#define AWS_IOT_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "timer_interface.h"
|
||||
|
||||
/**
|
||||
* definition of the Timer struct. Platform specific
|
||||
*/
|
||||
struct Timer {
|
||||
uint32_t start_ticks;
|
||||
uint32_t timeout_ticks;
|
||||
uint32_t last_polled_ticks;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AWS_IOT_PLATFORM_H */
|
||||
417
components/aws_iot/port/network_mbedtls_wrapper.c
Normal file
417
components/aws_iot/port/network_mbedtls_wrapper.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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 <sys/param.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <timer_platform.h>
|
||||
#include <network_interface.h>
|
||||
|
||||
#include "aws_iot_config.h"
|
||||
#include "aws_iot_error.h"
|
||||
#include "network_interface.h"
|
||||
#include "network_platform.h"
|
||||
|
||||
#include "mbedtls/esp_debug.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
|
||||
static const char *TAG = "aws_iot";
|
||||
|
||||
/* This is the value used for ssl read timeout */
|
||||
#define IOT_SSL_READ_TIMEOUT 10
|
||||
|
||||
/*
|
||||
* This is a function to do further verification if needed on the cert received.
|
||||
*
|
||||
* Currently used to print debug-level information about each cert.
|
||||
*/
|
||||
static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
|
||||
char buf[256];
|
||||
((void) data);
|
||||
|
||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) {
|
||||
ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
ESP_LOGD(TAG, "%s", buf);
|
||||
|
||||
if((*flags) == 0) {
|
||||
ESP_LOGD(TAG, " This certificate has no flags");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Verify result:%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _iot_tls_set_connect_params(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation,
|
||||
const char *pDevicePrivateKeyLocation, const char *pDestinationURL,
|
||||
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
|
||||
pNetwork->tlsConnectParams.DestinationPort = destinationPort;
|
||||
pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL;
|
||||
pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation;
|
||||
pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation;
|
||||
pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation;
|
||||
pNetwork->tlsConnectParams.timeout_ms = timeout_ms;
|
||||
pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_init(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation,
|
||||
const char *pDevicePrivateKeyLocation, const char *pDestinationURL,
|
||||
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
|
||||
_iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation,
|
||||
pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag);
|
||||
|
||||
pNetwork->connect = iot_tls_connect;
|
||||
pNetwork->read = iot_tls_read;
|
||||
pNetwork->write = iot_tls_write;
|
||||
pNetwork->disconnect = iot_tls_disconnect;
|
||||
pNetwork->isConnected = iot_tls_is_connected;
|
||||
pNetwork->destroy = iot_tls_destroy;
|
||||
|
||||
pNetwork->tlsDataParams.flags = 0;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_is_connected(Network *pNetwork) {
|
||||
/* Use this to add implementation which can check for physical layer disconnect */
|
||||
return NETWORK_PHYSICAL_LAYER_CONNECTED;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
|
||||
int ret = SUCCESS;
|
||||
TLSDataParams *tlsDataParams = NULL;
|
||||
char portBuffer[6];
|
||||
char info_buf[256];
|
||||
|
||||
if(NULL == pNetwork) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if(NULL != params) {
|
||||
_iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
|
||||
params->pDevicePrivateKeyLocation, params->pDestinationURL,
|
||||
params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
|
||||
}
|
||||
|
||||
tlsDataParams = &(pNetwork->tlsDataParams);
|
||||
|
||||
mbedtls_net_init(&(tlsDataParams->server_fd));
|
||||
mbedtls_ssl_init(&(tlsDataParams->ssl));
|
||||
mbedtls_ssl_config_init(&(tlsDataParams->conf));
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_DEBUG
|
||||
mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4);
|
||||
#endif
|
||||
|
||||
mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
|
||||
mbedtls_x509_crt_init(&(tlsDataParams->cacert));
|
||||
mbedtls_x509_crt_init(&(tlsDataParams->clicert));
|
||||
mbedtls_pk_init(&(tlsDataParams->pkey));
|
||||
|
||||
ESP_LOGD(TAG, "Seeding the random number generator...");
|
||||
mbedtls_entropy_init(&(tlsDataParams->entropy));
|
||||
if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
|
||||
(const unsigned char *) TAG, strlen(TAG))) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret);
|
||||
return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
|
||||
}
|
||||
|
||||
/* Load root CA...
|
||||
|
||||
Certs/keys can be paths or they can be raw data. These use a
|
||||
very basic heuristic: if the cert starts with '/' then it's a
|
||||
path, if it's longer than this then it's raw cert data (PEM or DER,
|
||||
neither of which can start with a slash. */
|
||||
if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') {
|
||||
ESP_LOGD(TAG, "Loading CA root certificate from file ...");
|
||||
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Loading embedded CA root certificate ...");
|
||||
ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation,
|
||||
strlen(pNetwork->tlsConnectParams.pRootCALocation)+1);
|
||||
}
|
||||
|
||||
if(ret < 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret);
|
||||
return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
|
||||
}
|
||||
ESP_LOGD(TAG, "ok (%d skipped)", ret);
|
||||
|
||||
/* Load client certificate... */
|
||||
if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') {
|
||||
ESP_LOGD(TAG, "Loading client cert from file...");
|
||||
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert),
|
||||
pNetwork->tlsConnectParams.pDeviceCertLocation);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Loading embedded client certificate...");
|
||||
ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert),
|
||||
(const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation,
|
||||
strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1);
|
||||
}
|
||||
if(ret != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret);
|
||||
return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* Parse client private key... */
|
||||
if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') {
|
||||
ESP_LOGD(TAG, "Loading client private key from file...");
|
||||
ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey),
|
||||
pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
|
||||
"");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Loading embedded client private key...");
|
||||
ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey),
|
||||
(const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
|
||||
strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1,
|
||||
(const unsigned char *)"", 0);
|
||||
}
|
||||
if(ret != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret);
|
||||
return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
|
||||
}
|
||||
|
||||
/* Done parsing certs */
|
||||
ESP_LOGD(TAG, "ok");
|
||||
snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
|
||||
ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
|
||||
if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
|
||||
portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret);
|
||||
switch(ret) {
|
||||
case MBEDTLS_ERR_NET_SOCKET_FAILED:
|
||||
return NETWORK_ERR_NET_SOCKET_FAILED;
|
||||
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
|
||||
return NETWORK_ERR_NET_UNKNOWN_HOST;
|
||||
case MBEDTLS_ERR_NET_CONNECT_FAILED:
|
||||
default:
|
||||
return NETWORK_ERR_NET_CONNECT_FAILED;
|
||||
};
|
||||
}
|
||||
|
||||
ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
|
||||
if(ret != 0) {
|
||||
ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
} ESP_LOGD(TAG, "ok");
|
||||
|
||||
ESP_LOGD(TAG, "Setting up the SSL/TLS structure...");
|
||||
if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
|
||||
|
||||
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
|
||||
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
} else {
|
||||
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
}
|
||||
mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
|
||||
ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey));
|
||||
if(ret != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);
|
||||
|
||||
/* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */
|
||||
if (pNetwork->tlsConnectParams.DestinationPort == 443) {
|
||||
const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
|
||||
if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret);
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
|
||||
mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL,
|
||||
mbedtls_net_recv_timeout);
|
||||
ESP_LOGD(TAG, "ok");
|
||||
|
||||
ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
|
||||
ESP_LOGD(TAG, "Performing the SSL/TLS handshake...");
|
||||
while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
|
||||
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret);
|
||||
if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
ESP_LOGE(TAG, " Unable to verify the server's certificate. ");
|
||||
}
|
||||
return SSL_CONNECTION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)),
|
||||
mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
|
||||
if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
|
||||
ESP_LOGD(TAG, " [ Record expansion is %d ]", ret);
|
||||
} else {
|
||||
ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]");
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Verifying peer X.509 certificate...");
|
||||
|
||||
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
|
||||
if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
|
||||
ESP_LOGE(TAG, "failed");
|
||||
mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags);
|
||||
ESP_LOGE(TAG, "%s", info_buf);
|
||||
ret = SSL_CONNECTION_ERROR;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "ok");
|
||||
ret = SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, " Server Verification skipped");
|
||||
ret = SUCCESS;
|
||||
}
|
||||
|
||||
if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) {
|
||||
if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
|
||||
ESP_LOGD(TAG, "Peer certificate information:");
|
||||
mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
|
||||
ESP_LOGD(TAG, "%s", info_buf);
|
||||
}
|
||||
}
|
||||
|
||||
return (IoT_Error_t) ret;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) {
|
||||
size_t written_so_far;
|
||||
bool isErrorFlag = false;
|
||||
int frags, ret = 0;
|
||||
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
|
||||
|
||||
for(written_so_far = 0, frags = 0;
|
||||
written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) {
|
||||
while(!has_timer_expired(timer) &&
|
||||
(ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) {
|
||||
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret);
|
||||
/* All other negative return values indicate connection needs to be reset.
|
||||
* Will be caught in ping request so ignored here */
|
||||
isErrorFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isErrorFlag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*written_len = written_so_far;
|
||||
|
||||
if(isErrorFlag) {
|
||||
return NETWORK_SSL_WRITE_ERROR;
|
||||
} else if(has_timer_expired(timer) && written_so_far != len) {
|
||||
return NETWORK_SSL_WRITE_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) {
|
||||
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
|
||||
mbedtls_ssl_context *ssl = &(tlsDataParams->ssl);
|
||||
mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf);
|
||||
uint32_t read_timeout;
|
||||
size_t rxLen = 0;
|
||||
int ret;
|
||||
|
||||
read_timeout = ssl_conf->read_timeout;
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
/* Make sure we never block on read for longer than timer has left,
|
||||
but also that we don't block indefinitely (ie read_timeout > 0) */
|
||||
mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer))));
|
||||
|
||||
ret = mbedtls_ssl_read(ssl, pMsg, len);
|
||||
|
||||
/* Restore the old timeout */
|
||||
mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
rxLen += ret;
|
||||
pMsg += ret;
|
||||
len -= ret;
|
||||
} else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) {
|
||||
return NETWORK_SSL_READ_ERROR;
|
||||
}
|
||||
|
||||
// Evaluate timeout after the read to make sure read is done at least once
|
||||
if (has_timer_expired(timer)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
*read_len = rxLen;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (rxLen == 0) {
|
||||
return NETWORK_SSL_NOTHING_TO_READ;
|
||||
} else {
|
||||
return NETWORK_SSL_READ_TIMEOUT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_disconnect(Network *pNetwork) {
|
||||
mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl);
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = mbedtls_ssl_close_notify(ssl);
|
||||
} while(ret == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
|
||||
/* All other negative return values indicate connection needs to be reset.
|
||||
* No further action required since this is disconnect call */
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
IoT_Error_t iot_tls_destroy(Network *pNetwork) {
|
||||
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
|
||||
|
||||
mbedtls_net_free(&(tlsDataParams->server_fd));
|
||||
|
||||
mbedtls_x509_crt_free(&(tlsDataParams->clicert));
|
||||
mbedtls_x509_crt_free(&(tlsDataParams->cacert));
|
||||
mbedtls_pk_free(&(tlsDataParams->pkey));
|
||||
mbedtls_ssl_free(&(tlsDataParams->ssl));
|
||||
mbedtls_ssl_config_free(&(tlsDataParams->conf));
|
||||
mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg));
|
||||
mbedtls_entropy_free(&(tlsDataParams->entropy));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
104
components/aws_iot/port/threads_freertos.c
Normal file
104
components/aws_iot/port/threads_freertos.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "threads_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the provided mutex
|
||||
*
|
||||
* Call this function to initialize the mutex
|
||||
*
|
||||
* @param IoT_Mutex_t - pointer to the mutex to be initialized
|
||||
* @return IoT_Error_t - error code indicating result of operation
|
||||
*/
|
||||
IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) {
|
||||
|
||||
pMutex->mutex = xSemaphoreCreateRecursiveMutex();
|
||||
return pMutex->mutex ? SUCCESS : MUTEX_INIT_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the provided mutex
|
||||
*
|
||||
* Call this function to lock the mutex before performing a state change
|
||||
* Blocking, thread will block until lock request fails
|
||||
*
|
||||
* @param IoT_Mutex_t - pointer to the mutex to be locked
|
||||
* @return IoT_Error_t - error code indicating result of operation
|
||||
*/
|
||||
IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) {
|
||||
xSemaphoreTakeRecursive(pMutex->mutex, portMAX_DELAY);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to lock the provided mutex
|
||||
*
|
||||
* Call this function to attempt to lock the mutex before performing a state change
|
||||
* Non-Blocking, immediately returns with failure if lock attempt fails
|
||||
*
|
||||
* @param IoT_Mutex_t - pointer to the mutex to be locked
|
||||
* @return IoT_Error_t - error code indicating result of operation
|
||||
*/
|
||||
IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) {
|
||||
if (xSemaphoreTakeRecursive(pMutex->mutex, 0)) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return MUTEX_LOCK_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlock the provided mutex
|
||||
*
|
||||
* Call this function to unlock the mutex before performing a state change
|
||||
*
|
||||
* @param IoT_Mutex_t - pointer to the mutex to be unlocked
|
||||
* @return IoT_Error_t - error code indicating result of operation
|
||||
*/
|
||||
IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) {
|
||||
if (xSemaphoreGiveRecursive(pMutex->mutex)) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return MUTEX_UNLOCK_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the provided mutex
|
||||
*
|
||||
* Call this function to destroy the mutex
|
||||
*
|
||||
* @param IoT_Mutex_t - pointer to the mutex to be destroyed
|
||||
* @return IoT_Error_t - error code indicating result of operation
|
||||
*/
|
||||
IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) {
|
||||
vSemaphoreDelete(pMutex->mutex);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
83
components/aws_iot/port/timer.c
Normal file
83
components/aws_iot/port/timer.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file timer.c
|
||||
* @brief FreeRTOS implementation of the timer interface uses ticks.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "timer_platform.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
const static char *TAG = "aws_timer";
|
||||
|
||||
bool has_timer_expired(Timer *timer) {
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
bool expired = (now - timer->start_ticks) >= timer->timeout_ticks;
|
||||
|
||||
/* AWS IoT SDK isn't very RTOS friendly because it polls for "done
|
||||
timers" a lot without ever sleeping on them. So we hack in some
|
||||
amount of sleeping here: if it seems like the caller is polling
|
||||
an unexpired timer in a tight loop then we delay a tick to let
|
||||
things progress elsewhere.
|
||||
*/
|
||||
if(!expired && now == timer->last_polled_ticks) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
timer->last_polled_ticks = now;
|
||||
return expired;
|
||||
}
|
||||
|
||||
void countdown_ms(Timer *timer, uint32_t timeout) {
|
||||
timer->start_ticks = xTaskGetTickCount();
|
||||
timer->timeout_ticks = timeout / portTICK_PERIOD_MS;
|
||||
timer->last_polled_ticks = 0;
|
||||
}
|
||||
|
||||
uint32_t left_ms(Timer *timer) {
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
uint32_t elapsed = now - timer->start_ticks;
|
||||
if (elapsed < timer->timeout_ticks) {
|
||||
return (timer->timeout_ticks - elapsed) * portTICK_PERIOD_MS;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void countdown_sec(Timer *timer, uint32_t timeout) {
|
||||
if (timeout > UINT32_MAX / 1000) {
|
||||
ESP_LOGE(TAG, "timeout is out of range: %ds", timeout);
|
||||
}
|
||||
countdown_ms(timer, timeout * 1000);
|
||||
}
|
||||
|
||||
void init_timer(Timer *timer) {
|
||||
timer->start_ticks = 0;
|
||||
timer->timeout_ticks = 0;
|
||||
timer->last_polled_ticks = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,21 +1,7 @@
|
||||
idf_component_register(PRIV_REQUIRES partition_table)
|
||||
# bootloader component logic is all in project_include.cmake,
|
||||
# and subproject/CMakeLists.txt.
|
||||
#
|
||||
# This file is only included so the build system finds the
|
||||
# component
|
||||
|
||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
|
||||
if(NOT CONFIG_SECURE_BOOT_ENABLED)
|
||||
set(flash_bootloader FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
||||
# Set values used in flash_bootloader_args.in and generate flash file
|
||||
# for bootloader
|
||||
esptool_py_flash_project_args(bootloader 0x1000
|
||||
${BOOTLOADER_BUILD_DIR}/bootloader.bin
|
||||
${flash_bootloader}
|
||||
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
|
||||
|
||||
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
|
||||
add_dependencies(bootloader partition_table)
|
||||
|
||||
@@ -1,537 +1,448 @@
|
||||
menu "Bootloader config"
|
||||
choice BOOTLOADER_LOG_LEVEL
|
||||
bool "Bootloader log verbosity"
|
||||
default BOOTLOADER_LOG_LEVEL_INFO
|
||||
help
|
||||
Specify how much output to see in bootloader logs.
|
||||
choice LOG_BOOTLOADER_LEVEL
|
||||
bool "Bootloader log verbosity"
|
||||
default LOG_BOOTLOADER_LEVEL_INFO
|
||||
help
|
||||
Specify how much output to see in bootloader logs.
|
||||
|
||||
config BOOTLOADER_LOG_LEVEL_NONE
|
||||
bool "No output"
|
||||
config BOOTLOADER_LOG_LEVEL_ERROR
|
||||
bool "Error"
|
||||
config BOOTLOADER_LOG_LEVEL_WARN
|
||||
bool "Warning"
|
||||
config BOOTLOADER_LOG_LEVEL_INFO
|
||||
bool "Info"
|
||||
config BOOTLOADER_LOG_LEVEL_DEBUG
|
||||
bool "Debug"
|
||||
config BOOTLOADER_LOG_LEVEL_VERBOSE
|
||||
bool "Verbose"
|
||||
endchoice
|
||||
config LOG_BOOTLOADER_LEVEL_NONE
|
||||
bool "No output"
|
||||
config LOG_BOOTLOADER_LEVEL_ERROR
|
||||
bool "Error"
|
||||
config LOG_BOOTLOADER_LEVEL_WARN
|
||||
bool "Warning"
|
||||
config LOG_BOOTLOADER_LEVEL_INFO
|
||||
bool "Info"
|
||||
config LOG_BOOTLOADER_LEVEL_DEBUG
|
||||
bool "Debug"
|
||||
config LOG_BOOTLOADER_LEVEL_VERBOSE
|
||||
bool "Verbose"
|
||||
endchoice
|
||||
|
||||
config BOOTLOADER_LOG_LEVEL
|
||||
int
|
||||
default 0 if BOOTLOADER_LOG_LEVEL_NONE
|
||||
default 1 if BOOTLOADER_LOG_LEVEL_ERROR
|
||||
default 2 if BOOTLOADER_LOG_LEVEL_WARN
|
||||
default 3 if BOOTLOADER_LOG_LEVEL_INFO
|
||||
default 4 if BOOTLOADER_LOG_LEVEL_DEBUG
|
||||
default 5 if BOOTLOADER_LOG_LEVEL_VERBOSE
|
||||
config LOG_BOOTLOADER_LEVEL
|
||||
int
|
||||
default 0 if LOG_BOOTLOADER_LEVEL_NONE
|
||||
default 1 if LOG_BOOTLOADER_LEVEL_ERROR
|
||||
default 2 if LOG_BOOTLOADER_LEVEL_WARN
|
||||
default 3 if LOG_BOOTLOADER_LEVEL_INFO
|
||||
default 4 if LOG_BOOTLOADER_LEVEL_DEBUG
|
||||
default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE
|
||||
|
||||
config BOOTLOADER_SPI_WP_PIN
|
||||
int "SPI Flash WP Pin when customising pins via eFuse (read help)"
|
||||
range 0 33
|
||||
default 7
|
||||
depends on ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT
|
||||
help
|
||||
This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been
|
||||
overriden by setting the eFuses SPI_PAD_CONFIG_xxx.
|
||||
config BOOTLOADER_SPI_WP_PIN
|
||||
int "SPI Flash WP Pin when customising pins via efuse (read help)"
|
||||
range 0 33
|
||||
default 7
|
||||
depends on FLASHMODE_QIO || FLASHMODE_QOUT
|
||||
help
|
||||
This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been
|
||||
overriden by setting the efuses SPI_PAD_CONFIG_xxx.
|
||||
|
||||
When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32
|
||||
pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. That pin number is compiled into the
|
||||
bootloader instead.
|
||||
When this is the case, the Efuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32
|
||||
pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in Efuse. That pin number is compiled into the bootloader
|
||||
instead.
|
||||
|
||||
The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
|
||||
The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
|
||||
|
||||
choice BOOTLOADER_VDDSDIO_BOOST
|
||||
bool "VDDSDIO LDO voltage"
|
||||
default BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
help
|
||||
If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse
|
||||
or MTDI bootstrapping pin), bootloader will change LDO settings to
|
||||
output 1.9V instead. This helps prevent flash chip from browning out
|
||||
during flash programming operations.
|
||||
choice BOOTLOADER_VDDSDIO_BOOST
|
||||
bool "VDDSDIO LDO voltage"
|
||||
default BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
help
|
||||
If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE
|
||||
or MTDI bootstrapping pin), bootloader will change LDO settings to
|
||||
output 1.9V instead. This helps prevent flash chip from browning out
|
||||
during flash programming operations.
|
||||
|
||||
This option has no effect if VDDSDIO is set to 3.3V, or if the internal
|
||||
VDDSDIO regulator is disabled via eFuse.
|
||||
This option has no effect if VDDSDIO is set to 3.3V, or if the internal
|
||||
VDDSDIO regulator is disabled via efuse.
|
||||
|
||||
config BOOTLOADER_VDDSDIO_BOOST_1_8V
|
||||
bool "1.8V"
|
||||
depends on !ESPTOOLPY_FLASHFREQ_80M
|
||||
config BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
bool "1.9V"
|
||||
endchoice
|
||||
config BOOTLOADER_VDDSDIO_BOOST_1_8V
|
||||
bool "1.8V"
|
||||
depends on !ESPTOOLPY_FLASHFREQ_80M
|
||||
config BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
bool "1.9V"
|
||||
endchoice
|
||||
|
||||
config BOOTLOADER_FACTORY_RESET
|
||||
bool "GPIO triggers factory reset"
|
||||
default N
|
||||
help
|
||||
Allows to reset the device to factory settings:
|
||||
- clear one or more data partitions;
|
||||
- boot from "factory" partition.
|
||||
The factory reset will occur if there is a GPIO input pulled low while device starts up.
|
||||
See settings below.
|
||||
config BOOTLOADER_FACTORY_RESET
|
||||
bool "GPIO triggers factory reset"
|
||||
default N
|
||||
help
|
||||
Allows to reset the device to factory settings:
|
||||
- clear one or more data partitions;
|
||||
- boot from "factory" partition.
|
||||
The factory reset will occur if there is a GPIO input pulled low while device starts up.
|
||||
See settings below.
|
||||
|
||||
config BOOTLOADER_NUM_PIN_FACTORY_RESET
|
||||
int "Number of the GPIO input for factory reset"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
range 0 39
|
||||
default 4
|
||||
help
|
||||
The selected GPIO will be configured as an input with internal pull-up enabled.
|
||||
To trigger a factory reset, this GPIO must be pulled low on reset.
|
||||
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
|
||||
config BOOTLOADER_NUM_PIN_FACTORY_RESET
|
||||
int "Number of the GPIO input for factory reset"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
range 0 39
|
||||
default 4
|
||||
help
|
||||
The selected GPIO will be configured as an input with internal pull-up enabled.
|
||||
To trigger a factory reset, this GPIO must be pulled low on reset.
|
||||
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
|
||||
|
||||
config BOOTLOADER_OTA_DATA_ERASE
|
||||
bool "Clear OTA data on factory reset (select factory partition)"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
help
|
||||
The device will boot from "factory" partition (or OTA slot 0 if no factory partition is present) after a
|
||||
factory reset.
|
||||
config BOOTLOADER_OTA_DATA_ERASE
|
||||
bool "Clear OTA data on factory reset (select factory partition)"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
help
|
||||
The device will boot from "factory" partition (or OTA slot 0 if no factory partition is present) after a factory reset.
|
||||
|
||||
config BOOTLOADER_DATA_FACTORY_RESET
|
||||
string "Comma-separated names of partitions to clear on factory reset"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
default "nvs"
|
||||
help
|
||||
Allows customers to select which data partitions will be erased while factory reset.
|
||||
config BOOTLOADER_DATA_FACTORY_RESET
|
||||
string "Comma-separated names of partitions to clear on factory reset"
|
||||
depends on BOOTLOADER_FACTORY_RESET
|
||||
default "nvs"
|
||||
help
|
||||
Allows customers to select which data partitions will be erased while factory reset.
|
||||
|
||||
Specify the names of partitions as a comma-delimited with optional spaces for readability. (Like this: "nvs, phy_init, ...")
|
||||
Make sure that the name specified in the partition table and here are the same.
|
||||
Partitions of type "app" cannot be specified here.
|
||||
|
||||
Specify the names of partitions as a comma-delimited with optional spaces for readability. (Like this:
|
||||
"nvs, phy_init, ...")
|
||||
Make sure that the name specified in the partition table and here are the same.
|
||||
Partitions of type "app" cannot be specified here.
|
||||
config BOOTLOADER_APP_TEST
|
||||
bool "GPIO triggers boot from test app partition"
|
||||
default N
|
||||
help
|
||||
Allows to run the test app from "TEST" partition.
|
||||
A boot from "test" partition will occur if there is a GPIO input pulled low while device starts up.
|
||||
See settings below.
|
||||
|
||||
config BOOTLOADER_APP_TEST
|
||||
bool "GPIO triggers boot from test app partition"
|
||||
default N
|
||||
help
|
||||
Allows to run the test app from "TEST" partition.
|
||||
A boot from "test" partition will occur if there is a GPIO input pulled low while device starts up.
|
||||
See settings below.
|
||||
config BOOTLOADER_NUM_PIN_APP_TEST
|
||||
int "Number of the GPIO input to boot TEST partition"
|
||||
depends on BOOTLOADER_APP_TEST
|
||||
range 0 39
|
||||
default 18
|
||||
help
|
||||
The selected GPIO will be configured as an input with internal pull-up enabled.
|
||||
To trigger a test app, this GPIO must be pulled low on reset.
|
||||
After the GPIO input is deactivated and the device reboots, the old application will boot.
|
||||
(factory or OTA[x]).
|
||||
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
|
||||
|
||||
config BOOTLOADER_NUM_PIN_APP_TEST
|
||||
int "Number of the GPIO input to boot TEST partition"
|
||||
depends on BOOTLOADER_APP_TEST
|
||||
range 0 39
|
||||
default 18
|
||||
help
|
||||
The selected GPIO will be configured as an input with internal pull-up enabled.
|
||||
To trigger a test app, this GPIO must be pulled low on reset.
|
||||
After the GPIO input is deactivated and the device reboots, the old application will boot.
|
||||
(factory or OTA[x]).
|
||||
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
|
||||
config BOOTLOADER_HOLD_TIME_GPIO
|
||||
int "Hold time of GPIO for reset/test mode (seconds)"
|
||||
depends on BOOTLOADER_FACTORY_RESET || BOOTLOADER_APP_TEST
|
||||
default 5
|
||||
help
|
||||
The GPIO must be held low continuously for this period of time after reset
|
||||
before a factory reset or test partition boot (as applicable) is performed.
|
||||
|
||||
config BOOTLOADER_HOLD_TIME_GPIO
|
||||
int "Hold time of GPIO for reset/test mode (seconds)"
|
||||
depends on BOOTLOADER_FACTORY_RESET || BOOTLOADER_APP_TEST
|
||||
default 5
|
||||
help
|
||||
The GPIO must be held low continuously for this period of time after reset
|
||||
before a factory reset or test partition boot (as applicable) is performed.
|
||||
config BOOTLOADER_WDT_ENABLE
|
||||
bool "Use RTC watchdog in start code"
|
||||
default y
|
||||
help
|
||||
Tracks the execution time of startup code.
|
||||
If the execution time is exceeded, the RTC_WDT will restart system.
|
||||
It is also useful to prevent a lock up in start code caused by an unstable power source.
|
||||
NOTE: Tracks the execution time starts from the bootloader code - re-set timeout, while selecting the source for slow_clk - and ends calling app_main.
|
||||
Re-set timeout is needed due to WDT uses a SLOW_CLK clock source. After changing a frequency slow_clk a time of WDT needs to re-set for new frequency.
|
||||
slow_clk depends on ESP32_RTC_CLOCK_SOURCE (INTERNAL_RC or EXTERNAL_CRYSTAL).
|
||||
|
||||
config BOOTLOADER_WDT_ENABLE
|
||||
bool "Use RTC watchdog in start code"
|
||||
default y
|
||||
help
|
||||
Tracks the execution time of startup code.
|
||||
If the execution time is exceeded, the RTC_WDT will restart system.
|
||||
It is also useful to prevent a lock up in start code caused by an unstable power source.
|
||||
NOTE: Tracks the execution time starts from the bootloader code - re-set timeout, while selecting the
|
||||
source for slow_clk - and ends calling app_main.
|
||||
Re-set timeout is needed due to WDT uses a SLOW_CLK clock source. After changing a frequency slow_clk a
|
||||
time of WDT needs to re-set for new frequency.
|
||||
slow_clk depends on ESP32_RTC_CLK_SRC (INTERNAL_RC or EXTERNAL_CRYSTAL).
|
||||
config BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||
bool "Allows RTC watchdog disable in user code"
|
||||
depends on BOOTLOADER_WDT_ENABLE
|
||||
default n
|
||||
help
|
||||
If it is set, the client must itself reset or disable rtc_wdt in their code (app_main()).
|
||||
Otherwise rtc_wdt will be disabled before calling app_main function.
|
||||
Use function rtc_wdt_feed() for resetting counter of rtc_wdt.
|
||||
Use function rtc_wdt_disable() for disabling rtc_wdt.
|
||||
|
||||
config BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||
bool "Allows RTC watchdog disable in user code"
|
||||
depends on BOOTLOADER_WDT_ENABLE
|
||||
default n
|
||||
help
|
||||
If it is set, the client must itself reset or disable rtc_wdt in their code (app_main()).
|
||||
Otherwise rtc_wdt will be disabled before calling app_main function.
|
||||
Use function rtc_wdt_feed() for resetting counter of rtc_wdt.
|
||||
Use function rtc_wdt_disable() for disabling rtc_wdt.
|
||||
|
||||
config BOOTLOADER_WDT_TIME_MS
|
||||
int "Timeout for RTC watchdog (ms)"
|
||||
depends on BOOTLOADER_WDT_ENABLE
|
||||
default 9000
|
||||
range 0 120000
|
||||
help
|
||||
Verify that this parameter is correct and more then the execution time.
|
||||
Pay attention to options such as reset to factory, trigger test partition and encryption on boot
|
||||
- these options can increase the execution time.
|
||||
Note: RTC_WDT will reset while encryption operations will be performed.
|
||||
|
||||
config BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
bool "Enable app rollback support"
|
||||
default n
|
||||
help
|
||||
After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set.
|
||||
This state prevents the re-run of this app. After the first boot of the new app in the user code, the
|
||||
function should be called to confirm the operability of the app or vice versa about its non-operability.
|
||||
If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to
|
||||
the previous working app. A reboot is performed, and the app is booted before the software update.
|
||||
Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen.
|
||||
Rollback is possible only between the apps with the same security versions.
|
||||
|
||||
config BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
bool "Enable app anti-rollback support"
|
||||
depends on BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
default n
|
||||
help
|
||||
This option prevents rollback to previous firmware/application image with lower security version.
|
||||
|
||||
config BOOTLOADER_APP_SECURE_VERSION
|
||||
int "eFuse secure version of app"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
default 0
|
||||
help
|
||||
The secure version is the sequence number stored in the header of each firmware.
|
||||
The security version is set in the bootloader, version is recorded in the eFuse field
|
||||
as the number of set ones. The allocated number of bits in the efuse field
|
||||
for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option).
|
||||
|
||||
Bootloader: When bootloader selects an app to boot, an app is selected that has
|
||||
a security version greater or equal that recorded in eFuse field.
|
||||
The app is booted with a higher (or equal) secure version.
|
||||
|
||||
The security version is worth increasing if in previous versions there is
|
||||
a significant vulnerability and their use is not acceptable.
|
||||
|
||||
Your partition table should has a scheme with ota_0 + ota_1 (without factory).
|
||||
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32
|
||||
default 32
|
||||
help
|
||||
The size of the efuse secure version field. Its length is limited to 32 bits.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
bool "Emulate operations with efuse secure version(only test)"
|
||||
default n
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
help
|
||||
This option allow emulate read/write operations with efuse secure version.
|
||||
It allow to test anti-rollback implemention without permanent write eFuse bits.
|
||||
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
|
||||
config BOOTLOADER_WDT_TIME_MS
|
||||
int "Timeout for RTC watchdog (ms)"
|
||||
depends on BOOTLOADER_WDT_ENABLE
|
||||
default 9000
|
||||
range 0 120000
|
||||
help
|
||||
Verify that this parameter is correct and more then the execution time.
|
||||
Pay attention to options such as reset to factory, trigger test partition and encryption on boot
|
||||
- these options can increase the execution time.
|
||||
Note: RTC_WDT will reset while encryption operations will be performed.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
menu "Security features"
|
||||
visible if !IDF_CMAKE
|
||||
|
||||
# These three are the actual options to check in code,
|
||||
# selected by the displayed options
|
||||
config SECURE_SIGNED_ON_BOOT
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
# These three are the actual options to check in code,
|
||||
# selected by the displayed options
|
||||
config SECURE_SIGNED_ON_BOOT
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_ON_UPDATE
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
config SECURE_SIGNED_ON_UPDATE
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_APPS
|
||||
bool
|
||||
default y
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
select MBEDTLS_ECP_C
|
||||
select MBEDTLS_ECDH_C
|
||||
select MBEDTLS_ECDSA_C
|
||||
depends on SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE
|
||||
config SECURE_SIGNED_APPS
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE
|
||||
|
||||
|
||||
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
bool "Require signed app images"
|
||||
default n
|
||||
depends on !SECURE_BOOT_ENABLED
|
||||
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
bool "Require signed app images"
|
||||
default n
|
||||
depends on !SECURE_BOOT_ENABLED
|
||||
help
|
||||
Require apps to be signed to verify their integrity.
|
||||
|
||||
This option uses the same app signature scheme as hardware secure boot, but unlike hardware secure boot it does not prevent the bootloader from being physically updated. This means that the device can be secured against remote network access, but not physical access. Compared to using hardware Secure Boot this option is much simpler to implement.
|
||||
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
bool "Bootloader verifies app signatures"
|
||||
default n
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
help
|
||||
If this option is set, the bootloader will be compiled with code to verify that an app is signed before booting it.
|
||||
|
||||
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
|
||||
If hardware secure boot is not enabled, this option doesn't add significant security by itself so most users will want to leave it disabled.
|
||||
|
||||
config SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
bool "Verify app signature on update"
|
||||
default y
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
help
|
||||
If this option is set, any OTA updated apps will have the signature verified before being considered valid.
|
||||
|
||||
When enabled, the signature is automatically checked whenever the esp_ota_ops.h APIs are used for OTA updates,
|
||||
or esp_image_format.h APIs are used to verify apps.
|
||||
|
||||
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
|
||||
If hardware secure boot is not enabled, this option still adds significant security against network-based attackers by preventing spoofing of OTA updates.
|
||||
|
||||
config SECURE_BOOT_ENABLED
|
||||
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
help
|
||||
Build a bootloader which enables secure boot on first boot.
|
||||
|
||||
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature. There are implications for reflashing updated apps once secure boot is enabled.
|
||||
|
||||
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_MODE
|
||||
bool "Secure bootloader mode"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
|
||||
config SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
bool "One-time flash"
|
||||
help
|
||||
On first boot, the bootloader will generate a key which is not readable externally or by software. A digest is generated from the bootloader image itself. This digest will be verified on each subsequent boot.
|
||||
|
||||
Enabling this option means that the bootloader cannot be changed after the first time it is booted.
|
||||
|
||||
config SECURE_BOOTLOADER_REFLASHABLE
|
||||
bool "Reflashable"
|
||||
help
|
||||
Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
|
||||
|
||||
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key.
|
||||
|
||||
This option is less secure than one-time flash, because a leak of the digest key from one device allows reflashing of any device that uses it.
|
||||
|
||||
endchoice
|
||||
|
||||
config SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
bool "Sign binaries during build"
|
||||
depends on SECURE_SIGNED_APPS
|
||||
default y
|
||||
help
|
||||
Once secure boot or signed app requirement is enabled, app images are required to be signed.
|
||||
|
||||
If enabled (default), these binary files are signed as part of the build process. The file named in "Secure boot private signing key" will be used to sign the image.
|
||||
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py (for example, on a remote signing server.)
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
string "Secure boot private signing key"
|
||||
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default secure_boot_signing_key.pem
|
||||
help
|
||||
Path to the key file used to sign app images.
|
||||
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format.
|
||||
|
||||
Path is evaluated relative to the project directory.
|
||||
|
||||
You can generate a new signing key by running the following command:
|
||||
espsecure.py generate_signing_key secure_boot_signing_key.pem
|
||||
|
||||
See docs/security/secure-boot.rst for details.
|
||||
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default signature_verification_key.bin
|
||||
help
|
||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or app,
|
||||
to verify app images.
|
||||
|
||||
Key file is in raw binary format, and can be extracted from a
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||
bool "Hardware Key Encoding"
|
||||
depends on SECURE_BOOTLOADER_REFLASHABLE
|
||||
default SECURE_BOOTLOADER_NO_ENCODING
|
||||
help
|
||||
|
||||
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and can be written to efuse
|
||||
with espefuse.py.
|
||||
|
||||
Normally this is a 256-bit key, but if 3/4 Coding Scheme is used on the device then the efuse key is truncated to 192 bits.
|
||||
|
||||
This configuration item doesn't change any firmware code, it only changes the size of key binary which is generated at build time.
|
||||
|
||||
config SECURE_BOOTLOADER_KEY_ENCODING_256BIT
|
||||
bool "No encoding (256 bit key)"
|
||||
|
||||
config SECURE_BOOTLOADER_KEY_ENCODING_192BIT
|
||||
bool "3/4 encoding (192 bit key)"
|
||||
|
||||
endchoice
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default N
|
||||
help
|
||||
You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features.
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
config FLASH_ENCRYPTION_ENABLED
|
||||
bool "Enable flash encryption on boot (READ DOCS FIRST)"
|
||||
default N
|
||||
help
|
||||
If this option is set, flash contents will be encrypted by the bootloader on first boot.
|
||||
|
||||
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
|
||||
system is complicated and not always possible.
|
||||
|
||||
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html before enabling.
|
||||
|
||||
config FLASH_ENCRYPTION_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on FLASH_ENCRYPTION_ENABLED
|
||||
default N
|
||||
help
|
||||
You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features.
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
|
||||
|
||||
menu "Potentially insecure options"
|
||||
visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE
|
||||
|
||||
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
|
||||
# and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu
|
||||
# itself doesn't enable/disable its children (if it's not set,
|
||||
# it's possible for the insecure menu to be disabled but the insecure option
|
||||
# to remain on which is very bad.)
|
||||
|
||||
config SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
bool "Leave ROM BASIC Interpreter available on reset"
|
||||
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
|
||||
default N
|
||||
help
|
||||
By default, the BASIC ROM Console starts on reset if no valid bootloader is
|
||||
read from the flash.
|
||||
|
||||
When either flash encryption or secure boot are enabled, the default is to
|
||||
disable this BASIC fallback mode permanently via efuse.
|
||||
|
||||
If this option is set, this efuse is not burned and the BASIC ROM Console may
|
||||
remain accessible. Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_ALLOW_JTAG
|
||||
bool "Allow JTAG Debugging"
|
||||
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled.
|
||||
|
||||
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot.
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
|
||||
bool "Allow app partition length not 64KB aligned"
|
||||
depends on SECURE_BOOT_INSECURE
|
||||
help
|
||||
If not set (default), app partition size must be a multiple of 64KB. App images are padded to 64KB length, and the bootloader checks any trailing bytes after the signature (before the next 64KB boundary) have not been written. This is because flash cache maps entire 64KB pages into the address space. This prevents an attacker from appending unverified data after the app image in the flash, causing it to be mapped into the address space.
|
||||
|
||||
Setting this option allows the app partition length to be unaligned, and disables padding of the app image to this length. It is generally not recommended to set this option, unless you have a legacy partitioning scheme which doesn't support 64KB aligned partition lengths.
|
||||
|
||||
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on FLASH_ENCRYPTION_INSECURE
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption.
|
||||
|
||||
It is recommended to only set this option in testing environments.
|
||||
|
||||
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
|
||||
bool "Leave UART bootloader decryption enabled"
|
||||
depends on FLASH_ENCRYPTION_INSECURE
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption.
|
||||
|
||||
Only set this option in testing environments. Setting this option allows complete bypass of flash encryption.
|
||||
|
||||
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
|
||||
bool "Leave UART bootloader flash cache enabled"
|
||||
depends on FLASH_ENCRYPTION_INSECURE
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache.
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_TEST_MODE
|
||||
bool "Secure boot test mode: don't permanently set any efuses"
|
||||
depends on SECURE_BOOT_INSECURE
|
||||
default N
|
||||
help
|
||||
If this option is set, all permanent secure boot changes (via Efuse) are disabled.
|
||||
|
||||
Log output will state changes which would be applied, but they will not be.
|
||||
|
||||
This option is for testing purposes only - it completely disables secure boot protection.
|
||||
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config FLASH_ENCRYPTION_DISABLE_PLAINTEXT
|
||||
bool "Disable serial reflashing of plaintext firmware"
|
||||
depends on FLASH_ENCRYPTION_ENABLED
|
||||
default y if SECURE_BOOT_ENABLED
|
||||
default n if !SECURE_BOOT_ENABLED
|
||||
help
|
||||
Require apps to be signed to verify their integrity.
|
||||
If this option is enabled, flash encryption is permanently enabled after first boot by write-protecting
|
||||
the FLASH_CRYPT_CNT efuse. This is the recommended configuration for a secure production system.
|
||||
|
||||
This option uses the same app signature scheme as hardware secure boot, but unlike hardware secure boot it
|
||||
does not prevent the bootloader from being physically updated. This means that the device can be secured
|
||||
against remote network access, but not physical access. Compared to using hardware Secure Boot this option
|
||||
is much simpler to implement.
|
||||
If this option is disabled, FLASH_CRYPT_CNT is left writeable and up to 4 plaintext re-flashes are allowed.
|
||||
An attacker with physical access will be able to read out encrypted flash contents until all plaintext
|
||||
re-flashes have been used up.
|
||||
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
bool "Bootloader verifies app signatures"
|
||||
default n
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
help
|
||||
If this option is set, the bootloader will be compiled with code to verify that an app is signed before
|
||||
booting it.
|
||||
If this option is disabled and hardware Secure Boot is enabled, Secure Boot must be configured in
|
||||
Reflashable mode so that a new Secure Boot digest can be flashed at the same time as plaintext firmware.
|
||||
This combination is not secure and should not be used for a production system.
|
||||
|
||||
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
|
||||
If hardware secure boot is not enabled, this option doesn't add significant security by itself so most
|
||||
users will want to leave it disabled.
|
||||
|
||||
config SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
bool "Verify app signature on update"
|
||||
default y
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
help
|
||||
If this option is set, any OTA updated apps will have the signature verified before being considered valid.
|
||||
|
||||
When enabled, the signature is automatically checked whenever the esp_ota_ops.h APIs are used for OTA
|
||||
updates, or esp_image_format.h APIs are used to verify apps.
|
||||
|
||||
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
|
||||
If hardware secure boot is not enabled, this option still adds significant security against network-based
|
||||
attackers by preventing spoofing of OTA updates.
|
||||
|
||||
config SECURE_BOOT_ENABLED
|
||||
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
help
|
||||
Build a bootloader which enables secure boot on first boot.
|
||||
|
||||
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition
|
||||
table or boot an app if the data has a verified digital signature. There are implications for reflashing
|
||||
updated apps once secure boot is enabled.
|
||||
|
||||
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_MODE
|
||||
bool "Secure bootloader mode"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
|
||||
config SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
bool "One-time flash"
|
||||
help
|
||||
On first boot, the bootloader will generate a key which is not readable externally or by software. A
|
||||
digest is generated from the bootloader image itself. This digest will be verified on each subsequent
|
||||
boot.
|
||||
|
||||
Enabling this option means that the bootloader cannot be changed after the first time it is booted.
|
||||
|
||||
config SECURE_BOOTLOADER_REFLASHABLE
|
||||
bool "Reflashable"
|
||||
help
|
||||
Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
|
||||
|
||||
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing
|
||||
key.
|
||||
|
||||
This option is less secure than one-time flash, because a leak of the digest key from one device
|
||||
allows reflashing of any device that uses it.
|
||||
|
||||
endchoice
|
||||
|
||||
config SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
bool "Sign binaries during build"
|
||||
depends on SECURE_SIGNED_APPS
|
||||
default y
|
||||
help
|
||||
Once secure boot or signed app requirement is enabled, app images are required to be signed.
|
||||
|
||||
If enabled (default), these binary files are signed as part of the build process. The file named in
|
||||
"Secure boot private signing key" will be used to sign the image.
|
||||
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py
|
||||
(for example, on a remote signing server.)
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
string "Secure boot private signing key"
|
||||
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default "secure_boot_signing_key.pem"
|
||||
help
|
||||
Path to the key file used to sign app images.
|
||||
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format.
|
||||
|
||||
Path is evaluated relative to the project directory.
|
||||
|
||||
You can generate a new signing key by running the following command:
|
||||
espsecure.py generate_signing_key secure_boot_signing_key.pem
|
||||
|
||||
See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details.
|
||||
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default "signature_verification_key.bin"
|
||||
help
|
||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
|
||||
app, to verify app images.
|
||||
|
||||
Key file is in raw binary format, and can be extracted from a
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||
bool "Hardware Key Encoding"
|
||||
depends on SECURE_BOOTLOADER_REFLASHABLE
|
||||
default SECURE_BOOTLOADER_KEY_ENCODING_256BIT
|
||||
help
|
||||
|
||||
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
|
||||
can be written to eFuse with espefuse.py.
|
||||
|
||||
Normally this is a 256-bit key, but if 3/4 Coding Scheme is used on the device then the eFuse key is
|
||||
truncated to 192 bits.
|
||||
|
||||
This configuration item doesn't change any firmware code, it only changes the size of key binary which is
|
||||
generated at build time.
|
||||
|
||||
config SECURE_BOOTLOADER_KEY_ENCODING_256BIT
|
||||
bool "No encoding (256 bit key)"
|
||||
|
||||
config SECURE_BOOTLOADER_KEY_ENCODING_192BIT
|
||||
bool "3/4 encoding (192 bit key)"
|
||||
|
||||
endchoice
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default N
|
||||
help
|
||||
You can disable some of the default protections offered by secure boot, in order to enable testing or a
|
||||
custom combination of security features.
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
config SECURE_FLASH_ENC_ENABLED
|
||||
bool "Enable flash encryption on boot (READ DOCS FIRST)"
|
||||
default N
|
||||
help
|
||||
If this option is set, flash contents will be encrypted by the bootloader on first boot.
|
||||
|
||||
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
|
||||
system is complicated and not always possible.
|
||||
|
||||
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
|
||||
before enabling.
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_MODE
|
||||
bool "Enable usage mode"
|
||||
depends on SECURE_FLASH_ENC_ENABLED
|
||||
default SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
help
|
||||
By default Development mode is enabled which allows UART bootloader to perform flash encryption operations
|
||||
|
||||
Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART
|
||||
bootloader
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and
|
||||
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
bool "Development(NOT SECURE)"
|
||||
select SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
bool "Release"
|
||||
|
||||
endchoice
|
||||
|
||||
menu "Potentially insecure options"
|
||||
visible if SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT || SECURE_BOOT_INSECURE
|
||||
|
||||
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
|
||||
# and/or SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT in "depends on", as the menu
|
||||
# itself doesn't enable/disable its children (if it's not set,
|
||||
# it's possible for the insecure menu to be disabled but the insecure option
|
||||
# to remain on which is very bad.)
|
||||
|
||||
config SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
bool "Leave ROM BASIC Interpreter available on reset"
|
||||
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
By default, the BASIC ROM Console starts on reset if no valid bootloader is
|
||||
read from the flash.
|
||||
|
||||
When either flash encryption or secure boot are enabled, the default is to
|
||||
disable this BASIC fallback mode permanently via eFuse.
|
||||
|
||||
If this option is set, this eFuse is not burned and the BASIC ROM Console may
|
||||
remain accessible. Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_ALLOW_JTAG
|
||||
bool "Allow JTAG Debugging"
|
||||
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot
|
||||
when either secure boot or flash encryption is enabled.
|
||||
|
||||
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption
|
||||
and some of the protections of secure boot.
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
|
||||
bool "Allow app partition length not 64KB aligned"
|
||||
depends on SECURE_BOOT_INSECURE
|
||||
help
|
||||
If not set (default), app partition size must be a multiple of 64KB. App images are padded to 64KB
|
||||
length, and the bootloader checks any trailing bytes after the signature (before the next 64KB
|
||||
boundary) have not been written. This is because flash cache maps entire 64KB pages into the address
|
||||
space. This prevents an attacker from appending unverified data after the app image in the flash,
|
||||
causing it to be mapped into the address space.
|
||||
|
||||
Setting this option allows the app partition length to be unaligned, and disables padding of the app
|
||||
image to this length. It is generally not recommended to set this option, unless you have a legacy
|
||||
partitioning scheme which doesn't support 64KB aligned partition lengths.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader encryption access on
|
||||
first boot. If set, the UART bootloader will still be able to access hardware encryption.
|
||||
|
||||
It is recommended to only set this option in testing environments.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
|
||||
bool "Leave UART bootloader decryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader decryption access on
|
||||
first boot. If set, the UART bootloader will still be able to access hardware decryption.
|
||||
|
||||
Only set this option in testing environments. Setting this option allows complete bypass of flash
|
||||
encryption.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
bool "Leave UART bootloader flash cache enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on
|
||||
first boot. If set, the UART bootloader will still be able to access the flash cache.
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
bool "Require flash encryption to be already enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), and flash encryption is not yet enabled in eFuses, the 2nd stage bootloader
|
||||
will enable flash encryption: generate the flash encryption key and program eFuses.
|
||||
If this option is set, and flash encryption is not yet enabled, the bootloader will error out and
|
||||
reboot.
|
||||
If flash encryption is enabled in eFuses, this option does not change the bootloader behavior.
|
||||
|
||||
Only use this option in testing environments, to avoid accidentally enabling flash encryption on
|
||||
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
endmenu # Security features
|
||||
|
||||
|
||||
@@ -1,125 +1,29 @@
|
||||
set(BOOTLOADER_OFFSET 0x1000)
|
||||
|
||||
# Do not generate flash file when building bootloader
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
return() # don't keep recursing!
|
||||
endif()
|
||||
|
||||
# Glue to build the bootloader subproject binary as an external
|
||||
# cmake project under this one
|
||||
#
|
||||
#
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
set(BOOTLOADER_BUILD_DIR "${build_dir}/bootloader")
|
||||
set(bootloader_build_dir "${CMAKE_BINARY_DIR}/bootloader")
|
||||
set(bootloader_binary_files
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader.elf"
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader.map"
|
||||
"${bootloader_build_dir}/bootloader.elf"
|
||||
"${bootloader_build_dir}/bootloader.bin"
|
||||
"${bootloader_build_dir}/bootloader.map"
|
||||
)
|
||||
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
|
||||
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
# For both cases, the user either sets binaries to be signed during build or not
|
||||
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
#
|
||||
# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject
|
||||
# via config.
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_custom_target(gen_secure_boot_keys)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
# Check that the configuration is sane
|
||||
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
|
||||
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
|
||||
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
set(bootloader_binary_files
|
||||
${bootloader_binary_files}
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Since keys are usually given relative to main project dir, get the absolute paths to the keys
|
||||
# for use by the bootloader subproject. Replace the values in config with these absolute paths,
|
||||
# so that bootloader subproject does not need to assume main project dir to obtain path to the keys.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS ${secure_boot_signing_key})
|
||||
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
|
||||
# fails the build. fail_at_build_time causes a cmake run next time
|
||||
# (to pick up a new signing key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_signing_key
|
||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
endif()
|
||||
|
||||
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
|
||||
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
|
||||
else()
|
||||
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS ${secure_boot_verification_key})
|
||||
# If the verification key is not found, create a phony gen_secure_boot_verification_key target that
|
||||
# fails the build. fail_at_build_time causes a cmake run next time
|
||||
# (to pick up a new verification key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_verification_key
|
||||
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
|
||||
"\tThis can be extracted from the private signing key."
|
||||
"\tSee docs/security/secure-boot.rst for details.")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_verification_key)
|
||||
endif()
|
||||
|
||||
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
idf_build_get_property(python PYTHON)
|
||||
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
|
||||
|
||||
externalproject_add(bootloader
|
||||
# TODO: support overriding the bootloader in COMPONENT_PATHS
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target} -DPYTHON=${python}
|
||||
-DPYTHON_DEPS_CHECKED=1
|
||||
BINARY_DIR "${bootloader_build_dir}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${SDKCONFIG} -DIDF_PATH=${IDF_PATH}
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
${sign_key_arg} ${ver_key_arg}
|
||||
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
|
||||
# the bootloader common component requirements depends on this and
|
||||
# config variables are not available before project() call.
|
||||
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
|
||||
${extra_cmake_args}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
)
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_dependencies(bootloader gen_secure_boot_keys)
|
||||
endif()
|
||||
|
||||
# this is a hack due to an (annoying) shortcoming in cmake, it can't
|
||||
# extend the 'clean' target to the external project
|
||||
# see thread: https://cmake.org/pipermail/cmake/2016-December/064660.html
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# sdkconfig replacement configurations for deprecated options formatted as
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_NONE CONFIG_BOOTLOADER_LOG_LEVEL_NONE
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_ERROR CONFIG_BOOTLOADER_LOG_LEVEL_ERROR
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_WARN CONFIG_BOOTLOADER_LOG_LEVEL_WARN
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE
|
||||
|
||||
CONFIG_APP_ROLLBACK_ENABLE CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
CONFIG_APP_ANTI_ROLLBACK CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
CONFIG_APP_SECURE_VERSION CONFIG_BOOTLOADER_APP_SECURE_VERSION
|
||||
CONFIG_APP_SECURE_VERSION_SIZE_EFUSE_FIELD CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
CONFIG_EFUSE_SECURE_VERSION_EMULATE CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
|
||||
CONFIG_FLASH_ENCRYPTION_ENABLED CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
@@ -10,120 +10,19 @@ if(NOT IDF_PATH)
|
||||
"in by the parent build process.")
|
||||
endif()
|
||||
|
||||
if(NOT IDF_TARGET)
|
||||
message(FATAL_ERROR "Bootloader subproject expects the IDF_TARGET variable to be passed "
|
||||
"in by the parent build process.")
|
||||
endif()
|
||||
|
||||
set(COMPONENTS bootloader esptool_py partition_table soc bootloader_support log spi_flash micro-ecc main efuse)
|
||||
set(COMPONENTS bootloader esptool_py esp32 partition_table soc bootloader_support log spi_flash micro-ecc soc main)
|
||||
set(BOOTLOADER_BUILD 1)
|
||||
add_definitions(-DBOOTLOADER_BUILD=1)
|
||||
|
||||
set(COMPONENT_REQUIRES_COMMON log esp32 soc)
|
||||
|
||||
include("${IDF_PATH}/tools/cmake/project.cmake")
|
||||
set(common_req log esp_rom esp_common xtensa)
|
||||
if(LEGACY_INCLUDE_COMMON_HEADERS)
|
||||
list(APPEND common_req soc)
|
||||
endif()
|
||||
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
|
||||
idf_build_set_property(__OUTPUT_SDKCONFIG 0)
|
||||
project(bootloader)
|
||||
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
|
||||
target_linker_script(bootloader.elf
|
||||
"main/esp32.bootloader.ld"
|
||||
"main/esp32.bootloader.rom.ld")
|
||||
# Imported from esp32 component
|
||||
target_linker_script(bootloader.elf ${ESP32_BOOTLOADER_LINKER_SCRIPTS})
|
||||
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
|
||||
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT)
|
||||
set(key_digest_len 192)
|
||||
else()
|
||||
set(key_digest_len 256)
|
||||
endif()
|
||||
|
||||
get_filename_component(bootloader_digest_bin
|
||||
"bootloader-reflash-digest.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
|
||||
get_filename_component(secure_bootloader_key
|
||||
"secure-bootloader-key-${key_digest_len}.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
|
||||
add_custom_command(OUTPUT "${secure_bootloader_key}"
|
||||
COMMAND ${ESPSECUREPY} digest_private_key
|
||||
--keylen "${key_digest_len}"
|
||||
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
|
||||
"${secure_bootloader_key}"
|
||||
VERBATIM)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_target(gen_secure_bootloader_key ALL DEPENDS "${secure_bootloader_key}")
|
||||
else()
|
||||
if(NOT EXISTS "${secure_bootloader_key}")
|
||||
message(FATAL_ERROR
|
||||
"No pre-generated key for a reflashable secure bootloader is available, "
|
||||
"due to signing configuration."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
|
||||
"\nIf a signing key is present, then instead use:"
|
||||
"\n\t${espsecurepy} digest_private_key "
|
||||
"--keylen (192/256) --keyfile KEYFILE "
|
||||
"${secure_bootloader_key}")
|
||||
endif()
|
||||
add_custom_target(gen_secure_bootloader_key)
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${bootloader_digest_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
|
||||
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
|
||||
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
|
||||
DEPENDS gen_secure_bootloader_key gen_project_binary
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"One-time flash command is:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
|
||||
VERBATIM)
|
||||
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Bootloader built and secure digest generated."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Burn secure boot key to efuse using:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${espefusepy} burn_key secure_boot ${secure_bootloader_key}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"First time flash command is:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"To reflash the bootloader after initial flash:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${esptoolpy_write_flash} 0x0 ${bootloader_digest_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"* After first boot, only re-flashes of this kind (with same key) will be accepted."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
|
||||
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
|
||||
VERBATIM)
|
||||
endif()
|
||||
target_link_libraries(bootloader.elf gcc)
|
||||
|
||||
@@ -8,17 +8,14 @@ endif
|
||||
|
||||
PROJECT_NAME := bootloader
|
||||
|
||||
COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main efuse
|
||||
COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main
|
||||
|
||||
# Clear C and CXX from top level project
|
||||
CFLAGS =
|
||||
CXXFLAGS =
|
||||
|
||||
#We cannot include the idf_target, esp_rom, esp_common component directly but we need their includes.
|
||||
CFLAGS += -I $(IDF_PATH)/components/$(IDF_TARGET)/include
|
||||
CFLAGS += -I $(IDF_PATH)/components/esp_rom/include
|
||||
CFLAGS += -I $(IDF_PATH)/components/esp_common/include
|
||||
CFLAGS += -I $(IDF_PATH)/components/xtensa/include -I $(IDF_PATH)/components/xtensa/$(IDF_TARGET)/include
|
||||
#We cannot include the esp32 component directly but we need its includes.
|
||||
CFLAGS += -I $(IDF_PATH)/components/esp32/include
|
||||
|
||||
# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
|
||||
#
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# only compile the "micro-ecc/uECC.c" source file
|
||||
idf_component_register(SRCS "micro-ecc/uECC.c"
|
||||
INCLUDE_DIRS micro-ecc)
|
||||
@@ -1,8 +1,4 @@
|
||||
idf_component_register(SRCS "bootloader_start.c"
|
||||
REQUIRES bootloader bootloader_support)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "${target}.bootloader.ld"
|
||||
"${target}.bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
set(COMPONENT_SRCS "bootloader_start.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||
set(COMPONENT_REQUIRES "bootloader bootloader_support")
|
||||
register_component()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Submodules normally added in component.mk, but fully qualified
|
||||
# paths can be added at this level (we need binary librtc to be
|
||||
# available to link bootloader).
|
||||
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp_wifi/lib_esp32
|
||||
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp32/lib
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
static const char* TAG = "boot";
|
||||
|
||||
@@ -113,9 +113,3 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
}
|
||||
return boot_index;
|
||||
}
|
||||
|
||||
// Return global reent struct if any newlib functions are linked to bootloader
|
||||
struct _reent* __getreent() {
|
||||
return _GLOBAL_REENT;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#
|
||||
|
||||
LINKER_SCRIPTS := \
|
||||
$(IDF_TARGET).bootloader.ld \
|
||||
$(IDF_TARGET).bootloader.rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.newlib-funcs.ld \
|
||||
$(IDF_PATH)/components/$(IDF_TARGET)/ld/$(IDF_TARGET).peripherals.ld
|
||||
esp32.bootloader.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
|
||||
esp32.bootloader.rom.ld
|
||||
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp32/ld/esp32.rom.spiflash.ld
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
@@ -40,12 +40,12 @@ SECTIONS
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_clock.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:efuse.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
@@ -54,8 +54,6 @@ SECTIONS
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_wdt.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_clk.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
@@ -151,6 +149,7 @@ SECTIONS
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
|
||||
@@ -2,8 +2,3 @@ PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on
|
||||
PROVIDE ( MD5Final = 0x4005db1c );
|
||||
PROVIDE ( MD5Init = 0x4005da7c );
|
||||
PROVIDE ( MD5Update = 0x4005da9c );
|
||||
|
||||
/* bootloader will use following functions from xtensa hal library */
|
||||
xthal_get_ccount = 0x4000c050;
|
||||
xthal_get_ccompare = 0x4000c078;
|
||||
xthal_set_ccompare = 0x4000c058;
|
||||
|
||||
@@ -1,96 +1,28 @@
|
||||
set(srcs
|
||||
"src/bootloader_clock.c"
|
||||
"src/bootloader_common.c"
|
||||
"src/bootloader_flash.c"
|
||||
"src/bootloader_flash_config.c"
|
||||
"src/bootloader_random.c"
|
||||
"src/bootloader_utility.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c")
|
||||
set(COMPONENT_SRCS "src/bootloader_clock.c"
|
||||
"src/bootloader_common.c"
|
||||
"src/bootloader_flash.c"
|
||||
"src/bootloader_flash_config.c"
|
||||
"src/bootloader_random.c"
|
||||
"src/bootloader_sha.c"
|
||||
"src/bootloader_utility.c"
|
||||
"src/efuse.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c"
|
||||
"src/secure_boot.c"
|
||||
"src/secure_boot_signatures.c")
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
set(include_dirs "include" "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires micro-ecc spi_flash efuse)
|
||||
list(APPEND srcs
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c"
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
if(${BOOTLOADER_BUILD})
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "include include_bootloader")
|
||||
set(COMPONENT_REQUIRES)
|
||||
set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc)
|
||||
list(APPEND COMPONENT_SRCS "src/bootloader_init.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||
set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader")
|
||||
set(COMPONENT_REQUIRES)
|
||||
set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls micro-ecc)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}")
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
|
||||
# in the library.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# We generate the key from the signing key. The signing key is passed from the main project.
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
get_filename_component(secure_boot_verification_key
|
||||
"signature_verification_key.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
DEPENDS ${secure_boot_signing_key}
|
||||
VERBATIM)
|
||||
else()
|
||||
# We expect to 'inherit' the verification key passed from main project.
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
endif()
|
||||
else() # normal app build
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_VERIFICATION_KEY)
|
||||
# verification-only build supplies verification key
|
||||
set(secure_boot_verification_key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY})
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${secure_boot_verification_key}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
else()
|
||||
# sign at build time, extracts key from signing key
|
||||
set(secure_boot_verification_key "${CMAKE_BINARY_DIR}/signature_verification_key.bin")
|
||||
get_filename_component(secure_boot_signing_key
|
||||
${CONFIG_SECURE_BOOT_SIGNING_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
WORKING_DIRECTORY ${project_dir}
|
||||
DEPENDS ${secure_boot_signing_key}
|
||||
VERBATIM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Embed the verification key in the binary (app & bootloader)
|
||||
#
|
||||
target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY"
|
||||
RENAME_TO signature_verification_key_bin)
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${secure_boot_verification_key}")
|
||||
endif()
|
||||
register_component()
|
||||
|
||||
@@ -9,12 +9,6 @@ endif
|
||||
|
||||
COMPONENT_SRCDIRS := src
|
||||
|
||||
ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_SRCDIRS += src/idf # idf sub-directory contains platform agnostic IDF versions
|
||||
else
|
||||
COMPONENT_SRCDIRS += src/$(IDF_TARGET) # one sub-dir per chip
|
||||
endif
|
||||
|
||||
ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_OBJEXCLUDE := src/bootloader_init.o
|
||||
endif
|
||||
|
||||
@@ -14,16 +14,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Configure clocks for early boot
|
||||
*
|
||||
* Called by bootloader, or by the app if the bootloader version is old (pre v2.1).
|
||||
*/
|
||||
void bootloader_clock_configure(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,13 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_flash_data_types.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_app_format.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Type of hold a GPIO in low state
|
||||
typedef enum {
|
||||
@@ -34,29 +29,21 @@ typedef enum {
|
||||
} esp_image_type;
|
||||
|
||||
/**
|
||||
* @brief Calculate crc for the OTA data select.
|
||||
* @brief Calculate crc for the OTA data partition.
|
||||
*
|
||||
* @param[in] s The OTA data select.
|
||||
* @param[in] ota_data The OTA data partition.
|
||||
* @return Returns crc value.
|
||||
*/
|
||||
uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Verifies the validity of the OTA data select
|
||||
* @brief Verifies the validity of the OTA data partition
|
||||
*
|
||||
* @param[in] s The OTA data select.
|
||||
* @param[in] ota_data The OTA data partition.
|
||||
* @return Returns true on valid, false otherwise.
|
||||
*/
|
||||
bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Returns true if OTADATA is not marked as bootable partition.
|
||||
*
|
||||
* @param[in] s The OTA data select.
|
||||
* @return Returns true if OTADATA invalid, false otherwise.
|
||||
*/
|
||||
bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Check if the GPIO input is a long hold or a short hold.
|
||||
*
|
||||
@@ -111,42 +98,6 @@ bool bootloader_common_label_search(const char *list, char *label);
|
||||
*/
|
||||
esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of active otadata.
|
||||
*
|
||||
* @param[in] two_otadata Pointer on array from two otadata structures.
|
||||
*
|
||||
* @return The number of active otadata (0 or 1).
|
||||
* - -1: If it does not have active otadata.
|
||||
*/
|
||||
int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of active otadata.
|
||||
*
|
||||
* @param[in] two_otadata Pointer on array from two otadata structures.
|
||||
* @param[in] valid_two_otadata Pointer on array from two bools. True means select.
|
||||
* @param[in] max True - will select the maximum ota_seq number, otherwise the minimum.
|
||||
*
|
||||
* @return The number of active otadata (0 or 1).
|
||||
* - -1: If it does not have active otadata.
|
||||
*/
|
||||
int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max);
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition App partition description.
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
* @return
|
||||
* - ESP_OK: Successful.
|
||||
* - ESP_ERR_INVALID_ARG: The arguments passed are not valid.
|
||||
* - ESP_ERR_NOT_FOUND: app_desc structure is not found. Magic word is incorrect.
|
||||
* - ESP_FAIL: mapping is fail.
|
||||
*/
|
||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief Get chip revision
|
||||
*
|
||||
@@ -165,11 +116,8 @@ uint8_t bootloader_common_get_chip_revision(void);
|
||||
*/
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
|
||||
*/
|
||||
void bootloader_common_vddsdio_configure();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable early entropy source for RNG
|
||||
*
|
||||
@@ -51,7 +47,3 @@ void bootloader_random_disable(void);
|
||||
* @param length This many bytes of random data will be copied to buffer
|
||||
*/
|
||||
void bootloader_fill_random(void *buffer, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if half-open intervals overlap
|
||||
*
|
||||
@@ -33,11 +29,6 @@ static inline bool bootloader_util_regions_overlap(
|
||||
const intptr_t start1, const intptr_t end1,
|
||||
const intptr_t start2, const intptr_t end2)
|
||||
{
|
||||
assert(end1>start1);
|
||||
assert(end2>start2);
|
||||
return (end1 > start2 && end2 > start1);
|
||||
return (end1 > start2 && end2 > start1) ||
|
||||
!(end1 <= start2 || end2 <= start1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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
|
||||
|
||||
/**
|
||||
* @brief ESP chip ID
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */
|
||||
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
||||
} __attribute__((packed)) esp_chip_id_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit");
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief SPI flash mode, used in esp_image_header_t
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_MODE_QIO, /*!< SPI mode QIO */
|
||||
ESP_IMAGE_SPI_MODE_QOUT, /*!< SPI mode QOUT */
|
||||
ESP_IMAGE_SPI_MODE_DIO, /*!< SPI mode DIO */
|
||||
ESP_IMAGE_SPI_MODE_DOUT, /*!< SPI mode DOUT */
|
||||
ESP_IMAGE_SPI_MODE_FAST_READ, /*!< SPI mode FAST_READ */
|
||||
ESP_IMAGE_SPI_MODE_SLOW_READ /*!< SPI mode SLOW_READ */
|
||||
} esp_image_spi_mode_t;
|
||||
|
||||
/**
|
||||
* @brief SPI flash clock frequency
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_SPEED_40M, /*!< SPI clock frequency 40 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_26M, /*!< SPI clock frequency 26 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_20M, /*!< SPI clock frequency 20 MHz */
|
||||
ESP_IMAGE_SPI_SPEED_80M = 0xF /*!< SPI clock frequency 80 MHz */
|
||||
} esp_image_spi_freq_t;
|
||||
|
||||
/**
|
||||
* @brief Supported SPI flash sizes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_IMAGE_FLASH_SIZE_1MB = 0, /*!< SPI flash size 1 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_2MB, /*!< SPI flash size 2 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_4MB, /*!< SPI flash size 4 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_8MB, /*!< SPI flash size 8 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_16MB, /*!< SPI flash size 16 MB */
|
||||
ESP_IMAGE_FLASH_SIZE_MAX /*!< SPI flash size MAX */
|
||||
} esp_image_flash_size_t;
|
||||
|
||||
#define ESP_IMAGE_HEADER_MAGIC 0xE9 /*!< The magic word for the esp_image_header_t structure. */
|
||||
|
||||
/**
|
||||
* @brief Main header of binary image
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t magic; /*!< Magic word ESP_IMAGE_HEADER_MAGIC */
|
||||
uint8_t segment_count; /*!< Count of memory segments */
|
||||
uint8_t spi_mode; /*!< flash read mode (esp_image_spi_mode_t as uint8_t) */
|
||||
uint8_t spi_speed: 4; /*!< flash frequency (esp_image_spi_freq_t as uint8_t) */
|
||||
uint8_t spi_size: 4; /*!< flash chip size (esp_image_flash_size_t as uint8_t) */
|
||||
uint32_t entry_addr; /*!< Entry address */
|
||||
uint8_t wp_pin; /*!< WP pin when SPI pins set via efuse (read by ROM bootloader,
|
||||
* the IDF bootloader uses software to configure the WP
|
||||
* pin and sets this field to 0xEE=disabled) */
|
||||
uint8_t spi_pin_drv[3]; /*!< Drive settings for the SPI flash pins (read by ROM bootloader) */
|
||||
esp_chip_id_t chip_id; /*!< Chip identification number */
|
||||
uint8_t min_chip_rev; /*!< Minimum chip revision supported by image */
|
||||
uint8_t reserved[8]; /*!< Reserved bytes in additional header space, currently unused */
|
||||
uint8_t hash_appended; /*!< If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum.
|
||||
* Included in image length. This digest
|
||||
* is separate to secure boot and only used for detecting corruption.
|
||||
* For secure boot signed images, the signature
|
||||
* is appended after this (and the simple hash is included in the signed data). */
|
||||
} __attribute__((packed)) esp_image_header_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Header of binary image segment
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t load_addr; /*!< Address of segment */
|
||||
uint32_t data_len; /*!< Length of data */
|
||||
} esp_image_segment_header_t;
|
||||
|
||||
#define ESP_IMAGE_MAX_SEGMENTS 16 /*!< Max count of segments in the image. */
|
||||
|
||||
#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */
|
||||
|
||||
/**
|
||||
* @brief Description about application.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */
|
||||
uint32_t secure_version; /*!< Secure version */
|
||||
uint32_t reserv1[2]; /*!< reserv1 */
|
||||
char version[32]; /*!< Application version */
|
||||
char project_name[32]; /*!< Project name */
|
||||
char time[16]; /*!< Compile time */
|
||||
char date[16]; /*!< Compile date*/
|
||||
char idf_ver[32]; /*!< Version IDF */
|
||||
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
|
||||
uint32_t reserv2[20]; /*!< reserv2 */
|
||||
} esp_app_desc_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
|
||||
/** @endcond */
|
||||
106
components/bootloader_support/include/esp_efuse.h
Normal file
106
components/bootloader_support/include/esp_efuse.h
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 _ESP_EFUSE_H
|
||||
#define _ESP_EFUSE_H
|
||||
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* @brief Permanently update values written to the efuse write registers
|
||||
*
|
||||
* After updating EFUSE_BLKx_WDATAx_REG registers with new values to
|
||||
* write, call this function to permanently write them to efuse.
|
||||
*
|
||||
* @note Setting bits in efuse is permanent, they cannot be unset.
|
||||
*
|
||||
* @note Due to this restriction you don't need to copy values to
|
||||
* Efuse write registers from the matching read registers, bits which
|
||||
* are set in the read register but unset in the matching write
|
||||
* register will be unchanged when new values are burned.
|
||||
*
|
||||
* @note This function is not threadsafe, if calling code updates
|
||||
* efuse values from multiple tasks then this is caller's
|
||||
* responsibility to serialise.
|
||||
*
|
||||
* After burning new efuses, the read registers are updated to match
|
||||
* the new efuse values.
|
||||
*/
|
||||
void esp_efuse_burn_new_values(void);
|
||||
|
||||
/* @brief Reset efuse write registers
|
||||
*
|
||||
* Efuse write registers are written to zero, to negate
|
||||
* any changes that have been staged here.
|
||||
*/
|
||||
void esp_efuse_reset(void);
|
||||
|
||||
/* @brief Disable BASIC ROM Console via efuse
|
||||
*
|
||||
* By default, if booting from flash fails the ESP32 will boot a
|
||||
* BASIC console in ROM.
|
||||
*
|
||||
* Call this function (from bootloader or app) to permanently
|
||||
* disable the console on this chip.
|
||||
*/
|
||||
void esp_efuse_disable_basic_rom_console(void);
|
||||
|
||||
/* @brief Encode one or more sets of 6 byte sequences into
|
||||
* 8 bytes suitable for 3/4 Coding Scheme.
|
||||
*
|
||||
* This function is only useful if the CODING_SCHEME efuse
|
||||
* is set to value 1 for 3/4 Coding Scheme.
|
||||
*
|
||||
* @param[in] in_bytes Pointer to a sequence of bytes to encode for 3/4 Coding Scheme. Must have length in_bytes_len. After being written to hardware, these bytes will read back as little-endian words.
|
||||
* @param[out] out_words Pointer to array of words suitable for writing to efuse write registers. Array must contain 2 words (8 bytes) for every 6 bytes in in_bytes_len. Can be a pointer to efuse write registers.
|
||||
* @param in_bytes_len. Length of array pointed to by in_bytes, in bytes. Must be a multiple of 6.
|
||||
*
|
||||
* @return ESP_ERR_INVALID_ARG if either pointer is null or in_bytes_len is not a multiple of 6. ESP_OK otherwise.
|
||||
*/
|
||||
esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len);
|
||||
|
||||
/* @brief Write random data to efuse key block write registers
|
||||
*
|
||||
* @note Caller is responsible for ensuring efuse
|
||||
* block is empty and not write protected, before calling.
|
||||
*
|
||||
* @note Behaviour depends on coding scheme: a 256-bit key is
|
||||
* generated and written for Coding Scheme "None", a 192-bit key
|
||||
* is generated, extended to 256-bits by the Coding Scheme,
|
||||
* and then writtten for 3/4 Coding Scheme.
|
||||
*
|
||||
* @note This function does not burn the new values, caller should
|
||||
* call esp_efuse_burn_new_values() when ready to do this.
|
||||
*
|
||||
* @param blk_wdata0_reg Address of the first data write register
|
||||
* in the block
|
||||
*/
|
||||
void esp_efuse_write_random_key(uint32_t blk_wdata0_reg);
|
||||
|
||||
/**
|
||||
* @brief Returns chip version from efuse
|
||||
*
|
||||
* @return chip version
|
||||
*/
|
||||
uint8_t esp_efuse_get_chip_ver(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_EFUSE_H */
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#warning esp_flash_data_types.h has been merged into esp_flash_partitions.h, please include esp_flash_partitions.h instead
|
||||
#include "esp_flash_partitions.h"
|
||||
@@ -11,7 +11,8 @@
|
||||
// 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
|
||||
#ifndef __ESP32_FLASH_ENCRYPT_H
|
||||
#define __ESP32_FLASH_ENCRYPT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_attr.h"
|
||||
@@ -19,19 +20,7 @@
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* @brief Flash encryption mode based on efuse values
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_FLASH_ENC_MODE_DISABLED, // flash encryption is not enabled (flash crypt cnt=0)
|
||||
ESP_FLASH_ENC_MODE_DEVELOPMENT, // flash encryption is enabled but for Development (reflash over UART allowed)
|
||||
ESP_FLASH_ENC_MODE_RELEASE // flash encryption is enabled for Release (reflash over UART disabled)
|
||||
} esp_flash_enc_mode_t;
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
/**
|
||||
* @file esp_partition.h
|
||||
@@ -121,33 +110,8 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
|
||||
* is enabled but secure boot is not used. This should protect against
|
||||
* serial re-flashing of an unauthorised code in absence of secure boot.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void esp_flash_write_protect_crypt_cnt();
|
||||
|
||||
/** @brief Return the flash encryption mode
|
||||
*
|
||||
* The API is called during boot process but can also be called by
|
||||
* application to check the current flash encryption mode of ESP32
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode();
|
||||
|
||||
|
||||
/** @brief Check the flash encryption mode during startup
|
||||
*
|
||||
* @note This function is called automatically during app startup,
|
||||
* it doesn't need to be called from the app.
|
||||
*
|
||||
* Verifies the flash encryption config during startup:
|
||||
*
|
||||
* - Correct any insecure flash encryption settings if hardware
|
||||
* Secure Boot is enabled.
|
||||
* - Log warnings if the efuse config doesn't match the project
|
||||
* config in any way
|
||||
*/
|
||||
void esp_flash_encryption_init_checks(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,37 +11,14 @@
|
||||
// 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
|
||||
#ifndef __ESP_FLASH_PARTITIONS_H
|
||||
#define __ESP_FLASH_PARTITIONS_H
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_flash_data_types.h"
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_PARTITION_MAGIC 0x50AA
|
||||
#define ESP_PARTITION_MAGIC_MD5 0xEBEB
|
||||
|
||||
#define PART_TYPE_APP 0x00
|
||||
#define PART_SUBTYPE_FACTORY 0x00
|
||||
#define PART_SUBTYPE_OTA_FLAG 0x10
|
||||
#define PART_SUBTYPE_OTA_MASK 0x0f
|
||||
#define PART_SUBTYPE_TEST 0x20
|
||||
|
||||
#define PART_TYPE_DATA 0x01
|
||||
#define PART_SUBTYPE_DATA_OTA 0x00
|
||||
#define PART_SUBTYPE_DATA_RF 0x01
|
||||
#define PART_SUBTYPE_DATA_WIFI 0x02
|
||||
#define PART_SUBTYPE_DATA_NVS_KEYS 0x04
|
||||
#define PART_SUBTYPE_DATA_EFUSE_EM 0x05
|
||||
|
||||
#define PART_TYPE_END 0xff
|
||||
#define PART_SUBTYPE_END 0xff
|
||||
|
||||
#define PART_FLAG_ENCRYPTED (1<<0)
|
||||
|
||||
/* Pre-partition table fixed flash offsets */
|
||||
#define ESP_BOOTLOADER_DIGEST_OFFSET 0x0
|
||||
#define ESP_BOOTLOADER_OFFSET 0x1000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */
|
||||
@@ -50,43 +27,6 @@ extern "C" {
|
||||
#define ESP_PARTITION_TABLE_MAX_LEN 0xC00 /* Maximum length of partition table data */
|
||||
#define ESP_PARTITION_TABLE_MAX_ENTRIES (ESP_PARTITION_TABLE_MAX_LEN / sizeof(esp_partition_info_t)) /* Maximum length of partition table data, including terminating entry */
|
||||
|
||||
/// OTA_DATA states for checking operability of the app.
|
||||
typedef enum {
|
||||
ESP_OTA_IMG_NEW = 0x0U, /*!< Monitor the first boot. In bootloader this state is changed to ESP_OTA_IMG_PENDING_VERIFY. */
|
||||
ESP_OTA_IMG_PENDING_VERIFY = 0x1U, /*!< First boot for this app was. If while the second boot this state is then it will be changed to ABORTED. */
|
||||
ESP_OTA_IMG_VALID = 0x2U, /*!< App was confirmed as workable. App can boot and work without limits. */
|
||||
ESP_OTA_IMG_INVALID = 0x3U, /*!< App was confirmed as non-workable. This app will not selected to boot at all. */
|
||||
ESP_OTA_IMG_ABORTED = 0x4U, /*!< App could not confirm the workable or non-workable. In bootloader IMG_PENDING_VERIFY state will be changed to IMG_ABORTED. This app will not selected to boot at all. */
|
||||
ESP_OTA_IMG_UNDEFINED = 0xFFFFFFFFU, /*!< Undefined. App can boot and work without limits. */
|
||||
} esp_ota_img_states_t;
|
||||
|
||||
/* OTA selection structure (two copies in the OTA data partition.)
|
||||
Size of 32 bytes is friendly to flash encryption */
|
||||
typedef struct {
|
||||
uint32_t ota_seq;
|
||||
uint8_t seq_label[20];
|
||||
uint32_t ota_state;
|
||||
uint32_t crc; /* CRC32 of ota_seq field only */
|
||||
} esp_ota_select_entry_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
} esp_partition_pos_t;
|
||||
|
||||
/* Structure which describes the layout of partition table entry.
|
||||
* See docs/partition_tables.rst for more information about individual fields.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t magic;
|
||||
uint8_t type;
|
||||
uint8_t subtype;
|
||||
esp_partition_pos_t pos;
|
||||
uint8_t label[16];
|
||||
uint32_t flags;
|
||||
} esp_partition_info_t;
|
||||
|
||||
/* @brief Verify the partition table
|
||||
*
|
||||
* @param partition_table Pointer to at least ESP_PARTITION_TABLE_MAX_ENTRIES of potential partition table data. (ESP_PARTITION_TABLE_MAX_LEN bytes.)
|
||||
@@ -98,16 +38,10 @@ typedef struct {
|
||||
esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions);
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the region on the main flash is safe to write.
|
||||
*
|
||||
* @param addr Start address of the region
|
||||
* @param size Size of the region
|
||||
*
|
||||
* @return true if the region is safe to write, otherwise false.
|
||||
*/
|
||||
bool esp_partition_main_flash_region_safe(size_t addr, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* This function is included for compatibility with the ESP-IDF v3.x API */
|
||||
inline static __attribute__((deprecated)) esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions)
|
||||
{
|
||||
return esp_partition_table_verify(partition_table, log_errors, num_partitions);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_app_format.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_ERR_IMAGE_BASE 0x2000
|
||||
#define ESP_ERR_IMAGE_FLASH_FAIL (ESP_ERR_IMAGE_BASE + 1)
|
||||
@@ -30,8 +25,89 @@ extern "C" {
|
||||
Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
|
||||
/* SPI flash mode, used in esp_image_header_t */
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_MODE_QIO,
|
||||
ESP_IMAGE_SPI_MODE_QOUT,
|
||||
ESP_IMAGE_SPI_MODE_DIO,
|
||||
ESP_IMAGE_SPI_MODE_DOUT,
|
||||
ESP_IMAGE_SPI_MODE_FAST_READ,
|
||||
ESP_IMAGE_SPI_MODE_SLOW_READ
|
||||
} esp_image_spi_mode_t;
|
||||
|
||||
/* SPI flash clock frequency */
|
||||
typedef enum {
|
||||
ESP_IMAGE_SPI_SPEED_40M,
|
||||
ESP_IMAGE_SPI_SPEED_26M,
|
||||
ESP_IMAGE_SPI_SPEED_20M,
|
||||
ESP_IMAGE_SPI_SPEED_80M = 0xF
|
||||
} esp_image_spi_freq_t;
|
||||
|
||||
/* Supported SPI flash sizes */
|
||||
typedef enum {
|
||||
ESP_IMAGE_FLASH_SIZE_1MB = 0,
|
||||
ESP_IMAGE_FLASH_SIZE_2MB,
|
||||
ESP_IMAGE_FLASH_SIZE_4MB,
|
||||
ESP_IMAGE_FLASH_SIZE_8MB,
|
||||
ESP_IMAGE_FLASH_SIZE_16MB,
|
||||
ESP_IMAGE_FLASH_SIZE_MAX
|
||||
} esp_image_flash_size_t;
|
||||
|
||||
#define ESP_IMAGE_HEADER_MAGIC 0xE9
|
||||
|
||||
/**
|
||||
* @brief ESP chip ID
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */
|
||||
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
||||
} __attribute__((packed)) esp_chip_id_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit");
|
||||
|
||||
|
||||
/* Main header of binary image */
|
||||
typedef struct {
|
||||
uint8_t magic;
|
||||
uint8_t segment_count;
|
||||
/* flash read mode (esp_image_spi_mode_t as uint8_t) */
|
||||
uint8_t spi_mode;
|
||||
/* flash frequency (esp_image_spi_freq_t as uint8_t) */
|
||||
uint8_t spi_speed: 4;
|
||||
/* flash chip size (esp_image_flash_size_t as uint8_t) */
|
||||
uint8_t spi_size: 4;
|
||||
uint32_t entry_addr;
|
||||
/* WP pin when SPI pins set via efuse (read by ROM bootloader, the IDF bootloader uses software to configure the WP
|
||||
* pin and sets this field to 0xEE=disabled) */
|
||||
uint8_t wp_pin;
|
||||
/* Drive settings for the SPI flash pins (read by ROM bootloader) */
|
||||
uint8_t spi_pin_drv[3];
|
||||
/*!< Chip identification number */
|
||||
esp_chip_id_t chip_id;
|
||||
/*!< Minimum chip revision supported by image */
|
||||
uint8_t min_chip_rev;
|
||||
/*!< Reserved bytes in additional header space, currently unused */
|
||||
uint8_t reserved[8];
|
||||
/* If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. Included in image length. This digest
|
||||
* is separate to secure boot and only used for detecting corruption. For secure boot signed images, the signature
|
||||
* is appended after this (and the simple hash is included in the signed data). */
|
||||
uint8_t hash_appended;
|
||||
} __attribute__((packed)) esp_image_header_t;
|
||||
|
||||
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
|
||||
|
||||
#define ESP_IMAGE_HASH_LEN 32 /* Length of the appended SHA-256 digest */
|
||||
|
||||
/* Header of binary image segment */
|
||||
typedef struct {
|
||||
uint32_t load_addr;
|
||||
uint32_t data_len;
|
||||
} esp_image_segment_header_t;
|
||||
|
||||
#define ESP_IMAGE_MAX_SEGMENTS 16
|
||||
|
||||
/* Structure to hold on-flash image metadata */
|
||||
typedef struct {
|
||||
uint32_t start_addr; /* Start address of image */
|
||||
@@ -51,6 +127,36 @@ typedef enum {
|
||||
#endif
|
||||
} esp_image_load_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Verify and (optionally, in bootloader mode) load an app image.
|
||||
*
|
||||
* This name is deprecated and is included for compatibility with the ESP-IDF v3.x API.
|
||||
* It will be removed in V4.0 version.
|
||||
* Function has been renamed to esp_image_verify().
|
||||
* Use function esp_image_verify() to verify a image. And use function bootloader_load_image() to load image from a bootloader space.
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param mode Mode of operation (verify, silent verify, or load).
|
||||
* @param part Partition to load the app from.
|
||||
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function. 'start_addr' member should be set (to the start address of the image.) Other fields will all be initialised by this function.
|
||||
*
|
||||
* Image validation checks:
|
||||
* - Magic byte.
|
||||
* - Partition smaller than 16MB.
|
||||
* - All segments & image fit in partition.
|
||||
* - 8 bit image checksum is valid.
|
||||
* - SHA-256 of image is valid (if image has this appended).
|
||||
* - (Signature) if signature verification is enabled.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if verify or load was successful
|
||||
* - ESP_ERR_IMAGE_FLASH_FAIL if a SPI flash error occurs
|
||||
* - ESP_ERR_IMAGE_INVALID if the image appears invalid.
|
||||
* - ESP_ERR_INVALID_ARG if the partition or data pointers are invalid.
|
||||
*/
|
||||
esp_err_t esp_image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Verify an app image.
|
||||
*
|
||||
@@ -132,7 +238,3 @@ typedef struct {
|
||||
uint32_t irom_load_addr;
|
||||
uint32_t irom_size;
|
||||
} esp_image_flash_mapping_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@@ -46,25 +46,6 @@ static inline bool esp_secure_boot_enabled(void) {
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will:
|
||||
* 1) generate the secure boot key and burn it on EFUSE
|
||||
* (without enabling R/W protection)
|
||||
* 2) generate the digest from bootloader and save it
|
||||
* to flash address 0x0
|
||||
*
|
||||
* If first boot gets interrupted after calling this function
|
||||
* but before esp_secure_boot_permanently_enable() is called, then
|
||||
* the key burned on EFUSE will not be regenerated, unless manually
|
||||
* done using espefuse.py tool
|
||||
*
|
||||
* @return ESP_OK if secure boot digest is generated
|
||||
* successfully or found to be already present
|
||||
*/
|
||||
esp_err_t esp_secure_boot_generate_digest(void);
|
||||
|
||||
/** @brief Enable secure boot if it is not already enabled.
|
||||
*
|
||||
@@ -73,13 +54,9 @@ esp_err_t esp_secure_boot_generate_digest(void);
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important This will enable r/w protection of secure boot key on EFUSE,
|
||||
* therefore it is to be ensured that esp_secure_boot_generate_digest()
|
||||
* is called before this
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will
|
||||
* 1) enable R/W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
* generate the secure boot digest and enable secure boot by blowing
|
||||
* the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
*
|
||||
* This function does not verify secure boot of the bootloader (the
|
||||
* ROM bootloader does this.)
|
||||
@@ -87,6 +64,7 @@ esp_err_t esp_secure_boot_generate_digest(void);
|
||||
* Will fail if efuses have been part-burned in a way that indicates
|
||||
* secure boot should not or could not be correctly enabled.
|
||||
*
|
||||
*
|
||||
* @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
|
||||
* secure boot to be enabled cleanly. ESP_OK if secure boot
|
||||
* is enabled on this chip from now on.
|
||||
@@ -131,6 +109,7 @@ typedef struct {
|
||||
uint8_t digest[64];
|
||||
} esp_secure_boot_iv_digest_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_flash_data_types.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
#define SPI_SEC_SIZE 0x1000
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
that can be used from bootloader or app code.
|
||||
|
||||
This header is available to source code in the bootloader & bootloader_support components only.
|
||||
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
|
||||
Use mbedTLS APIs or include hwcrypto/sha.h to calculate SHA256 in IDF apps.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -31,3 +31,26 @@ bootloader_sha256_handle_t bootloader_sha256_start();
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest);
|
||||
|
||||
/**
|
||||
* @brief Converts an array to a printable string.
|
||||
*
|
||||
* This function is useful for printing SHA-256 digest.
|
||||
* \code{c}
|
||||
* // Example of using. image_hash will be printed
|
||||
* #define HASH_LEN 32 // SHA-256 digest length
|
||||
* ...
|
||||
* char hash_print[HASH_LEN * 2 + 1];
|
||||
* hash_print[HASH_LEN * 2] = 0;
|
||||
* bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
|
||||
* ESP_LOGI(TAG, %s", hash_print);
|
||||
* \endcode
|
||||
|
||||
* @param[out] out_str Output string
|
||||
* @param[in] in_array_hex Pointer to input array
|
||||
* @param[in] len Length of input array
|
||||
*
|
||||
* @return ESP_OK: Successful
|
||||
* ESP_ERR_INVALID_ARG: Error in the passed arguments
|
||||
*/
|
||||
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include "bootloader_config.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
/**
|
||||
@@ -63,26 +62,3 @@ __attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootload
|
||||
* It is not recommended to call this function from an app (if called, the app will abort).
|
||||
*/
|
||||
__attribute__((noreturn)) void bootloader_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Converts an array to a printable string.
|
||||
*
|
||||
* This function is useful for printing SHA-256 digest.
|
||||
* \code{c}
|
||||
* // Example of using. image_hash will be printed
|
||||
* #define HASH_LEN 32 // SHA-256 digest length
|
||||
* ...
|
||||
* char hash_print[HASH_LEN * 2 + 1];
|
||||
* hash_print[HASH_LEN * 2] = 0;
|
||||
* bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
|
||||
* ESP_LOGI(TAG, %s", hash_print);
|
||||
* \endcode
|
||||
|
||||
* @param[out] out_str Output string
|
||||
* @param[in] in_array_hex Pointer to input array
|
||||
* @param[in] len Length of input array
|
||||
*
|
||||
* @return ESP_OK: Successful
|
||||
* ESP_ERR_INVALID_ARG: Error in the passed arguments
|
||||
*/
|
||||
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
// 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 "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
void bootloader_clock_configure()
|
||||
{
|
||||
@@ -52,18 +53,9 @@ void bootloader_clock_configure()
|
||||
* part of the start up time by enabling 32k XTAL early.
|
||||
* App startup code will wait until the oscillator has started up.
|
||||
*/
|
||||
#ifdef CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
|
||||
#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
||||
if (!rtc_clk_32k_enabled()) {
|
||||
rtc_clk_32k_bootstrap(CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
|
||||
int esp_clk_apb_freq(void)
|
||||
{
|
||||
return rtc_clk_apb_freq_get();
|
||||
}
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
@@ -17,19 +17,23 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/crc.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "esp_flash_data_types.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "sys/param.h"
|
||||
|
||||
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
|
||||
|
||||
@@ -40,14 +44,9 @@ uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s)
|
||||
return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4);
|
||||
}
|
||||
|
||||
bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s)
|
||||
{
|
||||
return s->ota_seq == UINT32_MAX || s->ota_state == ESP_OTA_IMG_INVALID || s->ota_state == ESP_OTA_IMG_ABORTED;
|
||||
}
|
||||
|
||||
bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s)
|
||||
{
|
||||
return bootloader_common_ota_select_invalid(s) == false && s->crc == bootloader_common_ota_select_crc(s);
|
||||
return s->ota_seq != UINT32_MAX && s->crc == bootloader_common_ota_select_crc(s);
|
||||
}
|
||||
|
||||
esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec)
|
||||
@@ -199,65 +198,6 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max)
|
||||
{
|
||||
if (two_otadata == NULL || valid_two_otadata == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int active_otadata = -1;
|
||||
if (valid_two_otadata[0] && valid_two_otadata[1]) {
|
||||
int condition = (max == true) ? MAX(two_otadata[0].ota_seq, two_otadata[1].ota_seq) : MIN(two_otadata[0].ota_seq, two_otadata[1].ota_seq);
|
||||
if (condition == two_otadata[0].ota_seq) {
|
||||
active_otadata = 0;
|
||||
} else {
|
||||
active_otadata = 1;
|
||||
}
|
||||
ESP_LOGD(TAG, "Both OTA copies are valid");
|
||||
} else {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (valid_two_otadata[i]) {
|
||||
active_otadata = i;
|
||||
ESP_LOGD(TAG, "Only otadata[%d] is valid", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return active_otadata;
|
||||
}
|
||||
|
||||
int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata)
|
||||
{
|
||||
if (two_otadata == NULL) {
|
||||
return -1;
|
||||
}
|
||||
bool valid_two_otadata[2];
|
||||
valid_two_otadata[0] = bootloader_common_ota_select_valid(&two_otadata[0]);
|
||||
valid_two_otadata[1] = bootloader_common_ota_select_valid(&two_otadata[1]);
|
||||
return bootloader_common_select_otadata(two_otadata, valid_two_otadata, true);
|
||||
}
|
||||
|
||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc)
|
||||
{
|
||||
if (partition == NULL || app_desc == NULL || partition->offset == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const uint8_t *image = bootloader_mmap(partition->offset, partition->size);
|
||||
if (image == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, partition->size);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
memcpy(app_desc, image + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), sizeof(esp_app_desc_t));
|
||||
bootloader_munmap(image);
|
||||
|
||||
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_common_vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
@@ -273,7 +213,6 @@ void bootloader_common_vddsdio_configure()
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
@@ -301,7 +240,6 @@ uint8_t bootloader_common_get_chip_revision(void)
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type)
|
||||
{
|
||||
|
||||
@@ -86,8 +86,8 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#else
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include <soc/dport_reg.h>
|
||||
#include <esp32/rom/spi_flash.h>
|
||||
#include <esp32/rom/cache.h>
|
||||
#include <rom/spi_flash.h>
|
||||
#include <rom/cache.h>
|
||||
|
||||
static const char *TAG = "bootloader_flash";
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "soc/spi_pins.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
|
||||
@@ -17,28 +17,28 @@
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#include "rom/cache.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/crc.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/secure_boot.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
@@ -127,14 +127,12 @@ static esp_err_t bootloader_main()
|
||||
ESP_LOGE(TAG, "failed to load bootloader header!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Check chip ID and minimum chip revision that supported by this image */
|
||||
uint8_t revision = bootloader_common_get_chip_revision();
|
||||
ESP_LOGI(TAG, "Chip Revision: %d", revision);
|
||||
if (bootloader_common_check_chip_validity(&fhdr, ESP_IMAGE_BOOTLOADER) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
bootloader_init_flash_configure(&fhdr);
|
||||
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
@@ -182,7 +180,7 @@ static esp_err_t bootloader_main()
|
||||
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
||||
bootloader_random_enable();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
@@ -308,11 +306,11 @@ static void IRAM_ATTR bootloader_init_flash_configure(const esp_image_header_t*
|
||||
|
||||
static void uart_console_configure(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
#if CONFIG_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
#else // CONFIG_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
@@ -320,10 +318,10 @@ static void uart_console_configure(void)
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
#if CONFIG_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
@@ -350,13 +348,13 @@ static void uart_console_configure(void)
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
#endif // CONFIG_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
#endif // CONFIG_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user