mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-06 22:05:15 +02:00
Compare commits
779 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6213a906c0 | |||
| 68b583f30c | |||
| 7023f5bf3c | |||
| 0afcc02c47 | |||
| c4bfb8adba | |||
| 7ee9e7e785 | |||
| 4e8ad76602 | |||
| c5a17106b6 | |||
| 8f570513ea | |||
| f638d5e075 | |||
| b5d1c978b3 | |||
| d6a4c374c1 | |||
| 4116e4f697 | |||
| 9b14f91478 | |||
| 1571758b3d | |||
| fd9b2fab3a | |||
| 2aeec90f6c | |||
| 79a0958671 | |||
| ffaf0819d5 | |||
| afadb17ed8 | |||
| 8026e7acc7 | |||
| d93967009e | |||
| 62723f532f | |||
| 807cbbf24b | |||
| 35f2cca5f2 | |||
| 954e88c92d | |||
| dcd29e50c4 | |||
| cca744cd70 | |||
| 5106b95910 | |||
| e326d533de | |||
| 9ddef27ed4 | |||
| bd0873f9ec | |||
| 335ba6b3c2 | |||
| 79ebe0b306 | |||
| 304b561f8a | |||
| 8b2a1b4e37 | |||
| 78af627857 | |||
| 570f9d3c82 | |||
| d8c054c8c1 | |||
| b9f42e7bae | |||
| 4a189516c7 | |||
| 55f48c9c14 | |||
| 6abac38b9c | |||
| 3041f332c2 | |||
| f76d50c279 | |||
| 4860379677 | |||
| d0d3c1f84a | |||
| 7191595d2a | |||
| 22ae972229 | |||
| ede834d775 | |||
| 8ab969db1c | |||
| 5f1ad2c18d | |||
| d0ceef20f4 | |||
| 23f49324b2 | |||
| 7ab87012db | |||
| 2f4c5d278e | |||
| 15d998cf3b | |||
| d6c483a073 | |||
| bc34abb201 | |||
| ce6e136e70 | |||
| b6ea70c57b | |||
| ceb7f1d827 | |||
| 957a232259 | |||
| 40314930a6 | |||
| a82bdb87d3 | |||
| 069950761c | |||
| 02be119399 | |||
| 7f0d091f6e | |||
| 32bee685d6 | |||
| e6e629e475 | |||
| d4f3bceb69 | |||
| 72cc5dee10 | |||
| 025aec91c5 | |||
| e928897801 | |||
| 6fe38c7efd | |||
| 03433aad49 | |||
| 068847e2af | |||
| 5beacd1ad2 | |||
| 0190ba0390 | |||
| f4a45a30b5 | |||
| 7549d083a4 | |||
| 6d293c8582 | |||
| 1c5cadea13 | |||
| 2fb938c7c3 | |||
| c81dc5a9c4 | |||
| 0da7604680 | |||
| 974f571251 | |||
| bdf4dafe56 | |||
| caf1a18188 | |||
| d839ecbcf0 | |||
| 211238d6cd | |||
| 0fc082d87e | |||
| a319aa902c | |||
| be87c12a74 | |||
| 2435ffd1c6 | |||
| 561f017ef7 | |||
| a4037e2416 | |||
| 2d2aac017a | |||
| 12d2347e24 | |||
| f861b7dd65 | |||
| 520ee76e03 | |||
| d445536897 | |||
| 71072cc1af | |||
| beb6d79fc9 | |||
| d7aba9b677 | |||
| e603f4ec6b | |||
| 7eb710862c | |||
| b35982d521 | |||
| 81ee3bbe2c | |||
| d099224758 | |||
| d38621e95a | |||
| 1548e1dd67 | |||
| 740762c997 | |||
| 56130d0366 | |||
| a8b6017ca5 | |||
| 8fb69d6ef8 | |||
| 52a6290cf5 | |||
| bb5fc032e0 | |||
| 8192dfc530 | |||
| 68f9f0381a | |||
| 81b93828cf | |||
| 3a7c1a2e74 | |||
| 49df6a8b77 | |||
| a4cb2dc98b | |||
| bf3a050f4d | |||
| 1b7cb43842 | |||
| 71bc00568d | |||
| f3f6bc95df | |||
| 3e09d4f251 | |||
| d9457b807c | |||
| 2a17297d66 | |||
| fb4b590941 | |||
| a8bf745f23 | |||
| dd893957f3 | |||
| 81bb6a0557 | |||
| 3785a2421d | |||
| fa54de736e | |||
| f05d47c7d3 | |||
| 1615270205 | |||
| 3e2945b595 | |||
| 60bef64f5c | |||
| e8cefb33c8 | |||
| 619caaa79f | |||
| 42682b1e36 | |||
| 2fb4c6771a | |||
| d345ac1a50 | |||
| 00b1d66c6e | |||
| f10dcd6140 | |||
| 86d33f4460 | |||
| 3b0f4e4083 | |||
| ae3f20fa9f | |||
| 10d4e71323 | |||
| c205f50f93 | |||
| b3f24a9533 | |||
| 5ec67f5e2c | |||
| a2257490d2 | |||
| 044de64f5b | |||
| 916f70192f | |||
| e71e7552ef | |||
| 443e8718b8 | |||
| 85d74cdde8 | |||
| a4fcd06785 | |||
| a172dac0ef | |||
| 0fa5b07c7e | |||
| f4e8813d45 | |||
| 446e2fce11 | |||
| 3550140131 | |||
| b25f3fa966 | |||
| 6392180813 | |||
| 555c511d28 | |||
| 7847a82b28 | |||
| baa888e09b | |||
| 6eb5bfe587 | |||
| 71e15a1085 | |||
| 2fbb86deb7 | |||
| 96c6c0db67 | |||
| c10d3ac9ff | |||
| 1c95cdf649 | |||
| 0fe1586a55 | |||
| 913645d239 | |||
| da4ac0c56a | |||
| 3c403e97e1 | |||
| 48b37dd56e | |||
| 23d71fecd6 | |||
| a39d38994f | |||
| d49f4d31d0 | |||
| 8fede49368 | |||
| 4233552ce4 | |||
| 39a44b4a94 | |||
| f1dd6da8a3 | |||
| c85075dc12 | |||
| 724ce1fc97 | |||
| c490702340 | |||
| 8d0527d7bf | |||
| ce3611db26 | |||
| 5b7922b028 | |||
| 71da548124 | |||
| 3b504812df | |||
| c1666c8033 | |||
| ec689969c2 | |||
| 18e884532b | |||
| 6d2bfc70c1 | |||
| 0f2c1ab859 | |||
| da1842ea0f | |||
| adcbdd7da4 | |||
| c57254c4b1 | |||
| 0d8a1f5427 | |||
| b03186d71f | |||
| d835854c8f | |||
| a3cf6468b1 | |||
| 6bbd68b1f8 | |||
| a10696d7e1 | |||
| a2fab0ad60 | |||
| 581521526b | |||
| c802176535 | |||
| 6c5bff1bd8 | |||
| 44d7fc43f6 | |||
| 3c8ba488e0 | |||
| 4be18a2469 | |||
| 57c8d23800 | |||
| dacaae746e | |||
| dbf7835a6b | |||
| aa4489a879 | |||
| d8631ed3db | |||
| 139df47cf3 | |||
| eae1f3c302 | |||
| 85ec4df4db | |||
| fe78370ec9 | |||
| afdf1a31c8 | |||
| d0aabd36b4 | |||
| b173783d92 | |||
| bc93cee52e | |||
| 5799f556b4 | |||
| 8b30f85f2f | |||
| af69042685 | |||
| 24c15284db | |||
| a04df4631e | |||
| b194636859 | |||
| 4a80901841 | |||
| 27f232a929 | |||
| 3efb46e480 | |||
| 532ea1ad6d | |||
| ea4787e6e6 | |||
| ce970143bb | |||
| 1533cab12b | |||
| 3b2c6aee2e | |||
| 7a6cd632c5 | |||
| 0e680775f9 | |||
| 6287650225 | |||
| 4323627865 | |||
| dc814f241a | |||
| 24048d8267 | |||
| 514853d2e3 | |||
| de3b6ff3d6 | |||
| 3c84fd7b4d | |||
| ab9304d3b7 | |||
| a929aae33f | |||
| 15c336bf49 | |||
| 76723c063a | |||
| 5928a87aa7 | |||
| 2a13a36589 | |||
| c6c2948a99 | |||
| 49a4325b15 | |||
| 92883fbbdf | |||
| 2209a6c0b5 | |||
| 7912f9fafe | |||
| 63b7ae9ad1 | |||
| b84e9b69ba | |||
| 26e49e1e82 | |||
| 56ac76d4d2 | |||
| f50ae95ab5 | |||
| c62b4c7994 | |||
| fc4b2fbc28 | |||
| 7d25722980 | |||
| f8832b583c | |||
| a045046a7a | |||
| 4ce1da7569 | |||
| 9abd30adc0 | |||
| 6aeba18713 | |||
| 44ba32bef7 | |||
| a2b7ce698b | |||
| 473f316906 | |||
| 1294da2754 | |||
| a3270694f0 | |||
| 469a39bb22 | |||
| efb4d5766a | |||
| efcb8a5a49 | |||
| 4a8e0d85e4 | |||
| 3c01fd8301 | |||
| 7f95986a0e | |||
| 224b7e158d | |||
| 7738bca124 | |||
| d4cd6e5741 | |||
| 28e3112cde | |||
| 1f8ced8e6f | |||
| 9f4b9d815a | |||
| 87a5aedb85 | |||
| 11ad7e0581 | |||
| 1f45f98573 | |||
| 5036509679 | |||
| 50ef5946cb | |||
| 15414f99c3 | |||
| bf950e7dc5 | |||
| f51c769d99 | |||
| 0e6c063a13 | |||
| 441b801bc8 | |||
| c23c21f3c0 | |||
| ad164f5d57 | |||
| 5dcd1a578b | |||
| 2ef09a7952 | |||
| 63acb01dc1 | |||
| 4d27e1a399 | |||
| db3946ab9f | |||
| 47d20da4cd | |||
| 8150573012 | |||
| d4129533e6 | |||
| d86a84edfd | |||
| 1614e71eb6 | |||
| a9cdd337ce | |||
| 1bb75b2fb9 | |||
| 6cd14c143b | |||
| 94190ff7a9 | |||
| 5521ddff22 | |||
| 36a5a71d5c | |||
| 8f224d6a63 | |||
| bebfd14ae5 | |||
| fed2fb0a23 | |||
| 77277b59fc | |||
| c6a0d9118e | |||
| 8c2ea986b4 | |||
| 44895c0b3a | |||
| 713a63fb9f | |||
| 3dc6313c21 | |||
| 99aa39f8e8 | |||
| adf1c5bc97 | |||
| fb32407754 | |||
| 7f2d5939b5 | |||
| f5748246ea | |||
| 31c8dac885 | |||
| 6177115241 | |||
| ca30088aa8 | |||
| edc227c5ea | |||
| 4ffb3fb32d | |||
| e05390f338 | |||
| a7388ddc6c | |||
| 16d25b4a52 | |||
| 99121258d4 | |||
| 8806db34a3 | |||
| de9a367f13 | |||
| bb41e4163b | |||
| ccda40d8f2 | |||
| 1b5758a25e | |||
| fb6693c7a0 | |||
| 79d69bc7e1 | |||
| 65642866bc | |||
| e6d92ab49c | |||
| 17338659b9 | |||
| 30758d9beb | |||
| 4c11e81fd9 | |||
| a8ed0133ca | |||
| 5f743900e7 | |||
| 449abbab76 | |||
| 80a5ec8e78 | |||
| 40844075c3 | |||
| 619996f74a | |||
| 5f582fdc28 | |||
| 951bc53a03 | |||
| eb76e6341d | |||
| f764953df3 | |||
| 24d2720793 | |||
| 4c3b989ce5 | |||
| 09f077969c | |||
| d8f4388926 | |||
| 94143f2f18 | |||
| 2a861eadfb | |||
| 00038bd6f3 | |||
| bb9fbc040e | |||
| e0c43e6e7c | |||
| ef58299d06 | |||
| 65b7e70564 | |||
| b90c12c30f | |||
| ffdd4d6c7b | |||
| 113f40a3e0 | |||
| 34f249a28b | |||
| 904d9526d3 | |||
| 643e6ffdf1 | |||
| c17baef38d | |||
| 7926ffd13f | |||
| 94994f7ad3 | |||
| 456ae964a1 | |||
| b3560860dd | |||
| 77e18528cd | |||
| e89dc281e9 | |||
| 45a9a31a7e | |||
| c91a897697 | |||
| b4846b8f26 | |||
| 2c5530528c | |||
| 7e554894ce | |||
| 1d9e0ceab7 | |||
| 1f37a8da9a | |||
| 2b81deaca8 | |||
| 463135fded | |||
| 0a93309a89 | |||
| 78a2e2cb2f | |||
| 10aef84983 | |||
| fb2565815e | |||
| 60e64d2464 | |||
| 0eb74ffcc3 | |||
| c9cf11cd1c | |||
| aebdb81aa6 | |||
| e527554144 | |||
| b9d7771a14 | |||
| 21391a45fd | |||
| 03e6dda224 | |||
| 6d502b710c | |||
| 4d59537d5f | |||
| c275b5e55b | |||
| dbb846c348 | |||
| 412b79ed1c | |||
| a74725a31b | |||
| f7fedf3fb8 | |||
| f2ac9185aa | |||
| 6fde8cf8d2 | |||
| 783ea76212 | |||
| e08ed84287 | |||
| fe40cc8f8b | |||
| 3ce7470434 | |||
| bd87b7cf57 | |||
| 79c0c7a3db | |||
| 9466411cd6 | |||
| 18a468b0d5 | |||
| d8d8e91a80 | |||
| 1fa420ef2f | |||
| a2cf361c5a | |||
| 7d086d6a8d | |||
| 16cc8f974d | |||
| 0359404330 | |||
| c6bc55f91e | |||
| a93d61b756 | |||
| c36f55c451 | |||
| b8c1c2b616 | |||
| 87feca0350 | |||
| bf24bcd836 | |||
| a952037d82 | |||
| f582bd9ed0 | |||
| 49c373e2e8 | |||
| bf8a3c3e51 | |||
| f6b8ad87fa | |||
| c63f51dcb3 | |||
| 8afb0fb9e6 | |||
| 9d0d1d2614 | |||
| fa7c9b63b1 | |||
| 8184004a4e | |||
| 561c7c4884 | |||
| 5ae42e6f0b | |||
| e9d7adf697 | |||
| e80293fdbe | |||
| 8925459572 | |||
| e0be50d9b5 | |||
| 909fd09ffa | |||
| 6897f90612 | |||
| d55709fdae | |||
| e08189f37b | |||
| ff408c31c7 | |||
| 91f92b0e57 | |||
| 90050df641 | |||
| 8555b6c837 | |||
| 6674470e89 | |||
| fe1091c2ff | |||
| 5599fd4b1f | |||
| 70e5042ea9 | |||
| a1c6d2a458 | |||
| 0f1dbcc6a5 | |||
| a21f7c78f9 | |||
| 4bfd180a94 | |||
| 6397820d0b | |||
| c8371ca405 | |||
| 91d1812315 | |||
| 9837138659 | |||
| 9e5ed3bdd2 | |||
| 57420057b6 | |||
| 522e9a1bb9 | |||
| 148d31b659 | |||
| 0fb8c2a9b8 | |||
| d86c2bde3e | |||
| 5783a22d84 | |||
| 13904408af | |||
| a42929a75f | |||
| d877949357 | |||
| 994f2c2b68 | |||
| 9b77416b60 | |||
| 2f8cd616cc | |||
| 1d12eb4124 | |||
| 18091976ec | |||
| dadcc7b9f3 | |||
| 5133b89183 | |||
| 9a3018e201 | |||
| 481f42ac9d | |||
| 11f32b88ac | |||
| 022614b1d3 | |||
| 2931aa23b6 | |||
| 7b54ca004f | |||
| c25f87920a | |||
| 7d5f89fa90 | |||
| 00e3f4885a | |||
| 1d71a9e811 | |||
| 412e7c48ee | |||
| eb9614d37f | |||
| 574f037b1e | |||
| 11382a2aae | |||
| 5981ae8a11 | |||
| bfc69338c8 | |||
| 602941ef61 | |||
| 884e54a8dd | |||
| b1b99b30ef | |||
| a3318d6280 | |||
| f229a84578 | |||
| 4b6b9c0ec8 | |||
| fc69f691ba | |||
| 8ab564a711 | |||
| be89fa36aa | |||
| 996a9ca25f | |||
| 88f66ae3aa | |||
| ebd4caf360 | |||
| b8650708aa | |||
| b164919f4b | |||
| 17cd200c67 | |||
| 2ce481ffbd | |||
| 0631340e2c | |||
| 1e6bc70837 | |||
| 6ead06c6d5 | |||
| 1d739291ca | |||
| 27d68f57e6 | |||
| 6a57d5fa61 | |||
| dcdeeeff45 | |||
| 925b563278 | |||
| e10460ce14 | |||
| b8e48fbfc0 | |||
| 12e2df2d74 | |||
| 958f4b8900 | |||
| 004abebdbd | |||
| 6d7593c1be | |||
| f238d75ba3 | |||
| 19ce9ed634 | |||
| 3003362bcb | |||
| 3fd17b8be8 | |||
| fc61875a56 | |||
| 754d357f18 | |||
| 0dbce7210d | |||
| 061c05c88c | |||
| 30f98140bb | |||
| ed09e97c66 | |||
| 7af3bddbca | |||
| d46019bf43 | |||
| 9800d715a5 | |||
| 9c8c40369a | |||
| 43e2abac14 | |||
| cd3aa6527c | |||
| 22f63191e6 | |||
| 086555e0ed | |||
| 0e85a78aa9 | |||
| 8931a8a764 | |||
| e4be25ba63 | |||
| 70792443c7 | |||
| bba90309e7 | |||
| 3568f19fef | |||
| 16a3b2c71b | |||
| 1db79146e9 | |||
| 74c34669f0 | |||
| 3f65227d39 | |||
| f8699785e9 | |||
| 24c46f1b89 | |||
| 7bca1fe76f | |||
| abd5be52f1 | |||
| baab409af9 | |||
| f931739352 | |||
| 39cbbab859 | |||
| 8262915e28 | |||
| 9ef152c220 | |||
| 79d503f267 | |||
| 077ce905ed | |||
| f7bc58e4ec | |||
| 10ac8e622e | |||
| 928b07b859 | |||
| fbfa32c372 | |||
| 3d842bcee7 | |||
| 016e83671d | |||
| f3147df360 | |||
| a7e61220a1 | |||
| 747e3e0f31 | |||
| 465d809845 | |||
| a58ce394c4 | |||
| 644e38fb7a | |||
| bd5b0917fc | |||
| 660244e6ee | |||
| 98a0702ffc | |||
| 1e516f0f84 | |||
| f23bbb6cc7 | |||
| 9b1a80695c | |||
| 54e071a88c | |||
| e178a09d19 | |||
| 3cbe162bf0 | |||
| b452748eb5 | |||
| ad98c1d9a1 | |||
| de2962dd77 | |||
| f64b4d00b6 | |||
| 892ba4cbf7 | |||
| 2cc28d90fb | |||
| a0f085d012 | |||
| 7f982fa09d | |||
| 1637e27ae3 | |||
| 093db55bf4 | |||
| d12e072b35 | |||
| 9d687daf36 | |||
| eb81a853fb | |||
| 207d85a5f7 | |||
| cd6038b6cf | |||
| 3cfd4d0166 | |||
| 69158d5064 | |||
| 27220c1b4c | |||
| 29f89efea6 | |||
| 244d4f8fa7 | |||
| 616dd97398 | |||
| 9c8ead5e03 | |||
| b1999b5cb2 | |||
| 89adafa6af | |||
| 184b993d41 | |||
| e9aa543a43 | |||
| 81cca78ca1 | |||
| 5945ad1a63 | |||
| ec096b3823 | |||
| 9f69fe5033 | |||
| a5313b998c | |||
| 9a109ca17c | |||
| c3239ce836 | |||
| 9f6136d650 | |||
| cead328c1c | |||
| 3dc92d64b9 | |||
| c707faa41d | |||
| 4983ba1a59 | |||
| 94d71a8cd0 | |||
| 6918a45ee6 | |||
| d5441e65e5 | |||
| 4a18a67898 | |||
| 1b9fe2142d | |||
| 8f6a2370d2 | |||
| 6297edade5 | |||
| 31a089c751 | |||
| 8e4da0b71c | |||
| c776b440ec | |||
| a8128adc92 | |||
| 4911efca3a | |||
| c19ed90553 | |||
| c742f0a677 | |||
| afa79e0473 | |||
| 733c0586bc | |||
| abc9c1fd55 | |||
| fa00aa43e7 | |||
| f1446571e7 | |||
| 007a497483 | |||
| 4fae51e3c1 | |||
| c2b8ea07d0 | |||
| 0944a2a68a | |||
| 0c8b297610 | |||
| 77ae2808b0 | |||
| 402bf0ce58 | |||
| 0ed5a94ab0 | |||
| 7107177e2d | |||
| 179eb5a5aa | |||
| fc72712b10 | |||
| f9765d0316 | |||
| f1da7a55b1 | |||
| e70f2705f3 | |||
| 01520e84fb | |||
| e7d7412222 | |||
| acc74fd930 | |||
| 582e5690b2 | |||
| b5303b5d95 | |||
| c559e045fc | |||
| f201fd08da | |||
| cf18fe5568 | |||
| b961f42e8b | |||
| accfa14bcd | |||
| 36588e9a92 | |||
| 66e5cc8801 | |||
| 9f68214ab7 | |||
| 0a771792a9 | |||
| 0c1e5a13e2 | |||
| 0154c7cfe3 | |||
| cd10016953 | |||
| 4acf13dc7b | |||
| e1b6493304 | |||
| 9750c21933 | |||
| a6c26c3e21 | |||
| ef08ccaddf | |||
| 0a8064c1e5 | |||
| 58542cfdc9 | |||
| b9546506d4 | |||
| 342e0024f1 | |||
| 1e0577ebd0 | |||
| 90b978c9cf | |||
| 0c6aeecde4 | |||
| acda9a7a7e | |||
| e7449782d0 | |||
| 6599ba3c00 | |||
| 2189c52776 | |||
| 2b4aae2e3a | |||
| c9bab9e0d3 | |||
| bee2ed2502 | |||
| 4b664441ac | |||
| 79c66cc16c | |||
| 27099e1c55 | |||
| 11321b585e | |||
| f24025f798 | |||
| c06fa310cf | |||
| 0f45b6c6c3 | |||
| 8a4f94faf4 | |||
| 17599e60c7 | |||
| eb5d761c9d | |||
| b901559207 | |||
| dc05b46ab5 | |||
| 9a9438b79a | |||
| c9c8560169 | |||
| 6d2f4b3656 | |||
| 3baaa8c829 | |||
| 334cbe0dab | |||
| 617d215f93 | |||
| cd5b3877bf | |||
| b370ebdef4 | |||
| 478eea8992 | |||
| 45db752f2f | |||
| 38e84d554a | |||
| 4e20dc58b3 | |||
| e53c25d3ae | |||
| 542d07d34a | |||
| 764d722bec | |||
| aa714f5ae6 | |||
| 810eadd917 | |||
| 28afc7067f | |||
| 5bed100761 | |||
| 9c84243073 | |||
| f3d1717408 | |||
| 27ec17a623 | |||
| c4aaceb430 | |||
| 7c16bce827 | |||
| b691eaba6d | |||
| 7f6e7f4506 | |||
| e65f7359e6 | |||
| f5a28000fa | |||
| 9859f5e690 | |||
| 0103155f6f | |||
| 3ee449bc5d | |||
| 91da4ea792 | |||
| c99c80c1d0 | |||
| f9b81e80ba | |||
| f89d6ee5a0 | |||
| f019c5d549 | |||
| 7023b489a7 | |||
| 236200a93f | |||
| 71b992ac5d | |||
| 0586d10317 | |||
| 94830549ae | |||
| bfa0fff2e5 | |||
| df8c1f7a96 | |||
| ebb76933d0 | |||
| 6552854cb5 | |||
| c758af714a | |||
| 993bd86ee1 | |||
| cb4d90186f | |||
| 1fa908a7a5 | |||
| a62464501f | |||
| 9f4eb5c94b | |||
| 5cc6cbd4c7 | |||
| ba86dbb9f6 | |||
| cd54be77db | |||
| 898f881226 | |||
| 2205a22dc1 | |||
| 201df702da | |||
| fc58a6c116 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*,docs/sphinx-known-warnings.txt
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen,parms
|
||||
write-changes = true
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
release_zips:
|
||||
name: Create release zip file
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create a recursive clone source zip
|
||||
uses: espressif/release-zips-action@v1
|
||||
|
||||
@@ -37,6 +37,7 @@ components/**/build/
|
||||
components/**/build_*_*/
|
||||
components/**/sdkconfig
|
||||
components/**/sdkconfig.old
|
||||
components/**/test_apps/wifi_nvs_config/nvs_data_suffix.csv
|
||||
|
||||
# Example project files
|
||||
examples/**/build/
|
||||
|
||||
+249
-1
@@ -2,5 +2,253 @@
|
||||
#
|
||||
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
|
||||
#
|
||||
# If more than one rule matches a given file, the latest rule is used.
|
||||
# The file should be generally kept sorted, except when it is necessary
|
||||
# to use a different order due to the fact above. In that case, use
|
||||
# '# sort-order-reset' comment line to reset the sort order.
|
||||
#
|
||||
# Recipes for a few common cases:
|
||||
#
|
||||
# 1. Specific directory with all its contents:
|
||||
#
|
||||
# /components/app_trace/
|
||||
#
|
||||
# Note the trailing slash!
|
||||
#
|
||||
# 2. File with certain extension in any subdirectory of a certain directory:
|
||||
#
|
||||
# /examples/**/*.py
|
||||
#
|
||||
# This includes an *.py files in /examples/ directory as well.
|
||||
#
|
||||
# 3. Contents of a directory with a certain name, anywhere in the tree:
|
||||
#
|
||||
# test_*_host/
|
||||
#
|
||||
# Will match everything under components/efuse/test_efuse_host/,
|
||||
# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc.
|
||||
#
|
||||
# 4. Same as above, except limited to a specific place in the tree:
|
||||
#
|
||||
# /components/esp32*/
|
||||
#
|
||||
# Matches everything under /components/esp32, /components/esp32s2, etc.
|
||||
# Doesn't match /tools/some-test/components/esp32s5.
|
||||
#
|
||||
# 5. Specific file:
|
||||
#
|
||||
# /tools/tools.json
|
||||
#
|
||||
# 6. File with a certain name anywhere in the tree
|
||||
#
|
||||
# .gitignore
|
||||
#
|
||||
|
||||
* @esp-idf-codeowners/all-maintainers
|
||||
* @esp-idf-codeowners/other
|
||||
|
||||
/.* @esp-idf-codeowners/tools
|
||||
/.codespellrc @esp-idf-codeowners/ci
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.readthedocs.yml @esp-idf-codeowners/docs
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
/CMakeLists.txt @esp-idf-codeowners/build-config
|
||||
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
|
||||
/CONTRIBUTING.md @esp-idf-codeowners/docs
|
||||
/Kconfig @esp-idf-codeowners/build-config
|
||||
/README*.md @esp-idf-codeowners/docs
|
||||
/ROADMAP*.md @esp-idf-codeowners/docs
|
||||
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
|
||||
/add_path.sh @esp-idf-codeowners/tools
|
||||
/conftest.py @esp-idf-codeowners/ci
|
||||
/export.* @esp-idf-codeowners/tools
|
||||
/install.* @esp-idf-codeowners/tools
|
||||
/pytest.ini @esp-idf-codeowners/ci
|
||||
/ruff.toml @esp-idf-codeowners/tools
|
||||
/sdkconfig.rename @esp-idf-codeowners/build-config
|
||||
/sonar-project.properties @esp-idf-codeowners/ci
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/app_trace/ @esp-idf-codeowners/debugging
|
||||
/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security
|
||||
/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/bt/ @esp-idf-codeowners/bluetooth
|
||||
/components/cmock/ @esp-idf-codeowners/system
|
||||
/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console
|
||||
/components/cxx/ @esp-idf-codeowners/system
|
||||
/components/driver/ @esp-idf-codeowners/peripherals
|
||||
/components/efuse/ @esp-idf-codeowners/system
|
||||
/components/esp_adc/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154
|
||||
/components/esp_common/ @esp-idf-codeowners/system
|
||||
/components/esp_driver_*/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_driver_sdmmc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/storage
|
||||
/components/esp_eth/ @esp-idf-codeowners/network
|
||||
/components/esp_event/ @esp-idf-codeowners/system
|
||||
/components/esp_gdbstub/ @esp-idf-codeowners/debugging
|
||||
/components/esp_hid/ @esp-idf-codeowners/bluetooth
|
||||
/components/esp_http_client/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_http_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_ota/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_hw_support/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals
|
||||
/components/esp_hw_support/lowpower/ @esp-idf-codeowners/power-management
|
||||
/components/esp_lcd/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_mm/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_netif/ @esp-idf-codeowners/network
|
||||
/components/esp_netif_stack/ @esp-idf-codeowners/network
|
||||
/components/esp_partition/ @esp-idf-codeowners/storage
|
||||
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system
|
||||
/components/esp_psram/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_psram/system_layer/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/esp_ringbuf/ @esp-idf-codeowners/system
|
||||
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
|
||||
/components/esp_security/ @esp-idf-codeowners/security
|
||||
/components/esp_system/ @esp-idf-codeowners/system
|
||||
/components/esp_tee/ @esp-idf-codeowners/security
|
||||
/components/esp_timer/ @esp-idf-codeowners/system
|
||||
/components/esp-tls/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_vfs_*/ @esp-idf-codeowners/storage
|
||||
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
|
||||
/components/esp_wifi/ @esp-idf-codeowners/wifi
|
||||
/components/espcoredump/ @esp-idf-codeowners/debugging
|
||||
/components/esptool_py/ @esp-idf-codeowners/tools
|
||||
/components/fatfs/ @esp-idf-codeowners/storage
|
||||
/components/freertos/ @esp-idf-codeowners/system
|
||||
/components/hal/ @esp-idf-codeowners/peripherals
|
||||
/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/components/json/ @esp-idf-codeowners/app-utilities
|
||||
/components/linux/ @esp-idf-codeowners/system
|
||||
/components/log/ @esp-idf-codeowners/system
|
||||
/components/lwip/ @esp-idf-codeowners/lwip
|
||||
/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security
|
||||
/components/mqtt/ @esp-idf-codeowners/network
|
||||
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
|
||||
/components/nvs_flash/ @esp-idf-codeowners/storage
|
||||
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
|
||||
/components/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/components/partition_table/ @esp-idf-codeowners/system
|
||||
/components/perfmon/ @esp-idf-codeowners/debugging
|
||||
/components/protobuf-c/ @esp-idf-codeowners/app-utilities
|
||||
/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/pthread/ @esp-idf-codeowners/system
|
||||
/components/riscv/ @esp-idf-codeowners/system
|
||||
/components/rt/ @esp-idf-codeowners/system
|
||||
/components/sdmmc/ @esp-idf-codeowners/storage
|
||||
/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/spiffs/ @esp-idf-codeowners/storage
|
||||
/components/tcp_transport/ @esp-idf-codeowners/network
|
||||
/components/touch_element/ @esp-idf-codeowners/peripherals
|
||||
/components/ulp/ @esp-idf-codeowners/system
|
||||
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/usb/ @esp-idf-codeowners/peripherals/usb
|
||||
/components/vfs/ @esp-idf-codeowners/storage
|
||||
/components/wear_levelling/ @esp-idf-codeowners/storage
|
||||
/components/wifi_provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/wpa_supplicant/ @esp-idf-codeowners/wifi @esp-idf-codeowners/app-utilities/mbedtls
|
||||
/components/xtensa/ @esp-idf-codeowners/system
|
||||
|
||||
/docs/ @esp-idf-codeowners/docs
|
||||
/docs/docs_not_updated/ @esp-idf-codeowners/all-maintainers
|
||||
/docs/**/api-guides/tools/ @esp-idf-codeowners/tools
|
||||
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
|
||||
/docs/**/api-guides/wifi* @esp-idf-codeowners/wifi
|
||||
/docs/**/api-guides/esp-wifi-mesh.rst @esp-idf-codeowners/wifi
|
||||
/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging
|
||||
/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/peripherals/usb*/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/docs/**/api-reference/storage/ @esp-idf-codeowners/storage
|
||||
/docs/**/api-reference/system/ @esp-idf-codeowners/system
|
||||
/docs/**/security/ @esp-idf-codeowners/security
|
||||
/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers
|
||||
/docs/**/contribute/install-pre-commit-hook.rst @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
/examples/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/examples/build_system/ @esp-idf-codeowners/build-config
|
||||
/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network
|
||||
/examples/custom_bootloader/ @esp-idf-codeowners/system
|
||||
/examples/cxx/ @esp-idf-codeowners/system
|
||||
/examples/ethernet/ @esp-idf-codeowners/network
|
||||
/examples/get-started/ @esp-idf-codeowners/system
|
||||
/examples/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/examples/lowpower/ @esp-idf-codeowners/power-management @esp-idf-codeowners/system
|
||||
/examples/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/examples/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/examples/security/ @esp-idf-codeowners/security
|
||||
/examples/storage/ @esp-idf-codeowners/storage
|
||||
/examples/system/ @esp-idf-codeowners/system
|
||||
/examples/system/ota/ @esp-idf-codeowners/app-utilities
|
||||
/examples/wifi/ @esp-idf-codeowners/wifi
|
||||
/examples/zigbee/ @esp-idf-codeowners/ieee802154
|
||||
|
||||
/tools/ @esp-idf-codeowners/tools
|
||||
/tools/ble/ @esp-idf-codeowners/app-utilities
|
||||
/tools/bt/ @esp-idf-codeowners/bluetooth
|
||||
/tools/catch/ @esp-idf-codeowners/ci
|
||||
/tools/ci/ @esp-idf-codeowners/ci
|
||||
/tools/cmake/ @esp-idf-codeowners/build-config
|
||||
/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain
|
||||
/tools/esp_app_trace/ @esp-idf-codeowners/debugging
|
||||
/tools/esp_prov/ @esp-idf-codeowners/app-utilities
|
||||
/tools/gdb_panic_server.py @esp-idf-codeowners/debugging
|
||||
/tools/kconfig*/ @esp-idf-codeowners/build-config
|
||||
/tools/ldgen/ @esp-idf-codeowners/build-config
|
||||
/tools/mass_mfg/ @esp-idf-codeowners/app-utilities
|
||||
/tools/mocks/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/ @esp-idf-codeowners/ci
|
||||
/tools/test_apps/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
|
||||
## Note: owners here should be the same as the owners for the same example subdir, above
|
||||
/tools/test_apps/build_system/ @esp-idf-codeowners/build-config
|
||||
/tools/test_apps/configs/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/tools/test_apps/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/tools/test_apps/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/tools/test_apps/security/ @esp-idf-codeowners/security
|
||||
/tools/test_apps/storage/ @esp-idf-codeowners/storage
|
||||
/tools/test_apps/system/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/tools/test_build_system/ @esp-idf-codeowners/tools @esp-idf-codeowners/build-config
|
||||
|
||||
/tools/tools.json @esp-idf-codeowners/tools @esp-idf-codeowners/toolchain @esp-idf-codeowners/debugging
|
||||
|
||||
/tools/unit-test-app/ @esp-idf-codeowners/system @esp-idf-codeowners/tools
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
# ignore lists
|
||||
/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools
|
||||
|
||||
+14
-3
@@ -231,12 +231,17 @@ pytest_build_system_macos:
|
||||
- .after_script:build:macos:upload-failed-job-logs:ccache-show-stats
|
||||
- .rules:build:macos
|
||||
tags:
|
||||
- macos_shell
|
||||
- macos
|
||||
parallel: 3
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
# CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions.
|
||||
CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache".
|
||||
CCACHE_MAXSIZE: "5G" # To preserve the limited Macbook storage. CCACHE automatically prunes old caches to fit the set limit.
|
||||
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
|
||||
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
|
||||
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
|
||||
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
|
||||
|
||||
build_docker:
|
||||
extends:
|
||||
@@ -245,11 +250,17 @@ build_docker:
|
||||
stage: host_test
|
||||
needs: []
|
||||
image: espressif/docker-builder:1
|
||||
tags: [shiny, dind]
|
||||
tags:
|
||||
- build_docker_amd64_brno
|
||||
variables:
|
||||
DOCKER_TMP_IMAGE_NAME: "idf_tmp_image"
|
||||
script:
|
||||
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$CI_COMMIT_SHA} --build-arg IDF_CLONE_SHALLOW=1 --build-arg IDF_GITHUB_ASSETS=${INTERNAL_GITHUB_ASSETS}"
|
||||
- export LOCAL_CI_REPOSITORY_URL=$CI_REPOSITORY_URL
|
||||
- if [ -n "$LOCAL_GITLAB_HTTPS_HOST" ]; then export LOCAL_CI_REPOSITORY_URL="https://gitlab-ci-token:${CI_JOB_TOKEN}@${LOCAL_GITLAB_HTTPS_HOST}/${CI_PROJECT_PATH}"; fi
|
||||
- if [ -n "$LOCAL_GIT_MIRROR" ]; then export LOCAL_CI_REPOSITORY_URL="${LOCAL_GIT_MIRROR}/${CI_PROJECT_PATH}"; fi
|
||||
- echo "Using repository at $LOCAL_CI_REPOSITORY_URL"
|
||||
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${LOCAL_CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$PIPELINE_COMMIT_SHA}"
|
||||
# Build
|
||||
- docker build --tag ${DOCKER_TMP_IMAGE_NAME} ${DOCKER_BUILD_ARGS} tools/docker/
|
||||
# We can't mount $PWD/examples/get-started/blink into the container, see https://gitlab.com/gitlab-org/gitlab-ce/issues/41227.
|
||||
# The workaround mentioned there works, but leaves around directories which need to be cleaned up manually.
|
||||
|
||||
+12
-7
@@ -40,7 +40,7 @@ variables:
|
||||
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
|
||||
# we're using .cache folder for caches
|
||||
GIT_CLEAN_FLAGS: -ffdx -e .cache/
|
||||
LATEST_GIT_TAG: v5.5.1
|
||||
LATEST_GIT_TAG: v6.0-dev
|
||||
|
||||
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
|
||||
# by default we will fetch all submodules
|
||||
@@ -55,9 +55,9 @@ variables:
|
||||
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
|
||||
|
||||
# Docker images
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:3"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:3-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.5:2"
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:1"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:1-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:1"
|
||||
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
|
||||
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
|
||||
|
||||
@@ -70,7 +70,7 @@ variables:
|
||||
CI_PYTHON_CONSTRAINT_BRANCH: ""
|
||||
|
||||
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.5.txt"
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.0.txt"
|
||||
|
||||
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
|
||||
# Keep the variable empty when not used.
|
||||
@@ -140,6 +140,13 @@ variables:
|
||||
if [[ -n "$IDF_DONT_USE_MIRRORS" ]]; then
|
||||
export IDF_MIRROR_PREFIX_MAP=
|
||||
fi
|
||||
# Optimize pip install
|
||||
if echo "${CI_RUNNER_TAGS}" | grep "shiny"; then
|
||||
export PIP_INDEX_URL="${PIP_INDEX_URL_SHINY}"
|
||||
fi
|
||||
if [[ "$(uname -m)" == "x86_64" ]] || [[ "$(uname -m)" == "aarch64" ]]; then
|
||||
export IDF_PIP_WHEELS_URL=""
|
||||
fi
|
||||
|
||||
if [[ "${CI_JOB_STAGE}" != "target_test" ]]; then
|
||||
section_start "running_install_sh" "Running install.sh"
|
||||
@@ -236,8 +243,6 @@ variables:
|
||||
# Ensure pyenv and PYENV_VERSION installed
|
||||
- eval "$(pyenv init -)"
|
||||
- *common-before_scripts
|
||||
# On macOS, these tools need to be installed
|
||||
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
|
||||
# remove idf-env.json, since it may contains enabled "features"
|
||||
- rm -f $IDF_TOOLS_PATH/idf-env.json
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
|
||||
@@ -16,6 +16,7 @@ bypass_check_test_targets:
|
||||
- esp32h21
|
||||
- esp32h4
|
||||
- esp32c5
|
||||
- esp32c61
|
||||
|
||||
#
|
||||
# These lines would
|
||||
|
||||
@@ -91,4 +91,4 @@
|
||||
specific_rules:
|
||||
- if-schedule-test-build-system-windows
|
||||
patterns:
|
||||
- build_system
|
||||
- build_system_win
|
||||
|
||||
+10
-4
@@ -3,7 +3,6 @@
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ deploy ]
|
||||
|
||||
# Check this before push_to_github
|
||||
check_submodule_sync:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
@@ -19,7 +18,6 @@ check_submodule_sync:
|
||||
dependencies: []
|
||||
script:
|
||||
- git submodule deinit --force .
|
||||
- rm -rf .git/modules # remove all the cached metadata
|
||||
# setting the default remote URL to the public one, to resolve relative location URLs
|
||||
- git config remote.origin.url ${PUBLIC_IDF_URL}
|
||||
# check if all submodules are correctly synced to public repository
|
||||
@@ -32,8 +30,9 @@ push_to_github:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:push_to_github
|
||||
- .rules:protected:deploy
|
||||
needs:
|
||||
# submodule must be synced before pushing to github
|
||||
- check_submodule_sync
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
@@ -46,12 +45,16 @@ push_to_github:
|
||||
- git remote remove github &>/dev/null || true
|
||||
- git remote add github git@github.com:espressif/esp-idf.git
|
||||
- tools/ci/push_to_github.sh
|
||||
environment:
|
||||
name: push_to_github_production
|
||||
deployment_tier: production
|
||||
url: "https://github.com/espressif/esp-idf"
|
||||
|
||||
deploy_update_SHA_in_esp-dockerfiles:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:protected-no_label-always
|
||||
- .rules:protected:deploy
|
||||
dependencies: []
|
||||
variables:
|
||||
GIT_DEPTH: 2
|
||||
@@ -60,3 +63,6 @@ deploy_update_SHA_in_esp-dockerfiles:
|
||||
- 'curl --header "PRIVATE-TOKEN: ${ESPCI_SCRIPTS_TOKEN}" -o create_MR_in_esp_dockerfile.sh $GITLAB_HTTP_SERVER/api/v4/projects/1260/repository/files/create_MR_in_esp_dockerfile%2Fcreate_MR_in_esp_dockerfile.sh/raw\?ref\=master'
|
||||
- chmod +x create_MR_in_esp_dockerfile.sh
|
||||
- ./create_MR_in_esp_dockerfile.sh
|
||||
environment:
|
||||
name: eploy_update_SHA_in_esp-dockerfiles_production
|
||||
deployment_tier: production
|
||||
|
||||
+15
-12
@@ -4,10 +4,10 @@
|
||||
- "**/*.rst"
|
||||
- "CONTRIBUTING.rst"
|
||||
- "**/soc_caps.h"
|
||||
- "**/Kconfig*"
|
||||
|
||||
.patterns-docs-partial: &patterns-docs-partial
|
||||
- "components/**/*.h"
|
||||
- "components/**/Kconfig*"
|
||||
- "components/**/CMakeList.txt"
|
||||
- "components/**/sdkconfig*"
|
||||
- "tools/tools.json"
|
||||
@@ -19,12 +19,9 @@
|
||||
.patterns-docs-preview: &patterns-docs-preview
|
||||
- "docs/**/*"
|
||||
|
||||
.if-protected: &if-protected
|
||||
.if-protected-check: &if-protected-check
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)'
|
||||
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-qa-test-tag: &if-qa-test-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
@@ -41,7 +38,7 @@
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build_docs
|
||||
- <<: *if-label-docs_full
|
||||
- <<: *if-dev-push
|
||||
@@ -64,7 +61,7 @@ check_readme_links:
|
||||
tags: ["build", "amd64", "internet"]
|
||||
allow_failure: true
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-example-readme
|
||||
script:
|
||||
@@ -96,7 +93,7 @@ check_docs_lang_sync:
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5","esp32h2", "esp32h21", "esp32p4"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5", "esp32h2", "esp32h4", "esp32h21", "esp32p4"]
|
||||
|
||||
check_docs_gh_links:
|
||||
image: $ESP_IDF_DOC_ENV_IMAGE
|
||||
@@ -182,14 +179,17 @@ deploy_docs_preview:
|
||||
DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER"
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
environment:
|
||||
name: deploy_docs_preview
|
||||
deployment_tier: staging
|
||||
url: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
|
||||
# stage: post_deploy
|
||||
deploy_docs_production:
|
||||
# The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings
|
||||
extends:
|
||||
- .deploy_docs_template
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
- .rules:protected:deploy
|
||||
stage: post_deploy
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs: # ensure runs after push_to_github succeeded
|
||||
@@ -204,12 +204,15 @@ deploy_docs_production:
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esp-idf"
|
||||
DEPLOY_STABLE: 1
|
||||
environment:
|
||||
name: deploy_docs_production
|
||||
deployment_tier: production
|
||||
url: "https://docs.espressif.com/projects/esp-idf"
|
||||
|
||||
check_doc_links:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
- .rules:protected:deploy
|
||||
stage: post_deploy
|
||||
needs:
|
||||
- job: deploy_docs_production
|
||||
|
||||
@@ -349,7 +349,7 @@ test_pytest_macos:
|
||||
- .host_test_template
|
||||
- .before_script:build:macos
|
||||
tags:
|
||||
- macos_shell
|
||||
- macos
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
@@ -360,18 +360,22 @@ test_pytest_macos:
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
|
||||
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
|
||||
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
|
||||
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
|
||||
script:
|
||||
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
|
||||
--target linux
|
||||
--pytest-apps
|
||||
-m \"host_test and macos_shell\"
|
||||
-m \"host_test and macos\"
|
||||
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
- python tools/ci/get_known_failure_cases_file.py
|
||||
- run_cmd pytest
|
||||
--target linux
|
||||
-m \"host_test and macos_shell\"
|
||||
-m \"host_test and macos\"
|
||||
--junitxml=XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--app-info-filepattern \"list_job_*.txt\"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
generate_failed_jobs_report:
|
||||
.post_deploy_template:
|
||||
stage: post_deploy
|
||||
tags: [build, shiny]
|
||||
image: $ESP_ENV_IMAGE
|
||||
|
||||
generate_failed_jobs_report:
|
||||
extends:
|
||||
- .post_deploy_template
|
||||
tags: [build, shiny]
|
||||
when: always
|
||||
dependencies: [] # Do not download artifacts from the previous stages
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
expire_in: 2 week
|
||||
when: always
|
||||
paths:
|
||||
- job_report.html
|
||||
@@ -13,12 +17,16 @@ generate_failed_jobs_report:
|
||||
- python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job
|
||||
|
||||
sync_support_status:
|
||||
stage: post_deploy
|
||||
extends:
|
||||
- .rules:sync_support_status
|
||||
- .post_deploy_template
|
||||
- .rules:master:push
|
||||
tags: [ brew, github_sync ]
|
||||
needs:
|
||||
- push_to_github
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ brew, github_sync ]
|
||||
cache: []
|
||||
before_script: []
|
||||
script:
|
||||
- curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL"
|
||||
environment:
|
||||
name: sync_support_status_production
|
||||
deployment_tier: production
|
||||
|
||||
@@ -10,7 +10,7 @@ check_version:
|
||||
# esp_idf_version.h in a branch before tagging the next version.
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .rules:protected
|
||||
- .rules:protected:check
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
# need a full clone to get the latest tag
|
||||
|
||||
+31
-45
@@ -56,6 +56,9 @@
|
||||
- "tools/ci/ci_build_apps.py"
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-build_system_win: &patterns-build_system_win
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-build_macos: &patterns-build_macos
|
||||
- "tools/ci/test_configure_ci_environment.sh"
|
||||
|
||||
@@ -167,22 +170,19 @@
|
||||
##############
|
||||
# if anchors #
|
||||
##############
|
||||
.if-ref-master: &if-ref-master
|
||||
if: '$CI_COMMIT_REF_NAME == "master"'
|
||||
.if-master-push: &if-master-push
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
|
||||
|
||||
.if-ref-master-no_label: &if-ref-master-no_label
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-tag-release: &if-tag-release
|
||||
.if-release-tag: &if-release-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/'
|
||||
|
||||
.if-protected: &if-protected
|
||||
.if-protected-check: &if-protected-check
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
.if-protected-deploy: &if-protected-deploy
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "api")'
|
||||
|
||||
.if-protected-ref-push: &if-protected-ref-push
|
||||
.if-protected-branch-push: &if-protected-branch-push
|
||||
# rules:changes always evaluates to true for new branch pipelines or when there is no Git push event
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
|
||||
|
||||
@@ -192,9 +192,6 @@
|
||||
.if-dev-push: &if-dev-push
|
||||
if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")'
|
||||
|
||||
.if-schedule: &if-schedule
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
|
||||
.if-schedule-nightly: &if-schedule-nightly
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"'
|
||||
|
||||
@@ -214,51 +211,41 @@
|
||||
# Rules #
|
||||
#########
|
||||
### Branches ###
|
||||
.rules:protected:
|
||||
.rules:protected:check:
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
|
||||
.rules:push_to_github:
|
||||
.rules:protected:deploy:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-no_label
|
||||
- <<: *if-protected-deploy
|
||||
|
||||
# Not uploading on release branches
|
||||
.rules:sync_support_status:
|
||||
.rules:master:push:
|
||||
rules:
|
||||
- <<: *if-ref-master-no_label
|
||||
|
||||
.rules:protected-no_label-always:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-no_label
|
||||
when: always
|
||||
- <<: *if-master-push
|
||||
|
||||
.rules:tag:release:
|
||||
rules:
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-release-tag
|
||||
|
||||
.rules:dev-push:
|
||||
rules:
|
||||
- <<: *if-dev-push
|
||||
|
||||
# Do not upload caches on dev branches by default
|
||||
.rules:upload-python-cache:
|
||||
rules:
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-schedule-nightly
|
||||
- <<: *if-protected-ref-push
|
||||
- <<: *if-protected-branch-push
|
||||
changes: *patterns-python-cache
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
|
||||
.rules:upload-submodule-cache:
|
||||
rules:
|
||||
# Needn't upload submodule cache in schedule pipeline
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-protected-ref-push
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-protected-branch-push
|
||||
changes: *patterns-submodule
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
@@ -266,11 +253,10 @@
|
||||
### Patterns ###
|
||||
.rules:patterns:clang_tidy:
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-c-files
|
||||
|
||||
|
||||
#.rules:patterns:static-code-analysis-preview:
|
||||
# rules:
|
||||
# - <<: *if-dev-push
|
||||
@@ -282,7 +268,7 @@
|
||||
|
||||
.rules:patterns:idf-pytest-plugin:
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-idf-pytest-plugin
|
||||
|
||||
@@ -326,7 +312,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
@@ -339,7 +325,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_check
|
||||
@@ -354,7 +340,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-docker
|
||||
- <<: *if-dev-push
|
||||
@@ -370,7 +356,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-macos
|
||||
- <<: *if-label-macos_test
|
||||
@@ -385,7 +371,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
@@ -409,13 +395,13 @@
|
||||
- <<: *if-schedule-test-build-system-windows
|
||||
- <<: *if-label-windows
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_system
|
||||
changes: *patterns-build_system_win
|
||||
|
||||
.rules:test:host_test:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-host_test
|
||||
@@ -426,7 +412,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-submodule
|
||||
|
||||
@@ -85,7 +85,7 @@ clang_tidy_check:
|
||||
#code_quality_report:
|
||||
# extends:
|
||||
# - .sonar_scan_template
|
||||
# - .rules:protected
|
||||
# - .rules:protected:check
|
||||
# allow_failure: true # it's using exit code to indicate the code analysis result,
|
||||
# # we don't want to block ci when critical issues founded
|
||||
# script:
|
||||
|
||||
@@ -14,12 +14,7 @@
|
||||
- job: upload-submodules-cache
|
||||
optional: true
|
||||
artifacts: false
|
||||
variables:
|
||||
GIT_STRATEGY: fetch # use brew local mirror first
|
||||
before_script:
|
||||
- if ($env:IDF_DONT_USE_MIRRORS) {
|
||||
$env:IDF_MIRROR_PREFIX_MAP = ""
|
||||
}
|
||||
before_script: []
|
||||
after_script: []
|
||||
|
||||
test_cli_installer_win:
|
||||
@@ -28,6 +23,7 @@ test_cli_installer_win:
|
||||
extends:
|
||||
- .host_test_win_template
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
@@ -37,7 +33,6 @@ test_cli_installer_win:
|
||||
variables:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
timeout: 3h
|
||||
allow_failure: true
|
||||
script:
|
||||
# Tools must be downloaded for testing
|
||||
# cmake@version that is supported
|
||||
|
||||
+5
-3
@@ -49,13 +49,15 @@
|
||||
[submodule "components/json/cJSON"]
|
||||
path = components/json/cJSON
|
||||
url = ../../DaveGamble/cJSON.git
|
||||
sbom-version = 1.7.19
|
||||
sbom-version = 1.7.18
|
||||
sbom-cpe = cpe:2.3:a:cjson_project:cjson:{}:*:*:*:*:*:*:*
|
||||
sbom-cpe = cpe:2.3:a:davegamble:cjson:{}:*:*:*:*:*:*:*
|
||||
sbom-supplier = Person: Dave Gamble
|
||||
sbom-url = https://github.com/DaveGamble/cJSON
|
||||
sbom-description = Ultralightweight JSON parser in ANSI C
|
||||
sbom-hash = c859b25da02955fef659d658b8f324b5cde87be3
|
||||
sbom-hash = 8f2beb57ddad1f94bed899790b00f46df893ccac
|
||||
sbom-cve-exclude-list = CVE-2024-31755 Resolved in v1.7.18
|
||||
sbom-cve-exclude-list = CVE-2023-26819 Resolved in commit a328d65ad490b64da8c87523cbbfe16050ba5bf6
|
||||
sbom-cve-exclude-list = CVE-2023-53154 Resolved in v1.7.18
|
||||
|
||||
[submodule "components/mbedtls/mbedtls"]
|
||||
path = components/mbedtls/mbedtls
|
||||
|
||||
@@ -70,7 +70,6 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ^docs/sphinx-known-warnings\.txt$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-executables
|
||||
@@ -213,7 +212,7 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/espressif/conventional-precommit-linter
|
||||
rev: v1.7.0
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: conventional-precommit-linter
|
||||
stages: [commit-msg]
|
||||
|
||||
+2
-2
@@ -8,9 +8,9 @@ This document describes the compatibility between ESP-IDF releases and Espressif
|
||||
|
||||
NOTE: This document on release branches may be out-of-date. Check the [Compatibility file on master](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the most accurate information.
|
||||
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com.cn/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
|
||||
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com.cn/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
|
||||
## ESP-IDF Support for Different Chip Revisions
|
||||
|
||||
|
||||
@@ -118,8 +118,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32c5"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
# TODO: [ESPTOOL-1044] remove when stub supported
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32P4
|
||||
bool
|
||||
@@ -143,13 +141,11 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32h21"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32H4
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32h4"
|
||||
select FREERTOS_UNICORE # TODO: [ESP32H4] IDF-12319, need remove
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
@@ -233,7 +229,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
CONFIG_APP_BUILD_TYPE_RAM=y
|
||||
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||
CONFIG_LIBC_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP_DEBUG_STUBS_ENABLE=
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||
@@ -650,7 +646,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
choice COMPILER_ORPHAN_SECTIONS
|
||||
prompt "Orphan sections handling"
|
||||
default COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
default COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
depends on !IDF_TARGET_LINUX
|
||||
help
|
||||
If the linker finds orphan sections, it attempts to place orphan sections after sections of the same
|
||||
@@ -658,6 +654,11 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
That means that orphan sections could placed between sections defined in IDF linker scripts.
|
||||
This could lead to corruption of the binary image. Configure the linker action here.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
bool "Fail if orphan sections found"
|
||||
help
|
||||
Fails the link step with an error if orphan sections are detected.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
bool "Place with warning"
|
||||
help
|
||||
@@ -707,3 +708,4 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
|
||||
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
|
||||
- CONFIG_LIBC_PICOLIBC
|
||||
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
|
||||
|
||||
@@ -15,18 +15,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li
|
||||
|
||||
The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported.
|
||||
|
||||
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- |:--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|Chip | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | |
|
||||
|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-supported-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-preview-orange "preview"
|
||||
|
||||
+12
-13
@@ -15,19 +15,18 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux
|
||||
|
||||
下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。
|
||||
|
||||
芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- | :--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------------ |
|
||||
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|
||||
|芯片 | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | |
|
||||
|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: | :------------------------------------------------------------------------ |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
|
||||
|
||||
+13
-15
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
@@ -65,7 +65,6 @@ Revision: $Rev: 7745 $
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
@@ -85,7 +84,11 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
// The target core name
|
||||
#define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
#define SYSVIEW_CORE_NAME "xtensa"
|
||||
#elif CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
#define SYSVIEW_CORE_NAME "riscv"
|
||||
#endif
|
||||
|
||||
// Determine which timer to use as timestamp source
|
||||
#if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT
|
||||
@@ -102,6 +105,9 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
// Timer group timer divisor
|
||||
#define SYSVIEW_TIMER_DIV 2
|
||||
|
||||
// Frequency of the timestamp, using APB as GPTimer source clock
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
|
||||
|
||||
// GPTimer handle
|
||||
gptimer_handle_t s_sv_gptimer;
|
||||
|
||||
@@ -171,38 +177,30 @@ static void _cbSendSystemDesc(void) {
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static int SEGGER_SYSVIEW_TS_Init(void)
|
||||
static void SEGGER_SYSVIEW_TS_Init(void)
|
||||
{
|
||||
/* We only need to initialize something if we use Timer Group.
|
||||
* esp_timer and ccount can be used as is.
|
||||
*/
|
||||
#if TS_USE_TIMERGROUP
|
||||
// get clock source frequency
|
||||
uint32_t counter_src_hz = 0;
|
||||
ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(
|
||||
(soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT,
|
||||
ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz));
|
||||
gptimer_config_t config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = counter_src_hz / SYSVIEW_TIMER_DIV,
|
||||
.resolution_hz = SYSVIEW_TIMESTAMP_FREQ,
|
||||
};
|
||||
// pick any free GPTimer instance
|
||||
ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer));
|
||||
/* Start counting */
|
||||
gptimer_enable(s_sv_gptimer);
|
||||
gptimer_start(s_sv_gptimer);
|
||||
return config.resolution_hz;
|
||||
#else
|
||||
return SYSVIEW_TIMESTAMP_FREQ;
|
||||
#endif // TS_USE_TIMERGROUP
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_Conf(void) {
|
||||
U32 disable_evts = 0;
|
||||
|
||||
int timestamp_freq = SEGGER_SYSVIEW_TS_Init();
|
||||
SEGGER_SYSVIEW_Init(timestamp_freq, SYSVIEW_CPU_FREQ,
|
||||
SEGGER_SYSVIEW_TS_Init();
|
||||
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
|
||||
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
|
||||
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "esp_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
#define OTA_SLOT(i) (i & 0x0F)
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */
|
||||
@@ -539,6 +539,69 @@ static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the next OTA sequence number that will boot the given OTA slot.
|
||||
*
|
||||
* Based on the ESP-IDF OTA boot scheme, the system selects the OTA slot to boot by:
|
||||
* boot_slot = (seq - 1) % ota_app_count
|
||||
*
|
||||
* This function determines the required seq value that would cause the given ota_slot_idx
|
||||
* to be selected on next boot.
|
||||
*
|
||||
* @param current_seq Current active OTA sequence number
|
||||
* @param ota_slot_idx Target OTA slot index (0-based)
|
||||
* @param ota_app_count Total number of OTA slots
|
||||
*
|
||||
* @return New sequence number that will result in booting ota_slot_idx
|
||||
*/
|
||||
static uint32_t compute_ota_seq_for_target_slot(uint32_t current_seq, uint32_t ota_slot_idx, uint8_t ota_app_count)
|
||||
{
|
||||
if (ota_app_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* ESP-IDF stores OTA boot information in the OTA data partition, which consists of two sectors.
|
||||
* Each sector holds an esp_ota_select_entry_t structure: otadata[0] and otadata[1].
|
||||
* These structures record the OTA sequence number (ota_seq) used to determine the current boot partition.
|
||||
*
|
||||
* Boot selection logic:
|
||||
* - If both otadata[0].ota_seq and otadata[1].ota_seq are 0xFFFFFFFF (invalid), it is the initial state:
|
||||
* → Boot the factory app, if it exists.
|
||||
* → Otherwise, fall back to booting ota[0].
|
||||
*
|
||||
* - If both otadata entries have valid sequence numbers and CRCs:
|
||||
* → Choose the higher sequence number (max_seq).
|
||||
* → Determine the OTA partition for boot (or running partition) using:
|
||||
* running_ota_slot = (max_seq - 1) % ota_app_count
|
||||
* where ota_app_count is the total number of OTA app partitions.
|
||||
*
|
||||
* Example:
|
||||
* otadata[0].ota_seq = 4
|
||||
* otadata[1].ota_seq = 5
|
||||
* ota_app_count = 8 (available OTA slots: ota_0 to ota_7)
|
||||
* → max_seq = 5
|
||||
* → running slot = (5 - 1) % 8 = 4
|
||||
* → So ota_4 is currently running
|
||||
*
|
||||
* If you want to switch to boot a different OTA slot (e.g., ota_7):
|
||||
* → You need to compute a new sequence number such that:
|
||||
* (new_seq - 1) % ota_app_count == 7
|
||||
* while ensuring new_seq > current_seq.
|
||||
*
|
||||
* General formula:
|
||||
* x = current OTA slot ID
|
||||
* ota_slot_idx = desired OTA slot ID
|
||||
* seq = current ota_seq
|
||||
*
|
||||
* To find the next ota_seq that will boot ota_y, use:
|
||||
* new_seq = ((ota_slot_idx + 1) % ota_app_count) + ota_app_count * i;
|
||||
* // where i is the smallest non-negative integer such that new_seq > seq
|
||||
*/
|
||||
uint32_t i = 0;
|
||||
uint32_t base = (ota_slot_idx + 1) % ota_app_count;
|
||||
while (current_seq > (base + i * ota_app_count)) { i++; };
|
||||
return base + i * ota_app_count;
|
||||
}
|
||||
|
||||
uint8_t esp_ota_get_app_partition_count(void)
|
||||
{
|
||||
uint16_t ota_app_count = 0;
|
||||
@@ -549,6 +612,30 @@ uint8_t esp_ota_get_app_partition_count(void)
|
||||
return ota_app_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the OTA data partition to set the given OTA app subtype as the next boot target.
|
||||
*
|
||||
* ESP-IDF uses the OTA data partition to track which OTA app should boot.
|
||||
* This partition contains two entries (otadata[0] and otadata[1]), each storing an esp_ota_select_entry_t struct,
|
||||
* which includes the OTA sequence number (ota_seq).
|
||||
*
|
||||
* On boot, the chip determines the current running OTA slot using:
|
||||
* current_slot = (max(ota_seq) - 1) % ota_app_count
|
||||
*
|
||||
* This function updates the OTA data to switch the next boot to the partition with the given subtype.
|
||||
*
|
||||
* Behavior:
|
||||
* - If the currently selected OTA slot already matches the requested subtype,
|
||||
* only the state field is updated (e.g., to mark the app as newly downloaded).
|
||||
* - Otherwise, it calculates the next valid ota_seq that will cause the bootloader to select
|
||||
* the requested OTA slot on reboot, and writes it to the inactive OTA data sector.
|
||||
*
|
||||
* @param subtype The OTA partition subtype (e.g., ESP_PARTITION_SUBTYPE_APP_OTA_0, ..._OTA_1, ...)
|
||||
* @return
|
||||
* - ESP_OK if update was successful
|
||||
* - ESP_ERR_NOT_FOUND if OTA data partition not found
|
||||
* - ESP_ERR_INVALID_ARG if subtype is out of range
|
||||
*/
|
||||
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
@@ -558,42 +645,31 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
}
|
||||
|
||||
uint8_t ota_app_count = esp_ota_get_app_partition_count();
|
||||
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
|
||||
if (OTA_SLOT(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);
|
||||
int next_otadata;
|
||||
uint32_t new_seq;
|
||||
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++;
|
||||
uint32_t ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count;
|
||||
if (ota_slot == OTA_SLOT(subtype)) {
|
||||
// ota_data is already valid and points to the correct OTA slot.
|
||||
// So after reboot the requested partition will be selected for boot.
|
||||
// Only update the ota_state of the requested partition.
|
||||
next_otadata = active_otadata;
|
||||
new_seq = otadata[active_otadata].ota_seq;
|
||||
} else {
|
||||
next_otadata = (~active_otadata) & 1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
new_seq = compute_ota_seq_for_target_slot(otadata[active_otadata].ota_seq, OTA_SLOT(subtype), ota_app_count);
|
||||
}
|
||||
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);
|
||||
} 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);
|
||||
next_otadata = 0;
|
||||
new_seq = OTA_SLOT(subtype) + 1;
|
||||
}
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, new_seq, next_otadata, otadata_partition);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
static const char *TAG = "ota_test";
|
||||
|
||||
|
||||
/* @brief Checks and prepares the partition so that the factory app is launched after that.
|
||||
*/
|
||||
static void start_test(void)
|
||||
@@ -617,3 +618,51 @@ static void test_rollback3_1(void)
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. Updated partition invalidated after esp_ota_begin", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback3, test_rollback3, test_rollback3, test_rollback3_1);
|
||||
|
||||
static void test_rollback4(void)
|
||||
{
|
||||
uint8_t boot_count = get_boot_count_from_nvs();
|
||||
boot_count++;
|
||||
set_boot_count_in_nvs(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);
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
app_update();
|
||||
|
||||
// Do not reboot and call app_update again.
|
||||
// This will not change the running partition since we haven't rebooted.
|
||||
// The esp_rewrite_otadata() will update the otadata for the non-running partition only.
|
||||
app_update();
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
// The last call to esp_rewrite_otadata should have updated the otadata for the non-running partition only.
|
||||
// Therefore, calling esp_ota_get_state_partition on the running partition should succeed and not return ESP_ERR_NOT_FOUND
|
||||
const esp_partition_t* running_partition;
|
||||
running_partition = esp_ota_get_running_partition();
|
||||
esp_ota_img_states_t ota_state;
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(running_partition, &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_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
break;
|
||||
default:
|
||||
erase_ota_data();
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test esp_rewrite_otadata. Updated sequence number for non-running partition always", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback4, test_rollback4, test_rollback4);
|
||||
|
||||
@@ -20,7 +20,7 @@ TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n')
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -33,7 +33,7 @@ def test_app_update(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update_xip_psram(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -46,7 +46,7 @@ def test_app_update_xip_psram(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -59,7 +59,7 @@ def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3', 'esp32p4'], indirect=['target'])
|
||||
def test_app_update_with_rollback(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.recovery_bootloader
|
||||
|
||||
@@ -553,13 +553,12 @@ menu "Security features"
|
||||
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
|
||||
help
|
||||
Select the ECDSA key size. Three key sizes are supported depending upon on the target:
|
||||
Select the ECDSA key size. Two key sizes are supported
|
||||
|
||||
- 192 bit key using NISTP192 curve
|
||||
- 256 bit key using NISTP256 curve (Recommended)
|
||||
- 384 bit key using NISTP384 curve (Recommended)
|
||||
|
||||
The advantage of using 384 and 256 bit keys is the extra randomness which makes it difficult to be
|
||||
The advantage of using 256 bit key is the extra randomness which makes it difficult to be
|
||||
bruteforced compared to 192 bit key.
|
||||
At present, both key sizes are practically implausible to bruteforce.
|
||||
|
||||
@@ -571,10 +570,6 @@ menu "Security features"
|
||||
bool "Using ECC curve NISTP256 (Recommended)"
|
||||
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
|
||||
config SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bool "Using ECC curve NISTP384 (Recommended)"
|
||||
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
|
||||
endchoice
|
||||
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
@@ -965,24 +960,6 @@ menu "Security features"
|
||||
so that the bootloader would not need to enable secure boot and thus you could avoid its revocation
|
||||
strategy.
|
||||
|
||||
config SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA
|
||||
bool "Skip write-protection of SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH"
|
||||
default y if SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
default n
|
||||
depends on SOC_ECDSA_SUPPORT_CURVE_P384 && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
help
|
||||
If not set (default, recommended), on the first boot when Secure Boot is enabled for
|
||||
targets that support Secure Boot using ECDSA-P384, the bootloader will burn the write-protection bit of
|
||||
of SECURE_BOOT_SHA384_EN that could be shared by multiple other efuse bits like
|
||||
SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH / XTS_DPA_PSEUDO_LEVEL.
|
||||
|
||||
Once this efuse bit is write-protected you cannot update the values of the shared efuses, for example,
|
||||
the security strength value of XTS_DPA_PSEUDO_LEVEL or setting ECC_FORCE_CONST_TIME.
|
||||
|
||||
List of eFuses with the same write protection bit:
|
||||
|
||||
ESP32-C5: XTS_DPA_PSEUDO_LEVEL and ECC_FORCE_CONST_TIME
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -1066,11 +1043,10 @@ menu "Security features"
|
||||
ESP32-S3: DIS_ICACHE, DIS_DCACHE, DIS_DOWNLOAD_ICACHE, DIS_DOWNLOAD_DCACHE,
|
||||
DIS_FORCE_DOWNLOAD, DIS_USB_OTG, DIS_TWAI, DIS_APP_CPU, DIS_PAD_JTAG,
|
||||
DIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_JTAG, DIS_USB_SERIAL_JTAG, STRAP_JTAG_SEL, USB_PHY_SEL.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART
|
||||
bool "Encrypt contents upto app image length in app partition"
|
||||
bool "Encrypt only the app image that is present in the partition of type app"
|
||||
depends on SECURE_FLASH_ENC_ENABLED && !SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
default y
|
||||
help
|
||||
@@ -1099,9 +1075,8 @@ menu "Security features"
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
bool "Permanently enable XTS-AES's pseudo rounds function"
|
||||
default y if SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
default n
|
||||
depends on SECURE_FLASH_ENC_ENABLED && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
default y
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_RELEASE && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
help
|
||||
If set (default), the bootloader will permanently enable the XTS-AES peripheral's pseudo rounds function.
|
||||
Note: Enabling this config would burn an efuse.
|
||||
@@ -1114,12 +1089,6 @@ menu "Security features"
|
||||
The strength of the pseudo rounds functions can be configured to low, medium and high,
|
||||
each denoting the values that would be stored in the efuses field.
|
||||
By default the value to set to low.
|
||||
|
||||
It is recommended that the required strength of the pseudo rounds function should be set during the
|
||||
first boot itself. If your workflow needs to update the function's strength after the first boot,
|
||||
you should enable CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA to avoid write protecting this
|
||||
bit during the boot up for targets that support Secure Boot using ECDSA-P384.
|
||||
|
||||
You can configure the strength of the pseudo rounds functions according to your use cases,
|
||||
for example, increasing the strength would provide higher security but would slow down the
|
||||
flash encryption/decryption operations.
|
||||
@@ -1193,7 +1162,7 @@ menu "Security features"
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
|
||||
Note: Secure Download mode is not available for ESP32.
|
||||
Note: Secure Download mode is not available for ESP32 (includes revisions till ECO3).
|
||||
|
||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||
bool "UART ROM download mode (Enabled (not recommended))"
|
||||
|
||||
@@ -70,8 +70,6 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
set(scheme "ecdsa192")
|
||||
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
|
||||
set(scheme "ecdsa256")
|
||||
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS)
|
||||
set(scheme "ecdsa384")
|
||||
endif()
|
||||
fail_at_build_time(gen_secure_boot_signing_key
|
||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||
|
||||
@@ -67,13 +67,9 @@ idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
|
||||
idf_build_set_property(__OUTPUT_SDKCONFIG 0)
|
||||
# Define a property for the default linker script
|
||||
set(LD_DEFAULT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/main/ld/${IDF_TARGET}")
|
||||
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.ld" APPEND)
|
||||
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.rom.ld" APPEND)
|
||||
project(bootloader)
|
||||
if(CONFIG_ESP32P4_REV_MIN_300)
|
||||
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.rev3.ld")
|
||||
else()
|
||||
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.ld")
|
||||
endif()
|
||||
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
|
||||
|
||||
@@ -1,324 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* Simplified memory map for the bootloader.
|
||||
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||
*
|
||||
* ESP32-P4 ROM static data usage is as follows:
|
||||
* - 0x4ff296b8 - 0x4ff3afc0: Shared buffers, used in UART/USB/SPI download mode only
|
||||
* - 0x4ff3afc0 - 0x4ff3fba4: CPU1 stack, can be reclaimed as heap after RTOS startup
|
||||
* - 0x4ff3fba4 - 0x4ff40000: ROM .bss and .data (not easily reclaimable)
|
||||
*
|
||||
* The 2nd stage bootloader can take space up to the end of ROM shared
|
||||
* buffers area (0x4087c610).
|
||||
*/
|
||||
|
||||
/* We consider 0x4087c610 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
|
||||
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
|
||||
*/
|
||||
|
||||
/* These lengths can be adjusted, if necessary: */
|
||||
bootloader_usable_dram_end = 0x4ffbcfc0;
|
||||
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
|
||||
bootloader_dram_seg_len = 0x5000;
|
||||
bootloader_iram_loader_seg_len = 0x7000;
|
||||
bootloader_iram_seg_len = 0x2D00;
|
||||
|
||||
/* Start of the lower region is determined by region size and the end of the higher region */
|
||||
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
|
||||
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
|
||||
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
|
||||
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
|
||||
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
|
||||
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
|
||||
}
|
||||
|
||||
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
|
||||
* If you have changed something above and this assert fails:
|
||||
* 1. Check what the new value of bootloader_iram_loader_seg start is.
|
||||
* 2. Update the value in this assert.
|
||||
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32p4/memory.ld.in to the same value.
|
||||
*/
|
||||
ASSERT(bootloader_iram_loader_seg_start == 0x4FFAEFC0, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.iram_loader.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_loader_text_start = ABSOLUTE(.);
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_common_loader.*(.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_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
|
||||
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
|
||||
*libbootloader_support.a:bootloader_efuse.*(.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:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.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_encryption_secure_features.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:key_mgr_hal.*(.literal.key_mgr_hal_set_key_usage .text.key_mgr_hal_set_key_usage)
|
||||
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
|
||||
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
|
||||
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_loader_text_end = ABSOLUTE(.);
|
||||
} > iram_loader_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
} > iram_seg
|
||||
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.dram0.bootdesc : ALIGN(0x10)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||
} > dram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.dram0.rodata :
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
*(.sdata2 .sdata2.* .srodata .srodata.*)
|
||||
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
. = (. + 3) & ~ 3;
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
__init_array_end = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
/* Literals are also RO data. */
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} > dram_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram .iram.*) /* catch stray IRAM_ATTR */
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
/** CPU will try to prefetch up to 16 bytes of
|
||||
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||
* safe access to up to 16 bytes after the last real instruction, add
|
||||
* dummy bytes to ensure this
|
||||
*/
|
||||
. += 16;
|
||||
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
.riscv.attributes 0: { *(.riscv.attributes) }
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
/* DWARF 3 */
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* GNU DWARF 2 extensions */
|
||||
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
|
||||
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
|
||||
/* DWARF 4 */
|
||||
.debug_types 0 : { *(.debug_types) }
|
||||
/* DWARF 5 */
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_loclists 0 : { *(.debug_loclists) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_names 0 : { *(.debug_names) }
|
||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
||||
|
||||
.comment 0 : { *(.comment) }
|
||||
.note.GNU-stack 0: { *(.note.GNU-stack) }
|
||||
|
||||
/**
|
||||
* Discarding .rela.* sections results in the following mapping:
|
||||
* .rela.text.* -> .text.*
|
||||
* .rela.data.* -> .data.*
|
||||
* And so forth...
|
||||
*/
|
||||
/DISCARD/ : { *(.rela.*) }
|
||||
|
||||
/**
|
||||
* This section is not included in the binary image; it is only present in the ELF file.
|
||||
* It is used to keep certain symbols in the ELF file.
|
||||
*/
|
||||
.noload 0 (INFO) :
|
||||
{
|
||||
_noload_keep_in_elf_start = ABSOLUTE(.);
|
||||
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
|
||||
_noload_keep_in_elf_end = ABSOLUTE(.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* 0x4ffa96b8 ------------------> _dram0_0_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
|
||||
* | |
|
||||
* | |
|
||||
* 0x4ffbafc0 ------------------> __stack_sentry
|
||||
* | |
|
||||
* | | 2. Startup pro cpu stack (freed when IDF app is running)
|
||||
* | |
|
||||
* 0x4ffbcfc0 ------------------> __stack (pro cpu)
|
||||
* | |
|
||||
* | | Startup app cpu stack
|
||||
* | |
|
||||
* 0x4ffbefc0 ------------------> __stack_app (app cpu)
|
||||
* | |
|
||||
* | |
|
||||
* | | 3. Shared memory only used in startup code or nonos/early boot*
|
||||
* | | (can be freed when IDF runs)
|
||||
* | |
|
||||
* | |
|
||||
* 0x4ffbfbb0 ------------------> _dram0_rtos_reserved_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 4. Shared memory used in startup code and when IDF runs
|
||||
* | |
|
||||
* | |
|
||||
* 0x4ffbffa4 ------------------> _dram0_rtos_reserved_end
|
||||
* | |
|
||||
* 0x4ffbffc8 ------------------> _data_start_interface
|
||||
* | |
|
||||
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
|
||||
* | |
|
||||
* 0x4ffc0000 ------------------> _data_end_interface
|
||||
*/
|
||||
@@ -138,7 +138,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
extern bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const size_t len);
|
||||
extern bool esp_tee_flash_check_paddr_in_active_tee_part(size_t paddr);
|
||||
#endif
|
||||
|
||||
static const char *TAG = "bootloader_flash";
|
||||
@@ -524,7 +524,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
* by validating the address before proceeding.
|
||||
*/
|
||||
#if ESP_TEE_BUILD
|
||||
bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(dest_addr, size);
|
||||
bool addr_chk = esp_tee_flash_check_paddr_in_active_tee_part(dest_addr);
|
||||
if (addr_chk) {
|
||||
ESP_EARLY_LOGE(TAG, "bootloader_flash_write invalid dest_addr");
|
||||
return ESP_FAIL;
|
||||
@@ -578,7 +578,7 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
|
||||
esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
{
|
||||
#if ESP_TEE_BUILD
|
||||
bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(start_addr, size);
|
||||
bool addr_chk = esp_tee_flash_check_paddr_in_active_tee_part(start_addr);
|
||||
if (addr_chk) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "soc/pcr_reg.h"
|
||||
|
||||
static const char *TAG = "boot.esp32h21";
|
||||
@@ -80,7 +81,9 @@ void IRAM_ATTR bootloader_configure_spi_pins(int drv)
|
||||
|
||||
static void IRAM_ATTR bootloader_flash_clock_init(void)
|
||||
{
|
||||
// At this moment, BBPLL should be enabled, safe to switch MSPI clock source to PLL_F64M (default clock src) to raise speed
|
||||
// To raise the MSPI clock to 64MHz, needs to enable the 64MHz clock source, which is XTAL_X2_CLK
|
||||
// (FPGA image fixed MSPI0/1 clock to 64MHz)
|
||||
clk_ll_xtal_x2_enable();
|
||||
_mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_PLL_F64M);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,6 @@ static void bootloader_spi_flash_resume(void)
|
||||
|
||||
esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_mspi_clock();
|
||||
bootloader_init_flash_configure();
|
||||
|
||||
#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
|
||||
|
||||
@@ -215,10 +215,6 @@ bool esp_flash_encryption_cfg_verify_release_mode(void);
|
||||
* It burns:
|
||||
* - "disable encrypt in dl mode"
|
||||
* - set FLASH_CRYPT_CNT efuse to max
|
||||
*
|
||||
* In case of the targets that support the XTS-AES peripheral's pseudo rounds function,
|
||||
* this API would configure the pseudo rounds level efuse bit to level low if the efuse bit
|
||||
* is not set already.
|
||||
*/
|
||||
void esp_flash_encryption_set_release_mode(void);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#if !CONFIG_IDF_TARGET_LINUX
|
||||
#include "rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
||||
#error "internal sdkconfig error, secure boot should always enable all signature options"
|
||||
@@ -32,20 +33,12 @@ extern "C" {
|
||||
Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
#define ESP_SECURE_BOOT_DIGEST_LEN 48
|
||||
#else /* !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
|
||||
#define ESP_SECURE_BOOT_DIGEST_LEN 32
|
||||
#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
|
||||
|
||||
/* SHA-256 length of the public key digest */
|
||||
#define ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN 32
|
||||
|
||||
/* Length of the public key digest that is stored in efuses */
|
||||
#if CONFIG_IDF_TARGET_ESP32C2
|
||||
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN / 2
|
||||
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 16
|
||||
#else
|
||||
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN
|
||||
#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 32
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
|
||||
@@ -200,8 +193,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
/** @brief Verify the secure boot signature appended to some binary data in flash.
|
||||
*
|
||||
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
|
||||
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image digest
|
||||
* For ECDSA Scheme (Secure Boot V2) - ECDSA Verification of the SHA-256 / SHA-384 (in case of ECDSA-P384 secure boot key) image digest
|
||||
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
|
||||
*
|
||||
* Public key is compiled into the calling program in the ECDSA Scheme.
|
||||
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
|
||||
@@ -225,23 +217,6 @@ typedef struct {
|
||||
uint8_t signature[64];
|
||||
} esp_secure_boot_sig_block_t;
|
||||
|
||||
/** @brief Get the size of the secure boot signature block
|
||||
*
|
||||
* This is the size of the signature block appended to a signed image.
|
||||
*
|
||||
* @return Size of the secure boot signature block in bytes
|
||||
*/
|
||||
static inline uint32_t esp_secure_boot_sig_block_size(void)
|
||||
{
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
return sizeof(ets_secure_boot_signature_t);
|
||||
#elif defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
return sizeof(esp_secure_boot_sig_block_t);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
|
||||
*
|
||||
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
|
||||
@@ -261,13 +236,13 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
|
||||
|
||||
/** @brief Verify the secure boot signature block for Secure Boot V2.
|
||||
*
|
||||
* Performs RSA-PSS or ECDSA verification of the SHA-256 / SHA-384 image based on the public key
|
||||
* Performs RSA-PSS or ECDSA verification of the SHA-256 image based on the public key
|
||||
* in the signature block, compared against the public key digest stored in efuse.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param[in] sig_block Pointer to signature block data
|
||||
* @param[in] image_digest Pointer to 32/48 byte buffer holding SHA-256/SHA-384 hash.
|
||||
* @param[out] verified_digest Pointer to 32/48 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
* @param[in] image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
* @param[out] verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
|
||||
@@ -280,7 +255,7 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
|
||||
* Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN]; /* SHA of the public key components in the signature block */
|
||||
uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} esp_image_sig_public_key_digests_t;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,18 +12,15 @@
|
||||
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *bootloader_sha256_handle_t;
|
||||
typedef bootloader_sha256_handle_t bootloader_sha_handle_t;
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void);
|
||||
|
||||
@@ -31,14 +28,6 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data,
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest);
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA512
|
||||
bootloader_sha_handle_t bootloader_sha512_start(bool is384);
|
||||
|
||||
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len);
|
||||
|
||||
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest);
|
||||
#endif /* SOC_SHA_SUPPORT_SHA512 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -138,20 +138,6 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
|
||||
*/
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
|
||||
|
||||
/** @brief Generates the digest of the data between offset & offset+length.
|
||||
*
|
||||
* This function should be used when the size of the data is larger than 3.2MB.
|
||||
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-384
|
||||
* of the data in chunks of 3.2MB, considering the MMU capacity.
|
||||
*
|
||||
* @param[in] flash_offset Offset of the data in flash.
|
||||
* @param[in] len Length of data in bytes.
|
||||
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
|
||||
*
|
||||
* @return ESP_OK if secure boot digest is generated successfully.
|
||||
*/
|
||||
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "soc/pmu_reg.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C5
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#endif
|
||||
#include "esp_rom_sys.h"
|
||||
@@ -34,11 +34,7 @@ __attribute__((weak)) void bootloader_clock_configure(void)
|
||||
esp_rom_output_tx_wait_idle(0);
|
||||
|
||||
/* Set CPU to a higher certain frequency. Keep other clocks unmodified. */
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
int cpu_freq_mhz = 100;
|
||||
#else
|
||||
int cpu_freq_mhz = CPU_CLK_FREQ_MHZ_BTLD;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "soc/lpperi_reg.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
@@ -30,8 +31,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
@@ -49,9 +50,6 @@ void bootloader_random_enable(void)
|
||||
adc_ll_digi_set_trigger_interval(200);
|
||||
adc_ll_digi_trigger_enable();
|
||||
|
||||
SET_PERI_REG_MASK(LPPERI_RNG_CFG_REG, LPPERI_RNG_SAMPLE_ENABLE);
|
||||
REG_SET_FIELD(LPPERI_RNG_CFG_REG, LPPERI_RTC_TIMER_EN, 0x3);
|
||||
SET_PERI_REG_MASK(LPPERI_RNG_CFG_REG, LPPERI_RNG_TIMER_EN);
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -29,8 +31,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_2;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -29,8 +31,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -29,8 +31,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.atten = ADC_ATTEN_DB_2_5;
|
||||
|
||||
@@ -1,108 +1,72 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/adc_reg.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "soc/regi2c_saradc.h"
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "soc/lp_adc_reg.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp_rom_regi2c.h"
|
||||
#include "hal/regi2c_ctrl_ll.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
// TODO IDF-6497: once ADC API is supported, use the API instead of defining functions and constants here
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2166
|
||||
|
||||
typedef struct {
|
||||
int atten;
|
||||
int channel;
|
||||
} pattern_item;
|
||||
|
||||
typedef struct {
|
||||
pattern_item item[4];
|
||||
} pattern_table;
|
||||
|
||||
static void adc1_fix_initcode_set(uint32_t initcode_value)
|
||||
{
|
||||
uint32_t msb = initcode_value >> 8;
|
||||
uint32_t lsb = initcode_value & 0xff;
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
|
||||
}
|
||||
|
||||
//total 4 tables
|
||||
static void hpadc_sar1_pattern_table_cfg(unsigned int table_idx, pattern_table table)
|
||||
{
|
||||
uint32_t wdata = 0;
|
||||
wdata = (table.item[0].channel << 20 | table.item[0].atten << 18 |
|
||||
table.item[1].channel << 14|table.item[1].atten << 12 |
|
||||
table.item[2].channel << 8 |table.item[2].atten << 6 |
|
||||
table.item[3].channel << 2 |table.item[3].atten);
|
||||
WRITE_PERI_REG(ADC_SAR1_PATT_TAB1_REG + table_idx * 4, wdata);
|
||||
}
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
pattern_table sar1_table[4] = {};
|
||||
uint32_t pattern_len = 0;
|
||||
_adc_ll_reset_register();
|
||||
_adc_ll_enable_bus_clock(true);
|
||||
|
||||
SET_PERI_REG_MASK(HP_SYS_CLKRST_SOC_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_ADC_APB_CLK_EN);
|
||||
SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL23_REG, HP_SYS_CLKRST_REG_ADC_CLK_EN);
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
|
||||
adc_ll_digi_controller_clk_div(0, 0, 0);
|
||||
|
||||
SET_PERI_REG_MASK(RTCADC_MEAS1_MUX_REG, RTCADC_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG,PMU_XPD_PERIF_I2C);
|
||||
|
||||
uint32_t sar1_clk_div_num = GET_PERI_REG_BITS2((HP_SYS_CLKRST_PERI_CLK_CTRL24_REG),
|
||||
(HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_M),
|
||||
(HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_S));
|
||||
|
||||
SET_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE); //start force 1
|
||||
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_enable();
|
||||
#else
|
||||
regi2c_ctrl_ll_i2c_sar_periph_enable();
|
||||
#endif
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc1_fix_initcode_set(I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
// cfg pattern table
|
||||
sar1_table[0].item[0].channel = 10; //rand() % 6;
|
||||
sar1_table[0].item[0].atten = 3;
|
||||
sar1_table[0].item[1].channel = 10;
|
||||
sar1_table[0].item[1].atten = 3;
|
||||
sar1_table[0].item[2].channel = 10;
|
||||
sar1_table[0].item[2].atten = 3;
|
||||
sar1_table[0].item[3].channel = 10;
|
||||
sar1_table[0].item[3].atten = 3;
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
pattern_config.atten = ADC_ATTEN_DB_12;
|
||||
pattern_config.channel = ADC_CHANNEL_10;
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 1, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 2, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 3, pattern_config);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 1);
|
||||
|
||||
hpadc_sar1_pattern_table_cfg(0, sar1_table[0]);
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_SAR1_PATT_LEN, pattern_len, ADC_SAR1_PATT_LEN_S);
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
|
||||
adc_ll_digi_set_power_manage(ADC_UNIT_1, ADC_LL_POWER_SW_ON);
|
||||
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR1_FORCE, 3, ADC_XPD_SAR1_FORCE_S);
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR2_FORCE, 3, ADC_XPD_SAR2_FORCE_S);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_ENT_VDD_GRP1, 1);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_DTEST_VDD_GRP1, 0);
|
||||
|
||||
CLEAR_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE);
|
||||
SET_PERI_REG_MASK(ADC_CTRL2_REG, ADC_TIMER_EN);
|
||||
SET_PERI_REG_BITS(ADC_CTRL2_REG, ADC_TIMER_TARGET, sar1_clk_div_num * 25, ADC_TIMER_TARGET_S);
|
||||
|
||||
while (GET_PERI_REG_MASK(ADC_INT_RAW_REG, ADC_SAR1_DONE_INT_RAW) == 0) { }
|
||||
|
||||
SET_PERI_REG_MASK(ADC_INT_CLR_REG, ADC_APB_SARADC1_DONE_INT_CLR);
|
||||
adc_ll_digi_set_clk_div(15);
|
||||
adc_ll_digi_set_trigger_interval(100);
|
||||
adc_ll_digi_trigger_enable();
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_reset_pattern_table();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
|
||||
adc_ll_regi2c_adc_deinit();
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_disable();
|
||||
#endif
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_ENT_VDD_GRP1, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_DTEST_VDD_GRP1, 0);
|
||||
adc_ll_digi_controller_clk_div(4, 0, 0);
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,15 @@ bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
#if !SOC_SECURE_BOOT_V2_ECC
|
||||
/* For secure boot, the key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
|
||||
* While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
|
||||
* ets_sha_update handles it cleanly so we can safely remove the check:
|
||||
*/
|
||||
assert(data_len % 4 == 0);
|
||||
#endif /* SOC_SECURE_BOOT_V2_ECC */
|
||||
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
@@ -42,33 +51,6 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA512
|
||||
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
ets_sha_init(&ctx, is384 ? SHA2_384 : SHA2_512);
|
||||
return &ctx; // Meaningless non-NULL value
|
||||
}
|
||||
|
||||
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
if (digest == NULL) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
return;
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA512 */
|
||||
#else /* !CONFIG_IDF_TARGET_ESP32 */
|
||||
|
||||
#include "soc/dport_reg.h"
|
||||
@@ -180,7 +162,6 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
|
||||
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/sha512.h>
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void)
|
||||
{
|
||||
@@ -218,43 +199,4 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
|
||||
free(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA512
|
||||
bootloader_sha_handle_t bootloader_sha512_start(bool is384)
|
||||
{
|
||||
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
|
||||
if (!ctx) {
|
||||
return NULL;
|
||||
}
|
||||
mbedtls_sha512_init(ctx);
|
||||
int ret = mbedtls_sha512_starts(ctx, is384);
|
||||
if (ret != 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
|
||||
int ret = mbedtls_sha512_update(ctx, data, data_len);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
|
||||
if (digest != NULL) {
|
||||
int ret = mbedtls_sha512_finish(ctx, digest);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
mbedtls_sha512_free(ctx);
|
||||
free(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA512 */
|
||||
#endif /* !(NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM) */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/sha_types.h"
|
||||
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_image_format.h"
|
||||
@@ -1214,29 +1213,18 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
{
|
||||
|
||||
if (digest == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Handling firmware images larger than MMU capacity */
|
||||
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
|
||||
bootloader_sha_handle_t sha_handle = NULL;
|
||||
|
||||
if (type == SHA2_256) {
|
||||
sha_handle = bootloader_sha256_start();
|
||||
} else
|
||||
// Using SOC_ECDSA_SUPPORT_CURVE_P384 here so that there is no flash size impact in the case of existing targets like ESP32.
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
if (type == SHA2_384) {
|
||||
sha_handle = bootloader_sha512_start(true);
|
||||
} else
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
{
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
@@ -1246,14 +1234,7 @@ static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash
|
||||
uint32_t max_pages = (mmu_free_pages_count > mmu_page_offset) ? (mmu_free_pages_count - mmu_page_offset) : 0;
|
||||
if (max_pages == 0) {
|
||||
ESP_LOGE(TAG, "No free MMU pages are available");
|
||||
if (type == SHA2_256) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (type == SHA2_384) {
|
||||
bootloader_sha512_finish(sha_handle, NULL);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
uint32_t max_image_len;
|
||||
@@ -1264,51 +1245,15 @@ static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash
|
||||
|
||||
const void * image = bootloader_mmap(flash_offset, partial_image_len);
|
||||
if (image == NULL) {
|
||||
if (type == SHA2_256) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (type == SHA2_384) {
|
||||
bootloader_sha512_finish(sha_handle, NULL);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (type == SHA2_256) {
|
||||
bootloader_sha256_data(sha_handle, image, partial_image_len);
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (type == SHA2_384) {
|
||||
bootloader_sha512_data(sha_handle, image, partial_image_len);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
bootloader_sha256_data(sha_handle, image, partial_image_len);
|
||||
bootloader_munmap(image);
|
||||
|
||||
flash_offset += partial_image_len;
|
||||
len -= partial_image_len;
|
||||
}
|
||||
|
||||
if (type == SHA2_256) {
|
||||
bootloader_sha256_finish(sha_handle, digest);
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (type == SHA2_384) {
|
||||
bootloader_sha512_finish(sha_handle, digest);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
bootloader_sha256_finish(sha_handle, digest);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
{
|
||||
return bootloader_sha_flash_contents(SHA2_256, flash_offset, len, digest);
|
||||
}
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
{
|
||||
return bootloader_sha_flash_contents(SHA2_384, flash_offset, len, digest);
|
||||
}
|
||||
#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
@@ -167,7 +167,7 @@ esp_err_t bootloader_init(void)
|
||||
|
||||
#if XCHAL_ERRATUM_572
|
||||
uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
|
||||
WSR(MEMCTL, memctl);
|
||||
WSR(XT_REG_MEMCTL, memctl);
|
||||
#endif // XCHAL_ERRATUM_572
|
||||
|
||||
// In RAM_APP, memory will be initialized in `call_start_cpu0`
|
||||
|
||||
@@ -86,7 +86,6 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-8667 Remove this?
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
|
||||
#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND)
|
||||
ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
|
||||
uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
@@ -71,9 +71,12 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_err_t esp_flash_encryption_enable_key_mgr(void)
|
||||
{
|
||||
_key_mgr_ll_enable_bus_clock(true);
|
||||
_key_mgr_ll_enable_peripheral_clock(true);
|
||||
_key_mgr_ll_reset_register();
|
||||
// Enable and reset key manager
|
||||
// To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV
|
||||
int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
|
||||
key_mgr_ll_enable_bus_clock(true);
|
||||
key_mgr_ll_enable_peripheral_clock(true);
|
||||
key_mgr_ll_reset_register();
|
||||
|
||||
while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) {
|
||||
};
|
||||
|
||||
@@ -49,10 +49,6 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN);
|
||||
#endif
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
||||
|
||||
@@ -87,7 +87,6 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-9274 Remove this?
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
|
||||
#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND)
|
||||
ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
|
||||
uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
|
||||
@@ -36,7 +36,7 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
|
||||
#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND)
|
||||
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
|
||||
ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
|
||||
uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
|
||||
|
||||
@@ -37,6 +37,12 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
|
||||
ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifdef SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
if (ecdsa_ll_is_configurable_curve_supported()) {
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable hardware & software JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
|
||||
@@ -89,8 +89,7 @@ static inline void bootloader_hardware_init(void)
|
||||
CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_RFPLL);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_FORCE_RFPLL);
|
||||
|
||||
//TODO: [ESP32H21] IDF-11550, regi2c atomic clock
|
||||
regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
|
||||
ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifdef SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable hardware & software JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -53,9 +53,12 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_err_t esp_flash_encryption_enable_key_mgr(void)
|
||||
{
|
||||
_key_mgr_ll_enable_bus_clock(true);
|
||||
_key_mgr_ll_enable_peripheral_clock(true);
|
||||
_key_mgr_ll_reset_register();
|
||||
// Enable and reset key manager
|
||||
// To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV
|
||||
int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
|
||||
key_mgr_ll_enable_bus_clock(true);
|
||||
key_mgr_ll_enable_peripheral_clock(true);
|
||||
key_mgr_ll_reset_register();
|
||||
|
||||
while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) {
|
||||
};
|
||||
|
||||
@@ -144,7 +144,7 @@ esp_err_t bootloader_init(void)
|
||||
|
||||
#if XCHAL_ERRATUM_572
|
||||
uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
|
||||
WSR(MEMCTL, memctl);
|
||||
WSR(XT_REG_MEMCTL, memctl);
|
||||
#endif // XCHAL_ERRATUM_572
|
||||
|
||||
bootloader_ana_reset_config();
|
||||
|
||||
@@ -105,6 +105,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
static esp_err_t process_image_header(esp_image_metadata_t *data, uint32_t part_offset, bootloader_sha256_handle_t *sha_handle, bool do_verify, bool silent);
|
||||
static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint32_t part_offset, uint32_t part_len, bool do_verify, bool silent);
|
||||
static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data, bool silent, bool skip_check_checksum);
|
||||
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
|
||||
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
|
||||
@@ -159,8 +160,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
bool verify_sha;
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
/* used for anti-FI checks */
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0xEE };
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0x01 };
|
||||
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
|
||||
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
|
||||
#endif
|
||||
|
||||
if (data == NULL || part == NULL) {
|
||||
@@ -236,7 +237,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
"only verify signature in bootloader" into the macro so it's tested multiple times.
|
||||
*/
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) == 0);
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
|
||||
ESP_FAULT_ASSERT(is_bootloader(data->start_addr) || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#endif
|
||||
@@ -386,11 +387,6 @@ err:
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
#define ROM_STACK_START (SOC_ROM_STACK_START_REV2)
|
||||
#else
|
||||
#define ROM_STACK_START (SOC_ROM_STACK_START)
|
||||
#endif
|
||||
/* Check the region load_addr - load_end doesn't overlap any memory used by the bootloader, registers, or other invalid memory
|
||||
*/
|
||||
static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_t load_end, bool print_error, bool no_recurse)
|
||||
@@ -410,7 +406,7 @@ static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_
|
||||
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_inclusive_end_p)) { /* Writing to DRAM */
|
||||
/* Check if we're clobbering the stack */
|
||||
intptr_t sp = (intptr_t)esp_cpu_get_sp();
|
||||
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, ROM_STACK_START,
|
||||
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
|
||||
load_addr, load_end)) {
|
||||
reason = "overlaps bootloader stack";
|
||||
goto invalid;
|
||||
@@ -1027,14 +1023,43 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
static esp_err_t verify_signature_and_adjust_image_len(esp_image_metadata_t *data, uint32_t end, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
bootloader_munmap(padding);
|
||||
end = padded_end;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
|
||||
|
||||
// Use hash to verify signature block
|
||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
const void *sig_block;
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0); /* sanity check that these values start differently */
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
#if defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
@@ -1051,7 +1076,7 @@ static esp_err_t verify_signature_and_adjust_image_len(esp_image_metadata_t *dat
|
||||
ESP_LOGI(TAG, "Calculating simple hash to check for corruption...");
|
||||
const void *whole_image = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
||||
if (whole_image != NULL) {
|
||||
bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
|
||||
sha_handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sha_handle, whole_image, data->image_len - HASH_LEN);
|
||||
bootloader_munmap(whole_image);
|
||||
if (verify_simple_hash(sha_handle, data) != ESP_OK) {
|
||||
@@ -1072,64 +1097,6 @@ static esp_err_t verify_signature_and_adjust_image_len(esp_image_metadata_t *dat
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* SECURE_BOOT_CHECK_SIGNATURE */
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
(void) sha_handle;
|
||||
/* Re-calculating image digest using SHA384 */
|
||||
const void *image_data = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
||||
bootloader_sha_handle_t sha384_handle = bootloader_sha512_start(true);
|
||||
bootloader_sha512_data(sha384_handle, image_data, data->image_len - HASH_LEN);
|
||||
bootloader_munmap(image_data);
|
||||
#endif
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_data(sha384_handle, simple_hash, HASH_LEN);
|
||||
#else
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
#endif
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_data(sha384_handle, padding, padded_end - end);
|
||||
#else
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
#endif
|
||||
bootloader_munmap(padding);
|
||||
end = padded_end;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_finish(sha384_handle, image_digest);
|
||||
#else
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
#endif
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_digest, ESP_SECURE_BOOT_DIGEST_LEN, "Calculated secure boot hash");
|
||||
|
||||
return verify_signature_and_adjust_image_len(data, end, image_digest, verified_digest);
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -212,13 +212,8 @@ void esp_flash_encryption_set_release_mode(void)
|
||||
|
||||
#ifdef SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
|
||||
uint8_t xts_pseudo_level = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
|
||||
if (xts_pseudo_level == ESP_XTS_AES_PSEUDO_ROUNDS_DISABLE) {
|
||||
xts_pseudo_level = ESP_XTS_AES_PSEUDO_ROUNDS_LOW;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
}
|
||||
uint8_t xts_pseudo_level = ESP_XTS_AES_PSEUDO_ROUNDS_LOW;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -428,10 +428,6 @@ static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partit
|
||||
if (partition->type == PART_TYPE_APP && should_encrypt) {
|
||||
// Encrypt only the app image instead of encrypting the whole partition
|
||||
size = image_data.image_len;
|
||||
#if CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
// If secure update without secure boot, also encrypt the signature block
|
||||
size += esp_secure_boot_sig_block_size();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else if (partition->type == PART_TYPE_PARTITION_TABLE) {
|
||||
|
||||
@@ -427,27 +427,7 @@ bool esp_secure_boot_cfg_verify_release_mode(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not enabled Secure Boot using SHA-384 mode (set SECURE_BOOT_SHA384_EN->1)");
|
||||
}
|
||||
#else
|
||||
/* When using Secure Boot with SHA-384, the efuse bit representing Secure Boot with SHA-384 would already be programmed.
|
||||
* But in the case of the existing Secure Boot V2 schemes using SHA-256, the efuse bit representing
|
||||
* Secure Boot with SHA-384 needs to be write-protected, so that an attacker cannot perform a denial-of-service
|
||||
* attack by changing the existing secure boot mode using SHA-256 to SHA-384.
|
||||
*/
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not write-protected secure boot using SHA-384 mode (set WR_DIS_SECURE_BOOT_SHA384_EN->1)");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
secure = (num_keys != 0);
|
||||
result &= secure;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -69,21 +69,16 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
*/
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%" PRIx32 " (sig block offset 0x%x)", flash_offset, sig_block_addr);
|
||||
|
||||
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
ret = bootloader_sha384_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
#else
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
#endif
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||
return ret;
|
||||
@@ -134,7 +129,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
}
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN);
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
|
||||
@@ -322,7 +317,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < tee_key_digests.num_digests; j++) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], tee_key_digests.key_digests[j], ESP_SECURE_BOOT_KEY_DIGEST_LEN)) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], tee_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "TEE key(%d) matches with bootloader key(%d).", j, i);
|
||||
tee_match = true;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ static esp_err_t calculate_image_public_key_digests(bool verify_image_digest, bo
|
||||
}
|
||||
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = img_metadata.start_addr + ALIGN_UP(img_metadata.image_len, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%"PRIu32" (sig block offset 0x%u)", img_metadata.start_addr, sig_block_addr);
|
||||
@@ -81,11 +81,7 @@ static esp_err_t calculate_image_public_key_digests(bool verify_image_digest, bo
|
||||
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
if (verify_image_digest) {
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
ret = bootloader_sha384_flash_contents(img_metadata.start_addr, sig_block_addr - img_metadata.start_addr, image_digest);
|
||||
#else
|
||||
ret = bootloader_sha256_flash_contents(img_metadata.start_addr, sig_block_addr - img_metadata.start_addr, image_digest);
|
||||
#endif
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||
return ret;
|
||||
@@ -122,7 +118,7 @@ static esp_err_t calculate_image_public_key_digests(bool verify_image_digest, bo
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
}
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[public_key_digests->num_digests], key_digest, ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN);
|
||||
memcpy((void *)public_key_digests->key_digests[public_key_digests->num_digests], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
}
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
@@ -188,19 +184,14 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t digest[ESP_SECURE_BOOT_KEY_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_KEY_DIGEST_LEN] = {0};
|
||||
|
||||
/* Rounding off length to the upper 4k boundary */
|
||||
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%"PRIx32" length 0x%"PRIx32, src_addr, length);
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
err = bootloader_sha384_flash_contents(src_addr, padded_length, digest);
|
||||
#else
|
||||
err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
#endif
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%"PRIx32", 0x%"PRIx32, src_addr, padded_length);
|
||||
return err;
|
||||
@@ -212,7 +203,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, NULL);
|
||||
err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
@@ -227,11 +218,9 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
|
||||
{
|
||||
bool any_trusted_key = false;
|
||||
|
||||
if (verified_digest != NULL) {
|
||||
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
|
||||
during boot-time verification. */
|
||||
memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
}
|
||||
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
|
||||
during boot-time verification. */
|
||||
memset(verified_digest, 0, ESP_SECURE_BOOT_KEY_DIGEST_LEN);
|
||||
|
||||
esp_image_sig_public_key_digests_t trusted = {0};
|
||||
|
||||
@@ -248,7 +237,7 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
|
||||
#endif
|
||||
|
||||
for (unsigned app_blk_idx = 0; app_blk_idx < secure_boot_num_blocks; app_blk_idx++) {
|
||||
uint8_t app_blk_digest[ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN] = { 0 };
|
||||
uint8_t app_blk_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 };
|
||||
const ets_secure_boot_sig_block_t *app_blk = &sig_block->block[app_blk_idx];
|
||||
const ets_secure_boot_sig_block_t *trusted_block = NULL;
|
||||
|
||||
|
||||
+1
-7
@@ -26,7 +26,6 @@ static const char* TAG = "secure_boot_v2";
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
|
||||
|
||||
@@ -35,12 +34,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%" PRIx32 " length 0x%" PRIx32, src_addr, length);
|
||||
|
||||
/* Calculate digest of main image */
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
err = bootloader_sha384_flash_contents(src_addr, padded_length, digest);
|
||||
#else
|
||||
err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
#endif
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%" PRIx32 ", 0x%" PRIx32, src_addr, padded_length);
|
||||
return err;
|
||||
|
||||
@@ -4,3 +4,7 @@ components/bootloader_support/test_apps/rtc_custom_section:
|
||||
enable:
|
||||
- if: SOC_RTC_MEM_SUPPORTED == 1
|
||||
reason: this feature is supported on chips that have RTC memory
|
||||
disable:
|
||||
- if: IDF_TARGET == "esp32h21"
|
||||
temporary: true
|
||||
reason: IDF-11534
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
+50
-129
@@ -29,7 +29,6 @@ set(common_include_dirs
|
||||
|
||||
set(ble_mesh_include_dirs
|
||||
"esp_ble_mesh/common/include"
|
||||
"esp_ble_mesh/common/tinycrypt/include"
|
||||
"esp_ble_mesh/core"
|
||||
"esp_ble_mesh/core/include"
|
||||
"esp_ble_mesh/core/storage"
|
||||
@@ -42,6 +41,10 @@ set(ble_mesh_include_dirs
|
||||
"esp_ble_mesh/api"
|
||||
)
|
||||
|
||||
set(ble_mesh_tinycrypt_dirs
|
||||
"esp_ble_mesh/common/tinycrypt/include"
|
||||
)
|
||||
|
||||
set(ble_mesh_v11_include_dirs
|
||||
"esp_ble_mesh/lib/include"
|
||||
"esp_ble_mesh/v1.1/api/core/include"
|
||||
@@ -134,45 +137,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"common/osi/semaphore.c"
|
||||
"porting/mem/bt_osi_mem.c"
|
||||
"common/ble_log/ble_log_spi_out.c"
|
||||
"common/ble_log/ble_log_uhci_out.c"
|
||||
)
|
||||
|
||||
# BLE Log Module
|
||||
if(CONFIG_BLE_LOG_ENABLED)
|
||||
# Core source files
|
||||
list(APPEND srcs
|
||||
common/ble_log/src/ble_log.c
|
||||
common/ble_log/src/ble_log_lbm.c
|
||||
common/ble_log/src/ble_log_rt.c
|
||||
common/ble_log/src/ble_log_util.c
|
||||
)
|
||||
|
||||
# Includes
|
||||
list(APPEND include_dirs
|
||||
common/ble_log/include
|
||||
)
|
||||
|
||||
# Private includes
|
||||
list(APPEND priv_include_dirs
|
||||
common/ble_log/src/internal_include
|
||||
common/ble_log/src/internal_include/prph
|
||||
)
|
||||
|
||||
# Timestamp synchronization extension
|
||||
if(CONFIG_BLE_LOG_TS_ENABLED)
|
||||
list(APPEND srcs common/ble_log/src/ble_log_ts.c)
|
||||
endif()
|
||||
|
||||
# Peripheral interface implementation
|
||||
if(CONFIG_BLE_LOG_PRPH_DUMMY)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_dummy.c)
|
||||
elseif(CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_spi_master_dma.c)
|
||||
elseif(CONFIG_BLE_LOG_PRPH_UART_DMA)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_uart_dma.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Host Bluedroid
|
||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||
|
||||
@@ -192,6 +158,9 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/bta/sys/include
|
||||
host/bluedroid/device/include
|
||||
host/bluedroid/hci/include
|
||||
host/bluedroid/external/sbc/decoder/include
|
||||
host/bluedroid/external/sbc/encoder/include
|
||||
host/bluedroid/external/sbc/plc/include
|
||||
host/bluedroid/btc/profile/esp/include
|
||||
host/bluedroid/btc/profile/std/a2dp/include
|
||||
host/bluedroid/btc/profile/std/include
|
||||
@@ -349,6 +318,29 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/device/bdaddr.c"
|
||||
"host/bluedroid/device/controller.c"
|
||||
"host/bluedroid/device/interop.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/alloc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitalloc-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitalloc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitstream-decode.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-oina.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-private.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/dequant.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/framing-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/framing.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/oi_codec_version.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-8-generated.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-dct8.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-sbc.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_analysis.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_dct.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_dct_coeffs.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_coeffs.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_packing.c"
|
||||
"host/bluedroid/external/sbc/plc/sbc_plc.c"
|
||||
"host/bluedroid/hci/hci_audio.c"
|
||||
"host/bluedroid/hci/hci_hal_h4.c"
|
||||
"host/bluedroid/hci/hci_layer.c"
|
||||
@@ -485,38 +477,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/api/esp_ble_cte_api.c")
|
||||
endif()
|
||||
|
||||
if((CONFIG_BT_A2DP_ENABLE AND NOT CONFIG_BT_A2DP_USE_EXTERNAL_CODEC) OR
|
||||
(CONFIG_BT_HFP_ENABLE AND CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI AND NOT CONFIG_BT_HFP_USE_EXTERNAL_CODEC))
|
||||
list(APPEND priv_include_dirs
|
||||
host/bluedroid/external/sbc/decoder/include
|
||||
host/bluedroid/external/sbc/encoder/include
|
||||
host/bluedroid/external/sbc/plc/include)
|
||||
|
||||
list(APPEND srcs "host/bluedroid/external/sbc/decoder/srce/alloc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitalloc-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitalloc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/bitstream-decode.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-oina.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-private.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/decoder-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/dequant.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/framing-sbc.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/framing.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/oi_codec_version.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-8-generated.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-dct8.c"
|
||||
"host/bluedroid/external/sbc/decoder/srce/synthesis-sbc.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_analysis.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_dct.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_dct_coeffs.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_enc_coeffs.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c"
|
||||
"host/bluedroid/external/sbc/encoder/srce/sbc_packing.c"
|
||||
"host/bluedroid/external/sbc/plc/sbc_plc.c")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(CONFIG_BLE_MESH)
|
||||
@@ -543,21 +503,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/utils.c"
|
||||
"esp_ble_mesh/common/atomic.c"
|
||||
"esp_ble_mesh/common/buf.c"
|
||||
"esp_ble_mesh/common/common.c"
|
||||
@@ -608,6 +553,26 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/models/server/state_binding.c"
|
||||
"esp_ble_mesh/models/server/state_transition.c"
|
||||
"esp_ble_mesh/models/server/time_scene_server.c")
|
||||
|
||||
if(NOT CONFIG_BLE_MESH_USE_UNIFIED_CRYPTO)
|
||||
list(APPEND include_dirs ${ble_mesh_tinycrypt_dirs})
|
||||
list(APPEND srcs
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/utils.c")
|
||||
endif()
|
||||
if(CONFIG_BLE_MESH_V11_SUPPORT)
|
||||
list(APPEND include_dirs ${ble_mesh_v11_include_dirs})
|
||||
|
||||
@@ -746,7 +711,6 @@ if(CONFIG_BT_ENABLED)
|
||||
host/nimble/nimble/nimble/host/util/include
|
||||
host/nimble/nimble/nimble/host/store/ram/include
|
||||
host/nimble/nimble/nimble/host/store/config/include
|
||||
host/nimble/nimble/nimble/host/services/ras/include
|
||||
)
|
||||
|
||||
list(APPEND srcs "host/nimble/nimble/nimble/transport/src/transport.c"
|
||||
@@ -767,8 +731,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c"
|
||||
"host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c"
|
||||
"host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c"
|
||||
"host/nimble/nimble/nimble/host/services/ras/src/ble_svc_ras.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_cs.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_conn.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_store_util.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_sm.c"
|
||||
@@ -822,13 +784,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/nimble/host/src/ble_eatt.c"
|
||||
)
|
||||
|
||||
if(CONFIG_BT_NIMBLE_ISO)
|
||||
list(APPEND srcs
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_iso_hci.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_iso.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_CONTROLLER_DISABLED AND CONFIG_BT_NIMBLE_TRANSPORT_UART)
|
||||
list(APPEND srcs
|
||||
"host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c"
|
||||
@@ -957,22 +912,6 @@ set(bt_priv_requires
|
||||
esp_gdbstub
|
||||
)
|
||||
|
||||
if(CONFIG_BLE_COMPRESSED_LOG_ENABLE)
|
||||
set(BT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
# When log compression is enabled, selected logs are replaced
|
||||
# by auto-generated macros that emit pre-encoded data.
|
||||
# This eliminates the original format strings, reducing firmware size and
|
||||
# removing runtime formatting overhead, so logs are produced faster and
|
||||
# with less system impact.
|
||||
add_subdirectory(common/ble_log/extension/log_compression)
|
||||
if(LOG_COMPRESSION_TARGET)
|
||||
set(srcs ${LOG_COMPRESS_SRCS})
|
||||
set(include_dirs ${LOG_COMPRESS_INCLUDE_DIRS})
|
||||
else()
|
||||
list(APPEND include_dirs ${LOG_COMPRESS_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
@@ -980,12 +919,6 @@ idf_component_register(SRCS "${srcs}"
|
||||
PRIV_REQUIRES "${bt_priv_requires}"
|
||||
LDFRAGMENTS "${ldscripts}")
|
||||
|
||||
if(CONFIG_BLE_COMPRESSED_LOG_ENABLE)
|
||||
if(LOG_COMPRESSION_TARGET)
|
||||
add_dependencies(${COMPONENT_LIB} ${LOG_COMPRESSION_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
@@ -1013,18 +946,6 @@ if(CONFIG_BT_ENABLED)
|
||||
if(CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_panic_handler")
|
||||
endif()
|
||||
if(CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||
endif()
|
||||
if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT)
|
||||
if(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT EQUAL 0)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_IDF_TARGET_ESP32C6)
|
||||
add_prebuilt_library(libble_app
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a"
|
||||
|
||||
@@ -6,10 +6,6 @@ config BT_ALARM_MAX_NUM
|
||||
This option decides the maximum number of alarms which
|
||||
could be used by Bluetooth host.
|
||||
|
||||
menu "BLE Log"
|
||||
source "$IDF_PATH/components/bt/common/ble_log/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
bool "Output ble logs to SPI bus (Experimental)"
|
||||
default n
|
||||
@@ -31,21 +27,6 @@ config BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
help
|
||||
Enable logging of HCI packets to the SPI bus when BLE SPI log output is enabled.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HCI_BUF_SIZE
|
||||
int "SPI transaction buffer size for HCI logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for HCI logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HCI_TASK_CNT
|
||||
int "HCI task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
default 1
|
||||
help
|
||||
HCI task count
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
bool "Enable Host log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
@@ -54,21 +35,6 @@ config BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
This configuration applies to the logs of both Bluedroid Host and NimBLE Host.
|
||||
When BLE SPI log output is enabled, this option allows host logs to be transmitted via SPI.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_BUF_SIZE
|
||||
int "SPI transaction buffer size for host logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for host logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_TASK_CNT
|
||||
int "Host task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
default 2
|
||||
help
|
||||
Host task count.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
bool "Enable Controller log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
@@ -136,6 +102,13 @@ config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
|
||||
help
|
||||
GPIO number of SYNC IO
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_TS_SYNC_SLEEP_SUPPORT
|
||||
bool "Enable ble log & logic analyzer log time sync sleep support"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable ble log & logic analyzer log time sync sleep support
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
|
||||
bool "Enable periodic buffer flush out"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
@@ -165,99 +138,3 @@ config BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE
|
||||
help
|
||||
SPI transaction buffer size for LE Audio logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LE_AUDIO_TASK_CNT
|
||||
int "LE audio task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
|
||||
default 1
|
||||
help
|
||||
LE audio task count
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
bool "Enable BLE mesh log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable BLE mesh log output to SPI
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_BUF_SIZE
|
||||
int "SPI transaction buffer size for BLE mesh logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for BLE mesh logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_TASK_CNT
|
||||
int "Mesh task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
default 3
|
||||
help
|
||||
Mesh task count
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
bool "Output ble logs via UHCI (UART DMA) driver (Experimental)"
|
||||
default n
|
||||
help
|
||||
Output ble logs via UHCI (UART DMA) driver
|
||||
On enable, BT_BLE_LOG_UHCI_OUT_UART_PORT would be reinited with
|
||||
BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE as new baud rate and
|
||||
BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX as new UART Tx IO
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
int "UART port connected to UHCI controller"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 0
|
||||
help
|
||||
UART port connected to UHCI controller
|
||||
If UART port 0 is selected, UART VFS Driver, UART ROM Driver
|
||||
and UART Driver output would be redirected to BLE Log UHCI Out
|
||||
to solve UART Tx FIFO multi-task access issue
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_TASK_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer task logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer task logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_ISR_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer ISR logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer ISR logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_HCI_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer HCI logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer HCI logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
bool "Enable to init UART port"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable to init UART port
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE
|
||||
int "Baud rate for BT_BLE_LOG_UHCI_OUT_UART_PORT"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
default 3000000
|
||||
help
|
||||
Baud rate for BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX
|
||||
int "IO number for UART TX port"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
default 0
|
||||
help
|
||||
IO number for UART TX port
|
||||
|
||||
config BT_LE_USED_MEM_STATISTICS_ENABLED
|
||||
bool "Enable used memory statistics"
|
||||
default n
|
||||
help
|
||||
Used in internal tests only. Enable used memory statistics.
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
config BLE_LOG_ENABLED
|
||||
bool "Enable BLE Log Module (Experimental)"
|
||||
default n
|
||||
help
|
||||
Enable BLE Log Module
|
||||
|
||||
if BLE_LOG_ENABLED
|
||||
config BLE_LOG_LBM_TRANS_SIZE
|
||||
int "Buffer size for each peripheral transport"
|
||||
default 512
|
||||
help
|
||||
There're 2 log buffer managers (LBMs) with compare-and-swap
|
||||
(CAS) protection, 1 LBM with FreeRTOS mutex protection, 1 LBM
|
||||
without protection for critical section. Each LBM is managing
|
||||
2 ping-pong buffers, which means there will be 4 * 2 *
|
||||
BLE_LOG_LBM_TRANS_SIZE bytes buffer allocated
|
||||
|
||||
config BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||
int "Count of log buffer managers with atomic lock protection for task context"
|
||||
default 2
|
||||
help
|
||||
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||
lock protection are created, the better the logging performance will be.
|
||||
|
||||
config BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||
int "Count of log buffer managers with atomic lock protection for ISR context"
|
||||
default 1
|
||||
help
|
||||
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||
lock protection are created, the more ISRs can nest.
|
||||
|
||||
config BLE_LOG_IS_ESP_CONTROLLER
|
||||
bool "Current BLE Controller is ESP BLE Controller"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
depends on SOC_ESP_NIMBLE_CONTROLLER
|
||||
default y
|
||||
select BT_LE_CONTROLLER_LOG_ENABLED
|
||||
select BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
|
||||
select BLE_LOG_LL_ENABLED
|
||||
help
|
||||
Current BLE Controller is ESP BLE Controller
|
||||
|
||||
config BLE_LOG_IS_ESP_LEGACY_CONTROLLER
|
||||
bool "Current BLE Controller is ESP BLE Legacy Controller"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
depends on !SOC_ESP_NIMBLE_CONTROLLER
|
||||
depends on BT_CTRL_RUN_IN_FLASH_ONLY
|
||||
default y
|
||||
select BT_CTRL_LE_LOG_EN
|
||||
select BLE_LOG_LL_ENABLED
|
||||
help
|
||||
Current BLE Controller is ESP BLE Legacy Controller
|
||||
|
||||
config BLE_LOG_LL_ENABLED
|
||||
bool "Enable BLE Log for Link Layer"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable BLE Log for Link Layer
|
||||
|
||||
config BLE_LOG_LBM_LL_TRANS_SIZE
|
||||
int "Buffer size for each peripheral transport of Link Layer LBM"
|
||||
depends on BLE_LOG_LL_ENABLED
|
||||
default 1024
|
||||
help
|
||||
There're 2 Link Layer dedicated log buffer managers (LBMs) with
|
||||
compare-and-swap (CAS) protection. Each LBM is managing 2 ping-
|
||||
pong buffers, which means there will be additional 2 * 2 *
|
||||
BLE_LOG_LBM_LL_TRANS_SIZE bytes buffer allocated
|
||||
|
||||
config BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||
bool "Enable payload checksum for BLE Log data integrity check"
|
||||
default y
|
||||
help
|
||||
Checksum is the default method for BLE Log data integrity check,
|
||||
but for targets with slow CPU speed, it may cause significant system
|
||||
performance decrease; a compromise could be made to balance the
|
||||
realtime performance and log data integrity, which is calculating the
|
||||
checksum of frame head and payload all together by default, or only
|
||||
calculate the checksum of frame head to minimize performance decrease
|
||||
|
||||
config BLE_LOG_ENH_STAT_ENABLED
|
||||
bool "Enable enhanced statistics for BLE Log"
|
||||
default n
|
||||
help
|
||||
Enable enhanced statistics for written/lost frame/bytes count, which may
|
||||
cost additional ~100kB memory
|
||||
|
||||
config BLE_LOG_TS_ENABLED
|
||||
bool "Enable BLE Log Timestamp Synchronization (TS)"
|
||||
default n
|
||||
help
|
||||
Enable BLE Log TS with external logging module
|
||||
|
||||
config BLE_LOG_SYNC_IO_NUM
|
||||
int "GPIO number for Timestamp Synchronization (TS) toggle output"
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default 0
|
||||
help
|
||||
GPIO number for TS toggle output
|
||||
|
||||
choice BLE_LOG_PRPH_CHOICE
|
||||
prompt "BLE Log peripheral choice"
|
||||
default BLE_LOG_PRPH_DUMMY
|
||||
help
|
||||
Choose BLE Log peripheral
|
||||
|
||||
config BLE_LOG_PRPH_DUMMY
|
||||
bool "Dummy transport"
|
||||
help
|
||||
Dummy transport (dump only)
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||
bool "Utilize SPI master DMA driver as transport"
|
||||
depends on SOC_GPSPI_SUPPORTED
|
||||
help
|
||||
Utilize SPI master DMA driver as transport
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA
|
||||
bool "Utilize UART DMA driver as transport"
|
||||
depends on SOC_UHCI_SUPPORTED
|
||||
help
|
||||
Utilize UART DMA driver as transport
|
||||
endchoice
|
||||
|
||||
if BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM
|
||||
int "GPIO number of MOSI port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of MOSI port for SPI master DMA transport
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM
|
||||
int "GPIO number of SCLK port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of SCLK port for SPI master DMA transport
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM
|
||||
int "GPIO number of CS port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of CS port for SPI master DMA transport
|
||||
endif
|
||||
|
||||
if BLE_LOG_PRPH_UART_DMA
|
||||
config BLE_LOG_PRPH_UART_DMA_PORT
|
||||
int "UART port number for UART DMA transport"
|
||||
default 0
|
||||
help
|
||||
UART port number for UART DMA
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA_BAUD_RATE
|
||||
int "Baud rate of UART port for UART DMA transport"
|
||||
default 921600
|
||||
help
|
||||
Determine the baud rate of UART port
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA_TX_IO_NUM
|
||||
int "GPIO number for UART TX"
|
||||
default 0
|
||||
help
|
||||
GPIO number for UART TX
|
||||
endif
|
||||
|
||||
menu "Settings of BLE Log Compression"
|
||||
source "$IDF_PATH/components/bt/common/ble_log/extension/log_compression/Kconfig.in"
|
||||
endmenu
|
||||
endif
|
||||
@@ -1,450 +0,0 @@
|
||||
# BLE Log Module
|
||||
|
||||
A high-performance, modular Bluetooth logging system that provides real-time log capture and transmission capabilities for the ESP-IDF Bluetooth stack.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Architecture Design](#architecture-design)
|
||||
- [Features](#features)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Configuration Options](#configuration-options)
|
||||
- [API Reference](#api-reference)
|
||||
- [Usage Examples](#usage-examples)
|
||||
- [Performance & Memory Optimization](#performance--memory-optimization)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Important Notes](#important-notes)
|
||||
|
||||
## Overview
|
||||
|
||||
The BLE Log module is an efficient logging system specifically designed for the ESP-IDF Bluetooth stack, supporting real-time log capture, multi-source log collection, and various transmission methods. This module has been refactored with a modular design, featuring high-concurrency processing capabilities and low-latency characteristics.
|
||||
|
||||
### Main Components
|
||||
|
||||
- **BLE Log Core** (`ble_log.c`): Module core responsible for initialization and coordination of sub-modules
|
||||
- **Runtime Manager** (`ble_log_rt.c`): Runtime task management for log transmission scheduling
|
||||
- **Log Buffer Manager** (`ble_log_lbm.c`): Log buffer management supporting multiple locking mechanisms
|
||||
- **Peripheral Interface** (`ble_log_prph_*.c`): Peripheral interface abstraction layer supporting various transmission methods
|
||||
- **Timestamp Sync** (`ble_log_ts.c`): Timestamp synchronization module
|
||||
- **Utility** (`ble_log_util.c`): Common utility functions
|
||||
|
||||
## Features
|
||||
|
||||
### Core Functionality
|
||||
|
||||
- **Multi-source Log Collection**: Supports multiple log sources including Link Layer, Host, HCI, etc.
|
||||
- **High Concurrency Processing**: Uses atomic and spin lock mechanisms for multi-task concurrent writing
|
||||
- **Real-time Transmission**: Asynchronous transmission mechanism based on FreeRTOS tasks
|
||||
- **Data Integrity**: Configurable checksum mechanism ensures data integrity
|
||||
- **Memory Optimization**: Ping-pong buffer design minimizes memory usage
|
||||
|
||||
### Advanced Features
|
||||
|
||||
- **Timestamp Synchronization**: Supports timestamp synchronization with external devices (optional)
|
||||
- **Enhanced Statistics**: Detailed logging statistics including loss rate analysis (optional)
|
||||
- **Link Layer Integration**: Deep integration with ESP-IDF Bluetooth Link Layer
|
||||
- **Multiple Transmission Methods**: Supports SPI DMA, UART DMA, and Dummy transmission
|
||||
|
||||
### Performance Features
|
||||
|
||||
- **IRAM Optimization**: Critical path code runs in IRAM ensuring low latency
|
||||
- **Lock-free Design**: Most operations use atomic operations reducing lock contention
|
||||
- **Buffer Reuse**: Intelligent buffer management reduces memory allocation overhead
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Enable Module
|
||||
|
||||
Enable the BLE Log module in `menuconfig`:
|
||||
|
||||
```
|
||||
Component config → Bluetooth → Enable BLE Log Module (Experimental)
|
||||
```
|
||||
|
||||
### 2. Basic Configuration
|
||||
|
||||
```c
|
||||
#include "ble_log.h"
|
||||
|
||||
void app_main() {
|
||||
// Initialize BLE Log module
|
||||
if (!ble_log_init()) {
|
||||
ESP_LOGE(TAG, "Failed to initialize BLE Log");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write log data
|
||||
uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||
|
||||
// Force flush buffers
|
||||
ble_log_flush();
|
||||
|
||||
// Cleanup resources
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Link Layer Integration
|
||||
|
||||
When `CONFIG_BLE_LOG_LL_ENABLED` is enabled, Link Layer logs are automatically integrated:
|
||||
|
||||
```c
|
||||
// Link Layer logs will automatically call this function
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append,
|
||||
uint32_t flag);
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_ENABLED` | n | Enable BLE Log module |
|
||||
| `CONFIG_BLE_LOG_LBM_TRANS_SIZE` | 512 | Size of each transport buffer |
|
||||
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT` | 2 | Number of atomic lock LBMs for task context |
|
||||
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT` | 1 | Number of atomic lock LBMs for ISR context |
|
||||
|
||||
### Link Layer Configuration
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_LL_ENABLED` | y | Enable Link Layer logging |
|
||||
| `CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE` | 1024 | Link Layer transport buffer size |
|
||||
|
||||
### Advanced Features
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED` | y | Enable payload checksum |
|
||||
| `CONFIG_BLE_LOG_ENH_STAT_ENABLED` | n | Enable enhanced statistics |
|
||||
| `CONFIG_BLE_LOG_TS_ENABLED` | n | Enable timestamp synchronization |
|
||||
|
||||
### Transport Method Configuration
|
||||
|
||||
| Transport | Configuration | Description |
|
||||
|-----------|---------------|-------------|
|
||||
| Dummy | `CONFIG_BLE_LOG_PRPH_DUMMY` | Debug dummy transport |
|
||||
| SPI Master DMA | `CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA` | SPI DMA transport |
|
||||
| UART DMA | `CONFIG_BLE_LOG_PRPH_UART_DMA` | UART DMA transport |
|
||||
|
||||
## API Reference
|
||||
|
||||
### Core API
|
||||
|
||||
#### `bool ble_log_init(void)`
|
||||
|
||||
Initialize the BLE Log module.
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Initialization successful
|
||||
- `false`: Initialization failed
|
||||
|
||||
**Note**: Must be called before using any other APIs.
|
||||
|
||||
#### `void ble_log_deinit(void)`
|
||||
|
||||
Cleanup the BLE Log module and release all resources.
|
||||
|
||||
**Note**:
|
||||
- All pending logs will be lost after calling this function
|
||||
- Peripheral interface will be cleaned up first to avoid DMA transmission issues during memory release
|
||||
|
||||
#### `bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)`
|
||||
|
||||
Write hexadecimal log data.
|
||||
|
||||
**Parameters**:
|
||||
- `src_code`: Log source code
|
||||
- `addr`: Data pointer
|
||||
- `len`: Data length
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Write successful
|
||||
- `false`: Write failed (module not initialized or insufficient buffer)
|
||||
|
||||
#### `void ble_log_flush(void)`
|
||||
|
||||
Force flush all buffers and send pending logs immediately.
|
||||
|
||||
**Note**: This operation is blocking and will pause module operation until all buffers are cleared.
|
||||
|
||||
#### `void ble_log_dump_to_console(void)`
|
||||
|
||||
Output all buffer contents to console in hexadecimal format for debugging.
|
||||
|
||||
### Log Source Types
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
BLE_LOG_SRC_INTERNAL = 0, // Internal system logs
|
||||
BLE_LOG_SRC_CUSTOM, // User-defined logs
|
||||
BLE_LOG_SRC_LL_TASK, // Link Layer task logs
|
||||
BLE_LOG_SRC_LL_HCI, // Link Layer HCI logs
|
||||
BLE_LOG_SRC_LL_ISR, // Link Layer interrupt logs
|
||||
BLE_LOG_SRC_HOST, // Host layer logs
|
||||
BLE_LOG_SRC_HCI, // HCI layer logs
|
||||
BLE_LOG_SRC_ENCODE, // Encoding layer logs
|
||||
BLE_LOG_SRC_MAX,
|
||||
} ble_log_src_t;
|
||||
```
|
||||
|
||||
### Link Layer API (Conditional Compilation)
|
||||
|
||||
#### `void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag)`
|
||||
|
||||
Link Layer dedicated log writing interface.
|
||||
|
||||
**Parameters**:
|
||||
- `len`: Main data length
|
||||
- `addr`: Main data pointer
|
||||
- `len_append`: Append data length
|
||||
- `addr_append`: Append data pointer
|
||||
- `flag`: Log flag bits
|
||||
|
||||
**Flag Definitions**:
|
||||
```c
|
||||
enum {
|
||||
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||
BLE_LOG_LL_FLAG_END,
|
||||
BLE_LOG_LL_FLAG_TASK,
|
||||
BLE_LOG_LL_FLAG_ISR,
|
||||
BLE_LOG_LL_FLAG_HCI,
|
||||
BLE_LOG_LL_FLAG_RAW,
|
||||
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||
};
|
||||
```
|
||||
|
||||
### Timestamp Synchronization API (Conditional Compilation)
|
||||
|
||||
#### `bool ble_log_sync_enable(bool enable)`
|
||||
|
||||
Enable or disable timestamp synchronization functionality.
|
||||
|
||||
**Parameters**:
|
||||
- `enable`: true to enable, false to disable
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Operation successful
|
||||
- `false`: Operation failed (module not initialized)
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Basic Logging
|
||||
|
||||
```c
|
||||
#include "ble_log.h"
|
||||
|
||||
void example_basic_logging() {
|
||||
// Initialize
|
||||
if (!ble_log_init()) {
|
||||
printf("BLE Log init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Log some example data
|
||||
uint8_t hci_cmd[] = {0x01, 0x03, 0x0C, 0x00}; // HCI Reset Command
|
||||
ble_log_write_hex(BLE_LOG_SRC_HCI, hci_cmd, sizeof(hci_cmd));
|
||||
|
||||
uint8_t host_data[] = {0x02, 0x00, 0x20, 0x0B, 0x00, 0x07, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x28};
|
||||
ble_log_write_hex(BLE_LOG_SRC_HOST, host_data, sizeof(host_data));
|
||||
|
||||
// Force send
|
||||
ble_log_flush();
|
||||
|
||||
// Cleanup
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2: ISR Context Logging
|
||||
|
||||
```c
|
||||
void IRAM_ATTR some_isr_handler() {
|
||||
uint8_t isr_data[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
|
||||
// Safe to write logs in ISR context
|
||||
ble_log_write_hex(BLE_LOG_SRC_LL_ISR, isr_data, sizeof(isr_data));
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Logging with Timestamp Synchronization
|
||||
|
||||
```c
|
||||
void example_with_timestamp_sync() {
|
||||
if (!ble_log_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
// Enable timestamp synchronization
|
||||
ble_log_sync_enable(true);
|
||||
#endif
|
||||
|
||||
// Log data...
|
||||
uint8_t data[] = {0x01, 0x02, 0x03};
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||
|
||||
// Timestamp information will be automatically included in logs
|
||||
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### Example 4: Performance Testing
|
||||
|
||||
```c
|
||||
void example_performance_test() {
|
||||
if (!ble_log_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t test_data[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
test_data[i] = i;
|
||||
}
|
||||
|
||||
uint32_t start_time = esp_timer_get_time();
|
||||
|
||||
// Send 1000 logs
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, test_data, sizeof(test_data));
|
||||
}
|
||||
|
||||
ble_log_flush();
|
||||
uint32_t end_time = esp_timer_get_time();
|
||||
|
||||
printf("Time to write 1000 logs: %lu us\n", end_time - start_time);
|
||||
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
## Performance & Memory Optimization
|
||||
|
||||
### Memory Usage Estimation
|
||||
|
||||
Memory usage under default configuration:
|
||||
|
||||
```
|
||||
Total Buffers = (Atomic Task LBMs + Atomic ISR LBMs + Spin LBMs) × 2 × Transport Buffer Size
|
||||
Default Config = (2 + 1 + 2) × 2 × 512 = 5120 bytes
|
||||
|
||||
Additional when Link Layer enabled:
|
||||
LL Buffers = 2 × 2 × 1024 = 4096 bytes
|
||||
|
||||
Additional when Enhanced Statistics enabled:
|
||||
Statistics Data = Log Source Count × sizeof(ble_log_stat_mgr_t) = 8 × 40 = 320 bytes
|
||||
```
|
||||
|
||||
### Performance Optimization Recommendations
|
||||
|
||||
1. **Adjust LBM Count**: Adjust atomic lock LBM count based on concurrency requirements
|
||||
2. **Buffer Size**: Adjust transport buffer size based on log volume
|
||||
3. **Transport Method**: Choose optimal transport method based on hardware (SPI DMA typically has best performance)
|
||||
4. **Checksum**: Consider disabling payload checksum when performance requirements are extremely high
|
||||
|
||||
### Real-time Considerations
|
||||
|
||||
- Critical code paths are marked with `BLE_LOG_IRAM_ATTR` and run in IRAM
|
||||
- Atomic operations avoid lock contention
|
||||
- Ping-pong buffers ensure continuous writing
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. Initialization Failure
|
||||
|
||||
**Symptoms**: `ble_log_init()` returns `false`
|
||||
|
||||
**Possible Causes**:
|
||||
- Insufficient memory
|
||||
- Peripheral configuration error
|
||||
- Duplicate initialization
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Check available memory
|
||||
printf("Free heap: %d bytes\n", esp_get_free_heap_size());
|
||||
|
||||
// Ensure initialization only happens once
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = ble_log_init();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Log Loss
|
||||
|
||||
**Symptoms**: Some logs don't appear in output
|
||||
|
||||
**Possible Causes**:
|
||||
- Buffer overflow
|
||||
- Transmission speed can't keep up with write speed
|
||||
- Module not properly initialized
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Enable enhanced statistics to check loss rate
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
// Statistics will be automatically included in logs
|
||||
#endif
|
||||
|
||||
// Adjust buffer size
|
||||
// CONFIG_BLE_LOG_LBM_TRANS_SIZE=1024
|
||||
|
||||
// Increase atomic lock LBM count
|
||||
// CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT=4
|
||||
```
|
||||
|
||||
#### 3. Performance Issues
|
||||
|
||||
**Symptoms**: System response becomes slow
|
||||
|
||||
**Possible Causes**:
|
||||
- Checksum calculation overhead
|
||||
- Transmission bottleneck
|
||||
- Lock contention
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Disable payload checksum
|
||||
// CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED=n
|
||||
|
||||
// Use faster transmission method
|
||||
// CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA=y
|
||||
|
||||
// Adjust task priority
|
||||
#define BLE_LOG_TASK_PRIO configMAX_PRIORITIES-3
|
||||
```
|
||||
|
||||
### Debugging Techniques
|
||||
|
||||
#### 1. Use Dummy Transport for Debugging
|
||||
|
||||
```c
|
||||
// Select Dummy transport in menuconfig
|
||||
// Then use dump function to view buffer contents
|
||||
ble_log_dump_to_console();
|
||||
```
|
||||
|
||||
#### 2. Enable Enhanced Statistics
|
||||
|
||||
```c
|
||||
// Enable in menuconfig
|
||||
// CONFIG_BLE_LOG_ENH_STAT_ENABLED=y
|
||||
// Statistics will be automatically output to logs
|
||||
```
|
||||
|
||||
#### 3. Monitor Memory Usage
|
||||
|
||||
```c
|
||||
void monitor_memory() {
|
||||
printf("Free heap before init: %d\n", esp_get_free_heap_size());
|
||||
ble_log_init();
|
||||
printf("Free heap after init: %d\n", esp_get_free_heap_size());
|
||||
}
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,795 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "ble_log/ble_log_uhci_out.h"
|
||||
|
||||
|
||||
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
|
||||
// Private includes
|
||||
#include "esp_bt.h"
|
||||
|
||||
// sdkconfig defines
|
||||
#define UHCI_OUT_LL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_TASK_BUF_SIZE
|
||||
#define UHCI_OUT_LL_ISR_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_ISR_BUF_SIZE
|
||||
#define UHCI_OUT_LL_HCI_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_HCI_BUF_SIZE
|
||||
#define UHCI_OUT_UART_PORT CONFIG_BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
#define UHCI_OUT_UART_NEED_INIT CONFIG_BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
#if UHCI_OUT_UART_NEED_INIT
|
||||
#define UHCI_OUT_UART_BAUD_RATE CONFIG_BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE
|
||||
#define UHCI_OUT_UART_IO_NUM_TX CONFIG_BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX
|
||||
#endif // UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
// Private defines
|
||||
#define UHCI_OUT_MAX_TRANSFER_SIZE (10240)
|
||||
#define UHCI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#define UHCI_OUT_FLUSH_TIMEOUT_MS (100)
|
||||
#define UHCI_OUT_FLUSH_TIMEOUT_US (UHCI_OUT_FLUSH_TIMEOUT_MS * 1000)
|
||||
#define UHCI_OUT_USER_BUF_SIZE (512)
|
||||
#define UHCI_OUT_UART_PORT0 (0)
|
||||
#define UHCI_OUT_UART_PORT1 (1)
|
||||
#define UHCI_OUT_UART_DRIVER_RX_BUF_SIZE (32)
|
||||
|
||||
// Queue size defines
|
||||
#define UHCI_OUT_PING_PONG_BUF_CNT (2)
|
||||
#define UHCI_OUT_USER_QUEUE_SIZE (UHCI_OUT_PING_PONG_BUF_CNT)
|
||||
#define UHCI_OUT_LL_QUEUE_SIZE (3 * UHCI_OUT_PING_PONG_BUF_CNT)
|
||||
#define UHCI_OUT_QUEUE_SIZE (UHCI_OUT_USER_QUEUE_SIZE + UHCI_OUT_LL_QUEUE_SIZE)
|
||||
|
||||
#if CONFIG_SOC_ESP_NIMBLE_CONTROLLER
|
||||
#include "os/os_mbuf.h"
|
||||
#endif /* CONFIG_SOC_ESP_NIMBLE_CONTROLLER */
|
||||
|
||||
// Private typedefs
|
||||
typedef struct {
|
||||
// This flag is for multithreading, must be a word, do not modify
|
||||
volatile uint32_t flag;
|
||||
uint16_t buf_size;
|
||||
uint16_t length;
|
||||
uint8_t buffer[0];
|
||||
} uhci_out_trans_cb_t;
|
||||
|
||||
typedef struct {
|
||||
uhci_out_trans_cb_t *trans_cb[2];
|
||||
uint8_t trans_cb_idx;
|
||||
uint8_t type;
|
||||
uint16_t lost_frame_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
uint32_t frame_sn;
|
||||
} uhci_out_log_cb_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
uint8_t source;
|
||||
uint8_t type;
|
||||
uint16_t frame_sn;
|
||||
} __attribute__((packed)) frame_head_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint16_t lost_frame_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
} __attribute__((packed)) loss_payload_t;
|
||||
|
||||
// Private enums
|
||||
enum {
|
||||
TRANS_CB_FLAG_AVAILABLE = 0,
|
||||
TRANS_CB_FLAG_NEED_QUEUE,
|
||||
TRANS_CB_FLAG_IN_QUEUE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOG_CB_TYPE_USER = 0,
|
||||
LOG_CB_TYPE_LL,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOG_CB_LL_SUBTYPE_TASK = 0,
|
||||
LOG_CB_LL_SUBTYPE_ISR,
|
||||
LOG_CB_LL_SUBTYPE_HCI
|
||||
};
|
||||
|
||||
enum {
|
||||
LL_LOG_FLAG_CONTINUE = 0,
|
||||
LL_LOG_FLAG_END,
|
||||
LL_LOG_FLAG_TASK,
|
||||
LL_LOG_FLAG_ISR,
|
||||
LL_LOG_FLAG_HCI,
|
||||
LL_LOG_FLAG_RAW,
|
||||
LL_LOG_FLAG_OMDATA,
|
||||
LL_LOG_FLAG_HCI_UPSTREAM,
|
||||
};
|
||||
|
||||
enum {
|
||||
LL_EV_FLAG_ISR_APPEND = 0,
|
||||
LL_EV_FLAG_FLUSH_LOG,
|
||||
};
|
||||
|
||||
// Private variables
|
||||
static bool uhci_out_inited = false;
|
||||
static uhci_controller_handle_t uhci_handle = NULL;
|
||||
|
||||
static bool user_log_inited = false;
|
||||
static SemaphoreHandle_t user_log_mutex = NULL;
|
||||
static uhci_out_log_cb_t *user_log_cb = NULL;
|
||||
static uint32_t user_last_write_ts = 0;
|
||||
|
||||
static bool ll_log_inited = false;
|
||||
static uhci_out_log_cb_t *ll_task_log_cb = NULL;
|
||||
static uhci_out_log_cb_t *ll_isr_log_cb = NULL;
|
||||
static uhci_out_log_cb_t *ll_hci_log_cb = NULL;
|
||||
static uint32_t ll_ev_flags = 0;
|
||||
static uint32_t ll_last_write_ts = 0;
|
||||
|
||||
static esp_timer_handle_t flush_timer = NULL;
|
||||
|
||||
// Private function declarations
|
||||
extern void esp_panic_handler_feed_wdts(void);
|
||||
|
||||
static int uhci_out_init_trans(uhci_out_trans_cb_t **trans_cb, uint16_t buf_size);
|
||||
static void uhci_out_deinit_trans(uhci_out_trans_cb_t **trans_cb);
|
||||
static bool uhci_out_tx_done_cb(uhci_controller_handle_t uhci_ctrl,
|
||||
const uhci_tx_done_event_data_t *edata, void *user_ctx);
|
||||
static inline void uhci_out_append_trans(uhci_out_trans_cb_t *trans_cb);
|
||||
|
||||
static int uhci_out_log_cb_init(uhci_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type, uint8_t idx);
|
||||
static void uhci_out_log_cb_deinit(uhci_out_log_cb_t **log_cb);
|
||||
static inline bool uhci_out_log_cb_check_trans(uhci_out_log_cb_t *log_cb, uint16_t len, bool *need_append);
|
||||
static inline void uhci_out_log_cb_append_trans(uhci_out_log_cb_t *log_cb);
|
||||
static inline void uhci_out_log_cb_flush_trans(uhci_out_log_cb_t *log_cb);
|
||||
static bool uhci_out_log_cb_write(uhci_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, uint8_t source, bool omdata);
|
||||
static void uhci_out_log_cb_write_loss(uhci_out_log_cb_t *log_cb);
|
||||
static void uhci_out_log_cb_dump(uhci_out_log_cb_t *log_cb);
|
||||
|
||||
static void esp_timer_cb_log_flush(void);
|
||||
static void uhci_out_user_write_str(const uint8_t *src, uint16_t len);
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
static void uhci_out_user_write_char(char c);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
static int uhci_out_user_log_init(void);
|
||||
static void uhci_out_user_log_deinit(void);
|
||||
|
||||
static int uhci_out_ll_log_init(void);
|
||||
static void uhci_out_ll_log_deinit(void);
|
||||
static void uhci_out_ll_log_flush(void);
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
|
||||
defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21)
|
||||
extern void r_ble_log_simple_put_ev(void);
|
||||
#define UHCI_OUT_LL_PUT_EV r_ble_log_simple_put_ev()
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||
extern void ble_log_simple_put_ev(void);
|
||||
#define UHCI_OUT_LL_PUT_EV ble_log_simple_put_ev()
|
||||
#else
|
||||
#define UHCI_OUT_LL_PUT_EV
|
||||
#endif
|
||||
|
||||
// Private macros
|
||||
#define UHCI_OUT_FRAME_HEAD_LEN (sizeof(frame_head_t))
|
||||
#define UHCI_OUT_FRAME_TAIL_LEN (sizeof(uint32_t))
|
||||
#define UHCI_OUT_FRAME_OVERHEAD (UHCI_OUT_FRAME_HEAD_LEN + UHCI_OUT_FRAME_TAIL_LEN)
|
||||
#define UHCI_OUT_GET_FRAME_SN(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_RELAXED)
|
||||
|
||||
// Private functions
|
||||
static int uhci_out_init_trans(uhci_out_trans_cb_t **trans_cb, uint16_t buf_size)
|
||||
{
|
||||
// Memory allocations
|
||||
size_t cb_size = sizeof(uhci_out_trans_cb_t) + buf_size;
|
||||
*trans_cb = (uhci_out_trans_cb_t *)UHCI_OUT_MALLOC(cb_size);
|
||||
if (!(*trans_cb)) {
|
||||
return -1;
|
||||
}
|
||||
memset(*trans_cb, 0, sizeof(uhci_out_trans_cb_t));
|
||||
|
||||
// Initialization
|
||||
(*trans_cb)->buf_size = buf_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uhci_out_deinit_trans(uhci_out_trans_cb_t **trans_cb)
|
||||
{
|
||||
if (!(*trans_cb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(*trans_cb);
|
||||
*trans_cb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
IRAM_ATTR static bool uhci_out_tx_done_cb(uhci_controller_handle_t uhci_ctrl,
|
||||
const uhci_tx_done_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb = (uhci_out_trans_cb_t *)((uint8_t *)edata->buffer - sizeof(uhci_out_trans_cb_t));
|
||||
trans_cb->length = 0;
|
||||
trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline void uhci_out_append_trans(uhci_out_trans_cb_t *trans_cb)
|
||||
{
|
||||
if ((trans_cb->flag != TRANS_CB_FLAG_NEED_QUEUE) || !trans_cb->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: If task yield after transmission but before flag set
|
||||
// flag might be reset in tx done ISR before flag set, leading to buffer access failure
|
||||
trans_cb->flag = TRANS_CB_FLAG_IN_QUEUE;
|
||||
if (uhci_transmit(uhci_handle, trans_cb->buffer, trans_cb->length) != ESP_OK) {
|
||||
goto recycle;
|
||||
}
|
||||
return;
|
||||
|
||||
recycle:
|
||||
trans_cb->length = 0;
|
||||
trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
|
||||
return;
|
||||
}
|
||||
|
||||
static int uhci_out_log_cb_init(uhci_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type, uint8_t idx)
|
||||
{
|
||||
// Initialize log control block
|
||||
*log_cb = (uhci_out_log_cb_t *)UHCI_OUT_MALLOC(sizeof(uhci_out_log_cb_t));
|
||||
if (!(*log_cb)) {
|
||||
return -1;
|
||||
}
|
||||
memset(*log_cb, 0, sizeof(uhci_out_log_cb_t));
|
||||
|
||||
// Initialize transactions
|
||||
int ret = 0;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
ret |= uhci_out_init_trans(&((*log_cb)->trans_cb[i]), buf_size);
|
||||
}
|
||||
if (ret != 0) {
|
||||
uhci_out_log_cb_deinit(log_cb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*log_cb)->type = (type << 4) | (idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uhci_out_log_cb_deinit(uhci_out_log_cb_t **log_cb)
|
||||
{
|
||||
if (!(*log_cb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
if ((*log_cb)->trans_cb[i]) {
|
||||
uhci_out_deinit_trans(&((*log_cb)->trans_cb[i]));
|
||||
}
|
||||
}
|
||||
free(*log_cb);
|
||||
*log_cb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline bool uhci_out_log_cb_check_trans(uhci_out_log_cb_t *log_cb, uint16_t len, bool *need_append)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
*need_append = false;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
if (len > trans_cb->buf_size) {
|
||||
goto failed;
|
||||
}
|
||||
if (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE) {
|
||||
if ((trans_cb->buf_size - trans_cb->length) >= len) {
|
||||
return true;
|
||||
} else {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
*need_append = true;
|
||||
}
|
||||
}
|
||||
log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
|
||||
}
|
||||
failed:
|
||||
log_cb->lost_bytes_cnt += len;
|
||||
log_cb->lost_frame_cnt++;
|
||||
return false;
|
||||
}
|
||||
|
||||
// CRITICAL: Shall not be called from ISR!
|
||||
IRAM_ATTR static inline void uhci_out_log_cb_append_trans(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
uint8_t idx = !log_cb->trans_cb_idx;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[idx];
|
||||
if (trans_cb->flag == TRANS_CB_FLAG_NEED_QUEUE) {
|
||||
uhci_out_append_trans(trans_cb);
|
||||
}
|
||||
idx = !idx;
|
||||
}
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline void uhci_out_log_cb_flush_trans(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[i];
|
||||
if (trans_cb->length && (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE)) {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return value: Need append
|
||||
IRAM_ATTR static bool uhci_out_log_cb_write(uhci_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, uint8_t source, bool omdata)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
|
||||
uint8_t *buf = trans_cb->buffer + trans_cb->length;
|
||||
uint16_t total_length = len + len_append;
|
||||
frame_head_t head = {
|
||||
.length = total_length,
|
||||
.source = source,
|
||||
.type = log_cb->type,
|
||||
.frame_sn = UHCI_OUT_GET_FRAME_SN(&(log_cb->frame_sn)) & 0xFFFF,
|
||||
};
|
||||
|
||||
memcpy(buf, (const uint8_t *)&head, UHCI_OUT_FRAME_HEAD_LEN);
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN, addr, len);
|
||||
if (len_append && addr_append) {
|
||||
#if CONFIG_SOC_ESP_NIMBLE_CONTROLLER
|
||||
if (omdata) {
|
||||
os_mbuf_copydata((struct os_mbuf *)addr_append, 0,
|
||||
len_append, buf + UHCI_OUT_FRAME_HEAD_LEN + len);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_SOC_ESP_NIMBLE_CONTROLLER */
|
||||
{
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t checksum = 0;
|
||||
for (int i = 0; i < UHCI_OUT_FRAME_HEAD_LEN + total_length; i++) {
|
||||
checksum += buf[i];
|
||||
}
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN + total_length, &checksum, UHCI_OUT_FRAME_TAIL_LEN);
|
||||
|
||||
trans_cb->length += total_length + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if ((trans_cb->buf_size - trans_cb->length) <= UHCI_OUT_FRAME_OVERHEAD) {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IRAM_ATTR static void uhci_out_log_cb_write_loss(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
if (!log_cb->lost_bytes_cnt || !log_cb->lost_frame_cnt) {
|
||||
return;
|
||||
}
|
||||
bool need_append;
|
||||
uint16_t frame_len = sizeof(loss_payload_t) + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if (uhci_out_log_cb_check_trans(log_cb, frame_len, &need_append)) {
|
||||
loss_payload_t payload = {
|
||||
.type = log_cb->type,
|
||||
.lost_frame_cnt = log_cb->lost_frame_cnt,
|
||||
.lost_bytes_cnt = log_cb->lost_bytes_cnt,
|
||||
};
|
||||
uhci_out_log_cb_write(log_cb, (const uint8_t *)&payload, sizeof(loss_payload_t),
|
||||
NULL, 0, BLE_LOG_UHCI_OUT_SOURCE_LOSS, false);
|
||||
|
||||
log_cb->lost_frame_cnt = 0;
|
||||
log_cb->lost_bytes_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void uhci_out_log_cb_dump(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
uint8_t *buf;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
// Dump the last transaction before dumping the current transaction
|
||||
log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
|
||||
trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
buf = (uint8_t *)trans_cb->buffer;
|
||||
for (uint16_t j = 0; j < trans_cb->buf_size; j++) {
|
||||
esp_rom_printf("%02x ", buf[j]);
|
||||
|
||||
// Feed watchdogs periodically to avoid wdts timeout
|
||||
if ((j % 100) == 0) {
|
||||
esp_panic_handler_feed_wdts();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_timer_cb_log_flush(void)
|
||||
{
|
||||
uint32_t os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
if ((os_ts - user_last_write_ts) > UHCI_OUT_FLUSH_TIMEOUT_MS) {
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
uhci_out_log_cb_flush_trans(user_log_cb);
|
||||
uhci_out_log_cb_append_trans(user_log_cb);
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
}
|
||||
|
||||
if ((esp_bt_controller_get_status() >= ESP_BT_CONTROLLER_STATUS_INITED) &&
|
||||
((os_ts - ll_last_write_ts) > UHCI_OUT_FLUSH_TIMEOUT_MS)) {
|
||||
ll_ev_flags |= BIT(LL_EV_FLAG_FLUSH_LOG);
|
||||
UHCI_OUT_LL_PUT_EV;
|
||||
}
|
||||
|
||||
esp_timer_start_once(flush_timer, UHCI_OUT_FLUSH_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void uhci_out_user_write_str(const uint8_t *src, uint16_t len)
|
||||
{
|
||||
if (!user_log_inited || !src || !len) {
|
||||
return;
|
||||
}
|
||||
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
|
||||
bool need_append;
|
||||
if (uhci_out_log_cb_check_trans(user_log_cb, len, &need_append)) {
|
||||
uhci_out_trans_cb_t *trans_cb = user_log_cb->trans_cb[user_log_cb->trans_cb_idx];
|
||||
uint8_t *buf = trans_cb->buffer + trans_cb->length;
|
||||
|
||||
memcpy(buf, (const uint8_t *)src, len);
|
||||
trans_cb->length += len;
|
||||
}
|
||||
|
||||
if (need_append) {
|
||||
uhci_out_log_cb_append_trans(user_log_cb);
|
||||
}
|
||||
|
||||
user_last_write_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
static void uhci_out_user_write_char(char c)
|
||||
{
|
||||
uhci_out_user_write_str((const uint8_t *)&c, 1);
|
||||
}
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
static int uhci_out_user_log_init(void)
|
||||
{
|
||||
if (user_log_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize mutex
|
||||
user_log_mutex = xSemaphoreCreateMutex();
|
||||
if (!user_log_mutex) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// Initialize log control block
|
||||
if (uhci_out_log_cb_init(&user_log_cb, UHCI_OUT_USER_BUF_SIZE, LOG_CB_TYPE_USER, 0) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// Initialization done
|
||||
user_log_inited = true;
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
uhci_out_user_log_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uhci_out_user_log_deinit(void)
|
||||
{
|
||||
user_log_inited = false;
|
||||
|
||||
if (!user_log_mutex) {
|
||||
return;
|
||||
}
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
|
||||
uhci_out_log_cb_deinit(&user_log_cb);
|
||||
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
vSemaphoreDelete(user_log_mutex);
|
||||
user_log_mutex = NULL;
|
||||
}
|
||||
|
||||
static int uhci_out_ll_log_init(void)
|
||||
{
|
||||
if (ll_log_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uhci_out_log_cb_init(&ll_task_log_cb, UHCI_OUT_LL_TASK_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_TASK) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
if (uhci_out_log_cb_init(&ll_isr_log_cb, UHCI_OUT_LL_ISR_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_ISR) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
if (uhci_out_log_cb_init(&ll_hci_log_cb, UHCI_OUT_LL_HCI_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_HCI) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ll_log_inited = true;
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
uhci_out_ll_log_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uhci_out_ll_log_deinit(void)
|
||||
{
|
||||
ll_log_inited = false;
|
||||
|
||||
uhci_out_log_cb_deinit(&ll_hci_log_cb);
|
||||
uhci_out_log_cb_deinit(&ll_isr_log_cb);
|
||||
uhci_out_log_cb_deinit(&ll_task_log_cb);
|
||||
}
|
||||
|
||||
static void uhci_out_ll_log_flush(void)
|
||||
{
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
uhci_out_log_cb_write_loss(ll_task_log_cb);
|
||||
uhci_out_log_cb_write_loss(ll_hci_log_cb);
|
||||
|
||||
uhci_out_log_cb_flush_trans(ll_task_log_cb);
|
||||
uhci_out_log_cb_flush_trans(ll_hci_log_cb);
|
||||
|
||||
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
uhci_out_log_cb_write_loss(ll_isr_log_cb);
|
||||
uhci_out_log_cb_flush_trans(ll_isr_log_cb);
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
uhci_out_log_cb_append_trans(ll_task_log_cb);
|
||||
uhci_out_log_cb_append_trans(ll_hci_log_cb);
|
||||
uhci_out_log_cb_append_trans(ll_isr_log_cb);
|
||||
}
|
||||
|
||||
// Public functions
|
||||
int ble_log_uhci_out_init(void)
|
||||
{
|
||||
// Avoid double init
|
||||
if (uhci_out_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_NEED_INIT
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = UHCI_OUT_UART_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
// Configure UART parameters
|
||||
uart_param_config(UHCI_OUT_UART_PORT, &uart_config);
|
||||
uart_set_pin(UHCI_OUT_UART_PORT, UHCI_OUT_UART_IO_NUM_TX, -1, -1, -1);
|
||||
#endif // UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
uhci_controller_config_t uhci_config = {
|
||||
.uart_port = UHCI_OUT_UART_PORT,
|
||||
.tx_trans_queue_depth = UHCI_OUT_QUEUE_SIZE,
|
||||
.max_receive_internal_mem = 1024,
|
||||
.max_transmit_size = UHCI_OUT_MAX_TRANSFER_SIZE,
|
||||
.dma_burst_size = 32,
|
||||
.rx_eof_flags.idle_eof = 1,
|
||||
};
|
||||
if (uhci_new_controller(&uhci_config, &uhci_handle) != ESP_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
uhci_event_callbacks_t uhci_cbs = {
|
||||
.on_tx_trans_done = uhci_out_tx_done_cb,
|
||||
};
|
||||
uhci_register_event_callbacks(uhci_handle, &uhci_cbs, NULL);
|
||||
|
||||
if (uhci_out_user_log_init() != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (uhci_out_ll_log_init() != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = (esp_timer_cb_t)esp_timer_cb_log_flush,
|
||||
.dispatch_method = ESP_TIMER_TASK
|
||||
};
|
||||
if (esp_timer_create(&timer_args, &flush_timer) != ESP_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
// Install UART Driver if not installed
|
||||
if (!uart_is_driver_installed(UHCI_OUT_UART_PORT0)) {
|
||||
uart_driver_install(UHCI_OUT_UART_PORT0, UHCI_OUT_UART_DRIVER_RX_BUF_SIZE, 0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// Redirect UART VFS Driver to UART Driver
|
||||
uart_vfs_dev_use_driver(UHCI_OUT_UART_PORT0);
|
||||
|
||||
// Redirect esp_rom_printf to BLE Log UHCI Out
|
||||
esp_rom_install_channel_putc(1, uhci_out_user_write_char);
|
||||
esp_rom_install_channel_putc(2, NULL);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
uhci_out_inited = true;
|
||||
esp_timer_start_once(flush_timer, UHCI_OUT_FLUSH_TIMEOUT_US);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
ble_log_uhci_out_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ble_log_uhci_out_deinit(void)
|
||||
{
|
||||
uhci_out_inited = false;
|
||||
|
||||
if (flush_timer) {
|
||||
esp_timer_stop(flush_timer);
|
||||
esp_timer_delete(flush_timer);
|
||||
flush_timer = NULL;
|
||||
}
|
||||
|
||||
if (uhci_handle) {
|
||||
uhci_wait_all_tx_transaction_done(uhci_handle, portMAX_DELAY);
|
||||
uhci_del_controller(uhci_handle);
|
||||
uhci_handle = NULL;
|
||||
}
|
||||
|
||||
uhci_out_ll_log_deinit();
|
||||
uhci_out_user_log_deinit();
|
||||
}
|
||||
|
||||
IRAM_ATTR void ble_log_uhci_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,
|
||||
const uint8_t *addr_append, uint32_t flag)
|
||||
{
|
||||
// Raw logs will come in case of assert, shall be printed to console directly
|
||||
if (flag & BIT(LL_LOG_FLAG_RAW)) {
|
||||
if (len && addr) {
|
||||
for (uint32_t i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); }
|
||||
}
|
||||
if (len_append && addr_append) {
|
||||
for (uint32_t i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); }
|
||||
}
|
||||
if (flag & BIT(LL_LOG_FLAG_END)) { esp_rom_printf("\n"); }
|
||||
}
|
||||
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool in_isr = false;
|
||||
uint8_t source;
|
||||
uhci_out_log_cb_t *log_cb;
|
||||
if (flag & BIT(LL_LOG_FLAG_ISR)) {
|
||||
log_cb = ll_isr_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_ESP_ISR;
|
||||
in_isr = true;
|
||||
} else if (flag & BIT(LL_LOG_FLAG_HCI)) {
|
||||
log_cb = ll_hci_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_LL_HCI;
|
||||
} else {
|
||||
log_cb = ll_task_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_ESP;
|
||||
}
|
||||
bool omdata = flag & BIT(LL_LOG_FLAG_OMDATA);
|
||||
|
||||
bool need_append;
|
||||
uint16_t frame_len = len + len_append + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if (uhci_out_log_cb_check_trans(log_cb, frame_len, &need_append)) {
|
||||
need_append |= uhci_out_log_cb_write(log_cb, addr, len, addr_append,
|
||||
len_append, source, omdata);
|
||||
}
|
||||
|
||||
ll_last_write_ts = in_isr?\
|
||||
pdTICKS_TO_MS(xTaskGetTickCountFromISR()):\
|
||||
pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
if (need_append) {
|
||||
if (in_isr) {
|
||||
ll_ev_flags |= BIT(LL_EV_FLAG_ISR_APPEND);
|
||||
UHCI_OUT_LL_PUT_EV;
|
||||
} else {
|
||||
uhci_out_log_cb_append_trans(log_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IRAM_ATTR void ble_log_uhci_out_ll_log_ev_proc(void)
|
||||
{
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ll_ev_flags & BIT(LL_EV_FLAG_ISR_APPEND)) {
|
||||
uhci_out_log_cb_append_trans(ll_isr_log_cb);
|
||||
ll_ev_flags &= ~BIT(LL_EV_FLAG_ISR_APPEND);
|
||||
}
|
||||
|
||||
if (ll_ev_flags & BIT(LL_EV_FLAG_FLUSH_LOG)) {
|
||||
uhci_out_ll_log_flush();
|
||||
ll_ev_flags &= ~BIT(LL_EV_FLAG_FLUSH_LOG);
|
||||
}
|
||||
|
||||
ll_ev_flags = 0;
|
||||
}
|
||||
|
||||
// Redirect UART Driver to BLE Log UHCI Out
|
||||
int __real_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len);
|
||||
int __wrap_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
uhci_out_user_write_str((const uint8_t *)buffer, len);
|
||||
return 0;
|
||||
#else
|
||||
return __real_uart_tx_chars(uart_num, buffer, len);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
|
||||
int __wrap_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
uhci_out_user_write_str((const uint8_t *)src, size);
|
||||
return 0;
|
||||
#else
|
||||
return __real_uart_write_bytes(uart_num, src, size);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len);
|
||||
int __wrap_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
return __wrap_uart_write_bytes(uart_num, src, size);
|
||||
#else
|
||||
return __real_uart_write_bytes_with_break(uart_num, src, size, brk_len);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
void ble_log_uhci_out_dump_all(void)
|
||||
{
|
||||
if (!uhci_out_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
esp_rom_output_tx_wait_idle(UHCI_OUT_UART_PORT0);
|
||||
esp_rom_install_uart_printf();
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
if (ll_log_inited) {
|
||||
esp_rom_printf("[DUMP_START:\n");
|
||||
uhci_out_log_cb_dump(ll_isr_log_cb);
|
||||
uhci_out_log_cb_dump(ll_task_log_cb);
|
||||
uhci_out_log_cb_dump(ll_hci_log_cb);
|
||||
esp_rom_printf("\n:DUMP_END]\n\n");
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
esp_rom_install_channel_putc(1, uhci_out_user_write_char);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
set(LOG_COMPRESSED_MODULE "")
|
||||
set(LOG_COMPRESSED_MODULE_CODE_PATH "")
|
||||
set(LOG_COMPRESSED_SRCS_DIR "${CMAKE_BINARY_DIR}/ble_log/.compressed_srcs")
|
||||
|
||||
# default config value for ble mesh module
|
||||
set(BLE_MESH_CODE_PATH "")
|
||||
set(BLE_MESH_LOG_INDEX_HEADER "\"\"")
|
||||
set(BLE_MESH_TAGS "")
|
||||
set(BLE_MESH_TAGS_PRESERVE "")
|
||||
|
||||
# default config value for host module
|
||||
set(HOST_CODE_PATH "")
|
||||
set(HOST_LOG_INDEX_HEADER "\"\"")
|
||||
set(BLE_HOST_TAGS "")
|
||||
set(BLE_HOST_TAGS_PRESERVE "")
|
||||
|
||||
if(CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE)
|
||||
list(APPEND LOG_COMPRESSED_MODULE "BLE_MESH")
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/mesh_log_index.h")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/mesh_log_index.h" "")
|
||||
endif()
|
||||
list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH "esp_ble_mesh")
|
||||
|
||||
# update config file
|
||||
set(BLE_MESH_CODE_PATH "esp_ble_mesh")
|
||||
set(BLE_MESH_LOG_INDEX_HEADER "mesh_log_index.h")
|
||||
# update BLE_MESH_TAGS and BLE_MESH_TAGS_PRESERVE
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_mesh_log_tags.cmake)
|
||||
|
||||
endif()
|
||||
if(CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE AND CONFIG_BT_BLUEDROID_ENABLED)
|
||||
list(APPEND LOG_COMPRESSED_MODULE "BLE_HOST")
|
||||
list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH "host/bluedroid/stack")
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/host_log_index.h")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/host_log_index.h" "")
|
||||
endif()
|
||||
|
||||
set(HOST_CODE_PATH "host/bluedroid/stack")
|
||||
set(HOST_LOG_INDEX_HEADER "host_log_index.h")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_host_bluedroid_tags.cmake)
|
||||
endif()
|
||||
if(LOG_COMPRESSED_MODULE)
|
||||
list(APPEND srcs "common/ble_log/extension/log_compression/ble_log_compression.c")
|
||||
list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include")
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.15.0)
|
||||
set(Python3_FIND_STRATEGY LOCATION)
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
if(Python3_Interpreter_FOUND)
|
||||
set(BLE_PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
||||
endif()
|
||||
else()
|
||||
find_package(PythonInterp 3)
|
||||
if(PYTHONINTERP_FOUND)
|
||||
set(BLE_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BLE_PYTHON_EXECUTABLE)
|
||||
set(PYTHON_SCRIPT ${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/ble_log_compress.py)
|
||||
|
||||
set(compressed_srcs "")
|
||||
set(uncompressed_srcs "")
|
||||
set(compressed_srcs_with_abs_path "")
|
||||
|
||||
execute_process(COMMAND ${BLE_PYTHON_EXECUTABLE}
|
||||
${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/env_check.py
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_VARIABLE err
|
||||
)
|
||||
|
||||
if(NOT ${result} EQUAL 0)
|
||||
message(WARNING "${err}")
|
||||
message(WARNING "Exit this log compression due to failure of environment check")
|
||||
set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
|
||||
set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(CONFIG_FILE_PATH "${CMAKE_BINARY_DIR}/ble_log/module_info.yml")
|
||||
if(NOT EXISTS "${CONFIG_FILE_PATH}")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/ble_log/module_info.yml")
|
||||
endif()
|
||||
set(YML_IN "${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in")
|
||||
configure_file(${YML_IN} ${CONFIG_FILE_PATH} @ONLY)
|
||||
|
||||
string(REPLACE ";" "|" MODULE_CODE_PATH "${LOG_COMPRESSED_MODULE_CODE_PATH}")
|
||||
set(MATCH_PATTERN "(${MODULE_CODE_PATH}).+\\.c")
|
||||
foreach(src ${srcs})
|
||||
if(src MATCHES ${MATCH_PATTERN})
|
||||
set(dest "${LOG_COMPRESSED_SRCS_DIR}/${src}")
|
||||
file(WRITE "${dest}" "")
|
||||
list(APPEND compressed_srcs ${src})
|
||||
list(APPEND compressed_srcs_with_abs_path "${dest}")
|
||||
else()
|
||||
list(APPEND uncompressed_srcs ${src})
|
||||
endif()
|
||||
endforeach()
|
||||
string(REPLACE "|" ";" LOG_COMPRESSED_MODULE_CODE_PATH "${MODULE_CODE_PATH}")
|
||||
|
||||
# Some header files of NIMBLE are not added to include_dirs,
|
||||
# but rely on relative path searches. This will cause the header
|
||||
# files to be found due to the change in the source code location
|
||||
# after using the log compression scheme.
|
||||
# Therefore, these paths are added to include_dirs here to avoid
|
||||
# unfinished compilation errors.
|
||||
if(CONFIG_BT_NIMBLE_ENABLED)
|
||||
list(APPEND include_dirs
|
||||
"host/nimble/nimble/nimble/host/src"
|
||||
"host/nimble/nimble/nimble/host/store/config/src")
|
||||
endif()
|
||||
|
||||
add_custom_target(ble_log_compression ALL
|
||||
COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT}
|
||||
compress
|
||||
--compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}"
|
||||
--build_path "${CMAKE_BINARY_DIR}"
|
||||
--module "'${LOG_COMPRESSED_MODULE}'"
|
||||
--bt_path "${BT_ROOT_PATH}"
|
||||
--srcs "'${compressed_srcs}'"
|
||||
DEPENDS ${compressed_srcs_with_abs_path} ${PYTHON_SCRIPT}
|
||||
COMMENT "Log compression is being performed, please wait..."
|
||||
WORKING_DIRECTORY ${BT_ROOT_PATH}
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
function(add_flags_if_in_list file file_list compile_flags)
|
||||
set(PROCESSED OFF PARENT_SCOPE)
|
||||
foreach(item IN LISTS file_list)
|
||||
if(item STREQUAL file)
|
||||
set_source_files_properties("${LOG_COMPRESSED_SRCS_DIR}/${file}"
|
||||
PROPERTIES
|
||||
GENERATED TRUE
|
||||
COMPILE_FLAGS "${compile_flags}"
|
||||
OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/ble_log_compression"
|
||||
)
|
||||
set(PROCESSED ON PARENT_SCOPE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
foreach(src ${compressed_srcs})
|
||||
set(PROCESSED OFF)
|
||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||
set(files_with_compile_flags
|
||||
"host/bluedroid/bta/gatt/bta_gattc_act.c"
|
||||
"host/bluedroid/bta/gatt/bta_gattc_cache.c"
|
||||
"host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c"
|
||||
"host/bluedroid/btc/profile/std/gatt/btc_gatts.c")
|
||||
add_flags_if_in_list("${src}"
|
||||
"${files_with_compile_flags}"
|
||||
"-Wno-address-of-packed-member")
|
||||
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
set(jump_table_opts "-fjump-tables")
|
||||
if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") )
|
||||
set(jump_table_opts "${jump_table_opts} -ftree-switch-conversion")
|
||||
endif()
|
||||
set(files_with_compile_flags
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_cmd.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
|
||||
)
|
||||
add_flags_if_in_list("${src}"
|
||||
"${files_with_compile_flags}"
|
||||
"${jump_table_opts}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0)
|
||||
set(files_with_compile_flags "host/bluedroid/device/controller.c")
|
||||
add_flags_if_in_list("${src}"
|
||||
"${files_with_compile_flags}"
|
||||
"-Wno-unterminated-string-initialization")
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_BT_NIMBLE_ENABLED)
|
||||
if(CONFIG_BT_NIMBLE_MESH)
|
||||
message(ERROR "The current log compression scheme does not support NIMBLE MESH")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT PROCESSED)
|
||||
set_source_files_properties("${LOG_COMPRESSED_SRCS_DIR}/${src}"
|
||||
PROPERTIES GENERATED TRUE
|
||||
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ble_log_compression
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(LOG_COMPRESSION_TARGET ble_log_compression PARENT_SCOPE)
|
||||
# set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
|
||||
set(LOG_COMPRESS_SRCS "${compressed_srcs_with_abs_path};${uncompressed_srcs}" PARENT_SCOPE)
|
||||
list(APPEND include_dirs "common/ble_log/extension/log_compression/include")
|
||||
set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
|
||||
else()
|
||||
set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
|
||||
message("Python 3 used for log compressing not found")
|
||||
endif()
|
||||
else()
|
||||
set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
|
||||
message(STATUS "No module enabled for log compress")
|
||||
endif()
|
||||
@@ -1,692 +0,0 @@
|
||||
|
||||
config BLE_COMPRESSED_LOG_ENABLE
|
||||
bool "Enable BLE log compression(Preview, Please read help information)"
|
||||
default n
|
||||
help
|
||||
Compress BLE logs during application build to reduce flash usage
|
||||
and improve output speed. When enabled, log data from Bluetooth
|
||||
Low Energy components will be compressed before storage,
|
||||
optimizing both memory footprint and transmission efficiency.
|
||||
|
||||
Note: This library depends on additional Python packages. It will
|
||||
function correctly only after these dependencies are installed;
|
||||
refer to:
|
||||
"components/bt/common/ble_log/log_compression/README.en.md"
|
||||
for installation instructions.
|
||||
|
||||
if BLE_COMPRESSED_LOG_ENABLE
|
||||
menuconfig BLE_MESH_COMPRESSED_LOG_ENABLE
|
||||
bool "Enable BLE Mesh log compression(Preview)"
|
||||
depends on BLE_COMPRESSED_LOG_ENABLE
|
||||
depends on BLE_MESH
|
||||
default n
|
||||
help
|
||||
Apply compression to ESP-BLE-MESH protocol stack logs. Requires
|
||||
base BLE compression to be enabled. Specifically optimizes log
|
||||
storage and transmission for ble mesh.
|
||||
|
||||
Note: This library depends on additional Python packages. It will
|
||||
function correctly only after these dependencies are installed;
|
||||
refer to:
|
||||
"components/bt/common/ble_log/log_compression/README.en.md"
|
||||
for installation instructions.
|
||||
|
||||
If the required packages are not installed, the log-compression
|
||||
mechanism will remain disabled even when this Config is enabled.
|
||||
|
||||
config BLE_MESH_COMPRESSED_LOG_BUFFER_LEN
|
||||
int "BLE Mesh log buffer length"
|
||||
depends on BLE_MESH_COMPRESSED_LOG_ENABLE
|
||||
default 400
|
||||
help
|
||||
Maximum output length for a single log
|
||||
|
||||
if BLE_MESH_COMPRESSED_LOG_ENABLE
|
||||
menu "Select the stack log tag to be compressed"
|
||||
config BLE_MESH_STACK_ERR_LOG_COMPRESSION
|
||||
bool "Compress ERROR log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The error log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_STACK_ERR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_MESH_STACK_ERR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_MESH_STACK_WARN_LOG_COMPRESSION
|
||||
bool "Compress warn log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The warn log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_STACK_WARN_LOG_PRESERVE
|
||||
bool "Keep the original warn log statement"
|
||||
depends on BLE_MESH_STACK_WARN_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_STACK_ERR_LOG_PRESERVE
|
||||
config BLE_MESH_STACK_INFO_LOG_COMPRESSION
|
||||
bool "Compress info log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The info log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_STACK_INFO_LOG_PRESERVE
|
||||
bool "Keep the original info log statement"
|
||||
depends on BLE_MESH_STACK_INFO_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_STACK_ERR_LOG_PRESERVE
|
||||
config BLE_MESH_STACK_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The debug log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_STACK_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_MESH_STACK_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_STACK_ERR_LOG_PRESERVE
|
||||
endmenu
|
||||
menu "Select the net buf log tag to be compressed"
|
||||
config BLE_MESH_NET_BUF_ERR_LOG_COMPRESSION
|
||||
bool "Compress ERROR log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The error log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_NET_BUF_ERR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_MESH_NET_BUF_ERR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
config BLE_MESH_NET_BUF_WARN_LOG_COMPRESSION
|
||||
bool "Compress warn log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The warn log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_NET_BUF_WARN_LOG_PRESERVE
|
||||
bool "Keep the original warn log statement"
|
||||
depends on BLE_MESH_NET_BUF_WARN_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_NET_BUF_ERR_LOG_PRESERVE
|
||||
config BLE_MESH_NET_BUF_INFO_LOG_COMPRESSION
|
||||
bool "Compress info log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The info log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_NET_BUF_INFO_LOG_PRESERVE
|
||||
bool "Keep the original info log statement"
|
||||
depends on BLE_MESH_NET_BUF_INFO_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_NET_BUF_ERR_LOG_PRESERVE
|
||||
config BLE_MESH_NET_BUF_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of ESP-BLE-MESH"
|
||||
default y
|
||||
help
|
||||
The debug log in the BLE-MESH component will be compressed
|
||||
config BLE_MESH_NET_BUF_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_MESH_NET_BUF_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_MESH_NET_BUF_ERR_LOG_PRESERVE
|
||||
endmenu
|
||||
endif
|
||||
|
||||
menuconfig BLE_HOST_COMPRESSED_LOG_ENABLE
|
||||
bool "Enable BLE Host log compression(Preview, only Bluedroid Host for now)"
|
||||
depends on BLE_COMPRESSED_LOG_ENABLE
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
default n
|
||||
help
|
||||
Apply compression to host logs. Requires
|
||||
base BLE compression to be enabled. Specifically optimizes log
|
||||
storage and transmission.
|
||||
|
||||
Note: This library depends on additional Python packages. It will
|
||||
function correctly only after these dependencies are installed;
|
||||
refer to:
|
||||
"components/bt/common/ble_log/log_compression/README.en.md"
|
||||
for installation instructions.
|
||||
|
||||
config BLE_HOST_COMPRESSED_LOG_BUFFER_LEN
|
||||
int "Host log buffer length"
|
||||
depends on BLE_HOST_COMPRESSED_LOG_ENABLE
|
||||
default 300
|
||||
help
|
||||
Maximum output length for a single log
|
||||
|
||||
if BLE_HOST_COMPRESSED_LOG_ENABLE
|
||||
menu "Select the BTM layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_BTM_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_BTM_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_BTM_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_BTM_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_BTM_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_BTM_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_BTM_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_BTM_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_BTM_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_BTM_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_BTM_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_BTM_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_BTM_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
|
||||
endmenu
|
||||
menu "Select the LA2CAP layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_L2CAP_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_L2CAP_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_L2CAP_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_L2CAP_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_L2CAP_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_L2CAP_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_L2CAP_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_L2CAP_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
endmenu
|
||||
menu "Select the GAP layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_GAP_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_GAP_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_GAP_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_GAP_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GAP_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_GAP_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GAP_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_GAP_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GAP_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_GAP_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GAP_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GAP_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_GAP_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
endmenu
|
||||
menu "Select the GATT layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_GATT_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_GATT_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_GATT_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_GATT_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GATT_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_GATT_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GATT_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_GATT_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GATT_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_GATT_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_GATT_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_GATT_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_GATT_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
endmenu
|
||||
menu "Select the SMP layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_SMP_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_SMP_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_SMP_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_SMP_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_SMP_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_SMP_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_SMP_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_SMP_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_SMP_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_SMP_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_SMP_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_SMP_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_SMP_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
endmenu
|
||||
menu "Select the APPL layer log tag to be compressed"
|
||||
config BLE_BLUEDROID_APPL_ERROR_LOG_COMPRESSION
|
||||
bool "Compress error log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The error log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
bool "Keep the original error log statement"
|
||||
depends on BLE_BLUEDROID_APPL_ERROR_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
When this option is enabled, the log data will be output
|
||||
through both the compressed log interface and the original
|
||||
UART interface at the same time, meaning that the log
|
||||
statements will appear on both paths. However, please note
|
||||
that this dual-output approach introduces additional code
|
||||
and string constants, which will increase the size of the
|
||||
firmware binary file. When this option is disabled, the
|
||||
logs will no longer be printed through the original UART
|
||||
output path; instead, they will only be output through the
|
||||
compressed log interface. As the code and strings related
|
||||
to the original UART output are omitted, the size of the
|
||||
firmware binary file can be effectively reduced.
|
||||
|
||||
config BLE_BLUEDROID_APPL_WARNING_LOG_COMPRESSION
|
||||
bool "Compress warning log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The warning log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_WARNING_LOG_PRESERVE
|
||||
bool "Keep the original warning log statement"
|
||||
depends on BLE_BLUEDROID_APPL_WARNING_LOG_COMPRESSION
|
||||
default y
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_APPL_API_LOG_COMPRESSION
|
||||
bool "Compress api log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The api log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_API_LOG_PRESERVE
|
||||
bool "Keep the original api log statement"
|
||||
depends on BLE_BLUEDROID_APPL_API_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_APPL_EVENT_LOG_COMPRESSION
|
||||
bool "Compress event log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The event log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_EVENT_LOG_PRESERVE
|
||||
bool "Keep the original event log statement"
|
||||
depends on BLE_BLUEDROID_APPL_EVENT_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_APPL_DEBUG_LOG_COMPRESSION
|
||||
bool "Compress debug log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The debug log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_DEBUG_LOG_PRESERVE
|
||||
bool "Keep the original debug log statement"
|
||||
depends on BLE_BLUEDROID_APPL_DEBUG_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
|
||||
config BLE_BLUEDROID_APPL_VERBOSE_LOG_COMPRESSION
|
||||
bool "Compress verbose log of Bluedroid host"
|
||||
default y
|
||||
help
|
||||
The verbose log in the Bluedroid host component will be compressed
|
||||
config BLE_BLUEDROID_APPL_VERBOSE_LOG_PRESERVE
|
||||
bool "Keep the original verbose log statement"
|
||||
depends on BLE_BLUEDROID_APPL_VERBOSE_LOG_COMPRESSION
|
||||
default n
|
||||
help
|
||||
Please refer to the help information in BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
endmenu
|
||||
endif
|
||||
endif
|
||||
@@ -1,111 +0,0 @@
|
||||
## BLE 日志压缩方案 (Preview)
|
||||
|
||||
### 一、概述
|
||||
|
||||
本方案通过在编译阶段扫描 BLE 协议栈相关组件的代码,将日志语句中的格式化字符串和参数转换为纯二进制数据,从而提升日志输出效率并减少协议栈所占用的 Flash 空间。
|
||||
|
||||
目前,该方案已支持对 BLE-MESH 和 BLE-HOST-BLUEDROID 组件的日志压缩。
|
||||
|
||||
### 二、使用方法
|
||||
该功能依赖额外的 Python 库,请按以下步骤安装所需环境。
|
||||
|
||||
#### 步骤一:验证 ESP-IDF 虚拟环境
|
||||
请确保在 ESP-IDF 的 Python 虚拟环境中执行后续操作。可通过以下命令验证当前环境是否已激活:
|
||||
```bash
|
||||
idf.py --version
|
||||
```
|
||||
若提示 `command not found`,则表示未激活 ESP-IDF 虚拟环境。
|
||||
|
||||
请参考官方文档配置并激活环境:
|
||||
[ESP-IDF 环境设置指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps)
|
||||
|
||||
激活后再次执行 `idf.py --version`,若显示版本信息则表明环境已就绪。
|
||||
|
||||
#### 步骤二:检查 Python 版本
|
||||
在虚拟环境中执行以下命令确认 Python 版本:
|
||||
```bash
|
||||
python --version
|
||||
```
|
||||
若版本低于 3.8,请根据同一官方文档升级 Python:
|
||||
[Python 升级指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps)
|
||||
|
||||
#### 步骤三:安装日志压缩依赖
|
||||
根据您的操作系统和终端环境,选择以下对应的命令安装所需依赖:
|
||||
|
||||
- **Linux 或 macOS**:
|
||||
```bash
|
||||
pip install -r $IDF_PATH/components/bt/common/ble_log/log_compression/scripts/requirements.txt
|
||||
```
|
||||
- **Windows (PowerShell)**:
|
||||
```ps
|
||||
pip install -r $Env:IDF_PATH\components\bt\common\ble_log\log_compression\scripts\requirements.txt
|
||||
```
|
||||
- **Windows (命令提示符 Cmd)**:
|
||||
```bat
|
||||
pip install -r %IDF_PATH%\components\bt\common\ble_log\log_compression\scripts\requirements.txt
|
||||
```
|
||||
|
||||
#### 步骤四:清理缓存文件
|
||||
安装日志压缩所需的依赖后,删除之前构建生成的 build 文件夹(如有)。之后重新构建应用程序即可。
|
||||
|
||||
|
||||
### 步骤五:配置 Menuconfig
|
||||
|
||||
使用命令`idf.py menuconfig`打开menuconfig, 以开启`BLE-MESH`组件的日志压缩为例:
|
||||
|
||||
通过路径`(Top) -> Component config -> Bluetooth -> Common Options -> BLE Log -> Enable BLE log compression(Preview, Please read help information)->Enable BLE Mesh log compression(Preview)`开启`BLE-MESH`组件的日志压缩功能。
|
||||
|
||||
在`Enable BLE Mesh log compression(Preview)`目录中有三个配置项目可供设置:
|
||||
1. `Mesh log buffer length` 通过该配置项来配置单条日志可能出现的最大长度。
|
||||
2. `Maximum number of tasks that can generate ble mesh logs` 通过该配置项目用来配置可能输出`BLE-MESH`组件日志的最大Task数目,(默认值为推荐值,不建议修改)。
|
||||
|
||||
|
||||
### 步骤六:构建应用程序
|
||||
|
||||
当开启配置项后,使用命令`idf.py build`构建应用程序,请注意构建过程中是否会有警告日志出现,比如出现以下日志时:
|
||||
```txt
|
||||
CMake Warning at esp/esp-idf/components/bt/common/ble_log/log_compression/CMakeLists.txt:46 (message):
|
||||
tree_sitter import failed, please check whether the package is installed
|
||||
correctly,Please refer to the
|
||||
file: esp/esp-idf/components/bt/common/ble_log/log_compression/README
|
||||
for installation instructions.
|
||||
```
|
||||
该警告表示依赖未正确安装,日志压缩构建失败,系统将自动回退至普通编译模式。请重新执行步骤一至步骤四。
|
||||
|
||||
若日志压缩成功,终端将显示如下信息:
|
||||
```
|
||||
[0/1285] Log compression is being performed, please wait...
|
||||
Log compression underway, please wait...
|
||||
Found module BLE_MESH for compression
|
||||
Found 111 source files in module BLE_MESH requiring compression
|
||||
3055 ble log(s) compressed
|
||||
Header file for compressed logs generated
|
||||
```
|
||||
出现该信息表明压缩日志构建成功,其中输出的文件数目和日志数目可能会随版本变更而略有不同。
|
||||
|
||||
构建成功后,将在 `build/ble_log/` 目录下生成如下结构::
|
||||
```
|
||||
build/ble_log/
|
||||
├── ble_log_database
|
||||
│ └── BLE_MESH_logs.json
|
||||
├── ble_script_log_{timestamp}.log
|
||||
├── .compressed_srcs
|
||||
│ └── esp_ble_mesh
|
||||
├── include
|
||||
│ └── mesh_log_index.h
|
||||
└── module_info.yml
|
||||
```
|
||||
- `.compressed_srcs`: 压缩处理后的C代码文件。
|
||||
- `mesh_log_index.h`: 生成的日志宏头文件。
|
||||
- `BLE_MESH_logs.json`: 每条日志的详细信息。
|
||||
- `ble_script_log_{timestamp}.log`: 压缩日志在运行过程中产生的日志。
|
||||
- `module_info.yml`: 压缩日志对各个模块的配置文件。
|
||||
|
||||
**注意:这些为自动生成文件,请勿手动修改。**
|
||||
|
||||
### 步骤七、接收日志
|
||||
开启日志压缩后, 被压缩组件在默认配置下, 除`ERR`、`WARN`级别的日志外,其余级别的日志将会被重定向到压缩日志接口进行输出,接收日志的方法请参考BLE Log模块的说明文档:[BLE Log Module](../../README.md)
|
||||
|
||||
|
||||
## 常见问题解决
|
||||
1. 如果出现编码后的日志导致编译错误或者找不到宏定义,请删除`build`文件夹后重新构建,如果问题持续存在,请将问题反馈给 Espressif BLE 团队。
|
||||
@@ -1,124 +0,0 @@
|
||||
## BLE Log Compression Scheme (Preview)
|
||||
|
||||
### 一、Overview
|
||||
|
||||
This scheme scans the code of BLE stack-related components during the compilation phase, converting formatted strings and parameters in log statements into pure binary data. This improves log output efficiency and reduces the Flash footprint of the protocol stack.
|
||||
|
||||
Currently, the scheme supports log compression for both `BLE-MESH` and `BLE-HOST-BLUEDROID` components.
|
||||
|
||||
---
|
||||
|
||||
### 二、How to Use
|
||||
This feature requires additional Python libraries. Please follow the steps below to set up the environment.
|
||||
|
||||
### Step 1: Verify ESP-IDF Virtual Environment
|
||||
Ensure all subsequent steps are performed within the ESP-IDF Python virtual environment.
|
||||
|
||||
Verify activation by running:
|
||||
```bash
|
||||
idf.py --version
|
||||
```
|
||||
|
||||
If the output shows `idf.py: command not found`, the virtual environment is not active.
|
||||
|
||||
Refer to the official documentation to configure and activate the environment:
|
||||
[ESP-IDF Setup Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html)
|
||||
|
||||
After activation, run `idf.py --version` again. A version number confirms successful setup.
|
||||
|
||||
### Step 2: Check Python Version
|
||||
|
||||
Within the virtual environment, check the Python version:
|
||||
```bash
|
||||
python --version
|
||||
```
|
||||
If the version is lower than 3.8, upgrade Python by following the same official guide:
|
||||
[Python Upgrade Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html)
|
||||
|
||||
### Step 3: Install Log Compression Dependencies
|
||||
|
||||
Choose the appropriate command below based on your operating system and terminal environment to install the required dependencies:
|
||||
If you are using Linux or macos, please use the following command:
|
||||
- **Linux or macOS**:
|
||||
```bash
|
||||
pip install -r $IDF_PATH/components/bt/common/ble_log/log_compression/scripts/requirements.txt
|
||||
```
|
||||
- **Windows (PowerShell)**:
|
||||
```ps
|
||||
pip install -r $Env:IDF_PATH\components\bt\common\ble_log\log_compression\scripts\requirements.txt
|
||||
```
|
||||
- **Windows (Command Prompt - Cmd)**:
|
||||
```bat
|
||||
pip install -r %IDF_PATH%\components\bt\common\ble_log\log_compression\scripts\requirements.txt
|
||||
```
|
||||
|
||||
#### Step 4: Clean Build Cache
|
||||
After installing the dependencies, it is recommended to delete the existing build folder (if any) and rebuild the application to ensure a clean environment.
|
||||
|
||||
|
||||
### Step 5: Configure via Menuconfig
|
||||
|
||||
>
|
||||
|
||||
Run `idf.py menuconfig` and navigate to the following path to enable `BLE-MESH` log compression:
|
||||
|
||||
```(Top) -> Component config -> Bluetooth -> Common Options -> BLE Log -> Enable BLE log compression(Preview, Please read help information)->Enable BLE Mesh log compression(Preview)```.
|
||||
|
||||
There are three configuration items under this submenu:
|
||||
|
||||
- Mesh log buffer length: Sets the maximum length of a single log entry.
|
||||
|
||||
- Maximum number of tasks that can generate BLE mesh logs: Sets the maximum number of tasks that can output BLE-MESH logs (the default is recommended; avoid modifying this).
|
||||
|
||||
|
||||
### Step 6: Build the Application
|
||||
|
||||
After configuration, build the application with:
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
Watch for any warnings during the build process. For example:
|
||||
```txt
|
||||
CMake Warning at esp/esp-idf/components/bt/common/ble_log/log_compression/CMakeLists.txt:46 (message):
|
||||
tree_sitter import failed, please check whether the package is installed
|
||||
correctly,Please refer to the
|
||||
file: esp/esp-idf/components/bt/common/ble_log/log_compression/README
|
||||
for installation instructions.
|
||||
```
|
||||
This indicates that the dependencies were not installed correctly, and log compression has failed—falling back to a normal build. Please repeat Steps 1–4.
|
||||
|
||||
If log compression is successful, you will see output similar to:
|
||||
```
|
||||
[0/1285] Log compression is being performed, please wait...
|
||||
Log compression underway, please wait...
|
||||
Found module BLE_MESH for compression
|
||||
Found 111 source files in module BLE_MESH requiring compression
|
||||
3055 ble log(s) compressed
|
||||
Header file for compressed logs generated
|
||||
```
|
||||
After a successful build, the following structure will be generated under `build/ble_log/`:
|
||||
```
|
||||
build/ble_log/
|
||||
├── ble_log_database
|
||||
│ └── BLE_MESH_logs.json
|
||||
├── ble_script_log_{timestamp}.log
|
||||
├── .compressed_srcs
|
||||
│ └── esp_ble_mesh
|
||||
├── include
|
||||
│ └── mesh_log_index.h
|
||||
└── module_info.yml
|
||||
```
|
||||
- `.compressed_srcs`: Compressed C source files.
|
||||
- `mesh_log_index.h`: Generated header file containing log macros.
|
||||
- `BLE_MESH_logs.json`: Detailed information for each log entry.
|
||||
- `ble_script_log_{timestamp}.log`: Log generated by the compression script.
|
||||
- `module_info.yml`: Configuration file for compressed logging across modules.
|
||||
|
||||
**Do not modify these auto-generated files.**
|
||||
|
||||
### Step 7: Receive Logs
|
||||
With log compression enabled and under the default configuration, all log levels except ERR and WARN generated by the compressed component will be redirected to the compression-log interface for output. Please refer to the BLE Log module’s documentation for how to receive these logs: [BLE Log module](../../README.md).
|
||||
|
||||
## Frequently Asked Questions
|
||||
1. If encoded logs cause compilation errors or missing macro definitions, delete the build folder and rebuild. If the issue persists, please report it to the Espressif BLE team.
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Private includes
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "ble_log_util.h"
|
||||
#include "log_compression/utils.h"
|
||||
|
||||
#if CONFIG_BLE_COMPRESSED_LOG_ENABLE
|
||||
|
||||
#define BUF_NAME(name, idx) name##_buffer##idx
|
||||
#define BUF_MGMT_NAME(name) name##_log_buffer_mgmt
|
||||
|
||||
#define DECL_BUF_OP(name, len, idx) \
|
||||
static uint8_t BUF_NAME(name, idx)[len];
|
||||
|
||||
#define INIT_MAP_OP(name, _, buffer_idx) \
|
||||
{.busy = 0, \
|
||||
.idx = 0, \
|
||||
.buffer = BUF_NAME(name, buffer_idx), \
|
||||
.len = sizeof(BUF_NAME(name, buffer_idx))},
|
||||
|
||||
#define DECLARE_BUFFERS(NAME, BUF_LEN, BUF_CNT) \
|
||||
FOR_EACH_IDX(DECL_BUF_OP, NAME, BUF_LEN, GEN_INDEX(BUF_CNT));
|
||||
|
||||
#define INIT_BUFFER_MGMT(NAME, BUF_CNT) \
|
||||
ble_cp_log_buffer_mgmt_t BUF_MGMT_NAME(NAME)[BUF_CNT] = { \
|
||||
FOR_EACH_IDX(INIT_MAP_OP, NAME, 0, GEN_INDEX(BUF_CNT)) \
|
||||
};
|
||||
|
||||
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
|
||||
DECLARE_BUFFERS(mesh, CONFIG_BLE_MESH_COMPRESSED_LOG_BUFFER_LEN, LOG_CP_MAX_LOG_BUFFER_USED_SIMU);
|
||||
INIT_BUFFER_MGMT(mesh, LOG_CP_MAX_LOG_BUFFER_USED_SIMU);
|
||||
char * mesh_last_task_handle = NULL;
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE
|
||||
DECLARE_BUFFERS(host, CONFIG_BLE_HOST_COMPRESSED_LOG_BUFFER_LEN, LOG_CP_MAX_LOG_BUFFER_USED_SIMU);
|
||||
INIT_BUFFER_MGMT(host, LOG_CP_MAX_LOG_BUFFER_USED_SIMU);
|
||||
char * host_last_task_handle = NULL;
|
||||
#endif
|
||||
|
||||
/* The maximum number of supported parameters is 64 */
|
||||
#define LOG_HEADER(log_type, info) ((log_type << 6) | (info & 0x3f))
|
||||
|
||||
int ble_compressed_log_cb_get(uint8_t source, ble_cp_log_buffer_mgmt_t **mgmt)
|
||||
{
|
||||
ble_cp_log_buffer_mgmt_t *buffer_mgmt = NULL;
|
||||
char ** last_handle = NULL;
|
||||
char * cur_handle = pcTaskGetName(NULL);
|
||||
|
||||
switch (source)
|
||||
{
|
||||
#if CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE
|
||||
case BLE_COMPRESSED_LOG_OUT_SOURCE_MESH:
|
||||
buffer_mgmt = BUF_MGMT_NAME(mesh);
|
||||
last_handle = &mesh_last_task_handle;
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE
|
||||
case BLE_COMPRESSED_LOG_OUT_SOURCE_HOST:
|
||||
buffer_mgmt = BUF_MGMT_NAME(host);
|
||||
last_handle = &host_last_task_handle;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0 && "Unsupported log source");
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LOG_CP_MAX_LOG_BUFFER_USED_SIMU; i++) {
|
||||
if (ble_log_cas_acquire(&(buffer_mgmt[i].busy))) {
|
||||
*mgmt = &buffer_mgmt[i];
|
||||
ble_log_cp_push_u8(*mgmt, source);
|
||||
if (*last_handle == NULL ||
|
||||
*last_handle != cur_handle) {
|
||||
ble_log_cp_push_u8(*mgmt, LOG_HEADER(LOG_TYPE_INFO, LOG_TYPE_INFO_TASK_SWITCH));
|
||||
*last_handle = cur_handle;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int ble_compressed_log_buffer_free(ble_cp_log_buffer_mgmt_t *mgmt)
|
||||
{
|
||||
#if BLE_LOG_CP_CONTENT_CHECK_ENBALE
|
||||
memset(mgmt->buffer, BLE_LOG_CP_CONTENT_CHECK_VAL, mgmt->idx);
|
||||
#endif
|
||||
mgmt->idx = 0;
|
||||
ble_log_cas_release(&mgmt->busy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_log_compressed_hex_print(uint8_t source, uint32_t log_index, size_t args_cnt, ...)
|
||||
{
|
||||
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
|
||||
uint8_t arg_type = 0;
|
||||
va_list args;
|
||||
|
||||
ble_compressed_log_cb_get(source, &mgmt);
|
||||
|
||||
if (args_cnt == 0) {
|
||||
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_ARGS, 0));
|
||||
ble_log_cp_push_u16(mgmt, log_index);
|
||||
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
|
||||
ble_compressed_log_buffer_free(mgmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_start(args, args_cnt);
|
||||
|
||||
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_ARGS, args_cnt));
|
||||
ble_log_cp_push_u16(mgmt, log_index);
|
||||
uint8_t size_info_idx = mgmt->idx;
|
||||
uint8_t *cur = &(mgmt->buffer)[mgmt->idx];
|
||||
uint8_t size_info = 0;
|
||||
|
||||
for (size_t i = 0; i < args_cnt; i++) {
|
||||
if (i % 2) {
|
||||
arg_type = va_arg(args, size_t);
|
||||
ble_log_cp_push_u8(mgmt, size_info|arg_type);
|
||||
size_info = 0;
|
||||
cur++;
|
||||
} else {
|
||||
arg_type = va_arg(args, size_t);
|
||||
if (i == args_cnt - 1) {
|
||||
ble_log_cp_push_u8(mgmt, arg_type);
|
||||
} else {
|
||||
size_info = arg_type << 4;
|
||||
}
|
||||
}
|
||||
if (arg_type >= ARG_SIZE_TYPE_MAX) {
|
||||
printf("Found invalid arg type %08lx type %d", log_index, arg_type);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
cur = &(mgmt->buffer)[size_info_idx];
|
||||
|
||||
for (size_t i = 0; i < args_cnt; i++) {
|
||||
if (i % 2) {
|
||||
arg_type = (*cur) & 0x0f;
|
||||
cur++;
|
||||
} else {
|
||||
arg_type = (*cur) >> 4;
|
||||
}
|
||||
switch(arg_type) {
|
||||
case ARG_SIZE_TYPE_U32:
|
||||
uint32_t u32v = va_arg(args, size_t);
|
||||
if (likely(u32v)) {
|
||||
if (u32v <= 0xff) {
|
||||
ble_log_cp_push_u8(mgmt, 3);
|
||||
ble_log_cp_push_u8(mgmt, u32v);
|
||||
ble_log_cp_update_half_byte(mgmt, size_info_idx + i/2, ARG_SIZE_TYPE_LZU32, !(i%2));
|
||||
break;
|
||||
} else if (u32v <= 0xffff) {
|
||||
ble_log_cp_push_u8(mgmt, 2);
|
||||
ble_log_cp_push_u16(mgmt, u32v);
|
||||
ble_log_cp_update_half_byte(mgmt, size_info_idx + i/2, ARG_SIZE_TYPE_LZU32, !(i%2));
|
||||
break;
|
||||
} else {
|
||||
ble_log_cp_push_u32(mgmt, u32v);
|
||||
}
|
||||
} else {
|
||||
ble_log_cp_update_half_byte(mgmt, size_info_idx + i/2, ARG_SIZE_TYPE_AZU32, !(i%2));
|
||||
}
|
||||
break;
|
||||
case ARG_SIZE_TYPE_U64:
|
||||
uint64_t u64v = va_arg(args, uint64_t);
|
||||
if (likely(u64v)) {
|
||||
if (unlikely(u64v >> 48)) {
|
||||
ble_log_cp_push_u64(mgmt, u64v);
|
||||
} else {
|
||||
uint32_t tmpv = 0;
|
||||
uint8_t lz = 0;
|
||||
if (likely(u64v <= UINT32_MAX)) {
|
||||
tmpv = (uint32_t)u64v;
|
||||
lz = 4;
|
||||
} else {
|
||||
tmpv = u64v >> 32;
|
||||
}
|
||||
lz += __builtin_clz(tmpv) / 8;
|
||||
ble_log_cp_push_u8(mgmt, lz);
|
||||
switch (8-lz) {
|
||||
case 5:
|
||||
ble_log_cp_push_u32(mgmt, (uint32_t)u64v);
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
ble_log_cp_push_u8(mgmt, (uint8_t)tmpv);
|
||||
break;
|
||||
case 6:
|
||||
ble_log_cp_push_u32(mgmt, (uint32_t)u64v);
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
ble_log_cp_push_u16(mgmt, (uint16_t)tmpv);
|
||||
break;
|
||||
case 7:
|
||||
ble_log_cp_push_u32(mgmt, (uint32_t)u64v);
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
ble_log_cp_push_u8(mgmt, (uint8_t)tmpv);
|
||||
ble_log_cp_push_u16(mgmt, (uint16_t)(tmpv >> 8));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
ble_log_cp_update_half_byte(mgmt, size_info_idx + i/2, ARG_SIZE_TYPE_LZU64, !(i%2));
|
||||
}
|
||||
} else {
|
||||
ble_log_cp_update_half_byte(mgmt, size_info_idx + i/2, ARG_SIZE_TYPE_AZU64, !(i%2));
|
||||
}
|
||||
break;
|
||||
case ARG_SIZE_TYPE_STR:
|
||||
char *str_p = (char *)va_arg(args, char *);
|
||||
ble_log_cp_push_buf(mgmt, (const uint8_t *)str_p, strlen(str_p) + 1);
|
||||
break;
|
||||
default:
|
||||
printf("Invalid size %d\n", arg_type);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
|
||||
ble_compressed_log_buffer_free(mgmt);
|
||||
va_end(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_log_compressed_hex_print_buf(uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len)
|
||||
{
|
||||
ble_cp_log_buffer_mgmt_t *mgmt = NULL;
|
||||
|
||||
ble_compressed_log_cb_get(source, &mgmt);
|
||||
|
||||
if (buf == NULL && len != 0) {
|
||||
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_INFO, LOG_TYPE_INFO_NULL_BUF));
|
||||
ble_log_cp_push_u16(mgmt, log_index);
|
||||
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
|
||||
ble_compressed_log_buffer_free(mgmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ble_log_cp_push_u8(mgmt, LOG_HEADER(LOG_TYPE_HEX_BUF, buf_idx));
|
||||
ble_log_cp_push_u16(mgmt, log_index);
|
||||
ble_log_cp_push_buf(mgmt, buf, len);
|
||||
ble_compressed_log_output(source, mgmt->buffer, mgmt->idx);
|
||||
ble_compressed_log_buffer_free(mgmt);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BLE_COMPRESSED_LOG_ENABLE */
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
set(_BLE_HOST_TAG_MAP
|
||||
# BTM Layer
|
||||
CONFIG_BLE_BLUEDROID_BTM_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_ERROR_LOG_PRESERVE
|
||||
BTM_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_BTM_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_WARNING_LOG_PRESERVE
|
||||
BTM_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_BTM_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_API_LOG_PRESERVE
|
||||
BTM_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_BTM_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_EVENT_LOG_PRESERVE
|
||||
BTM_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_BTM_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_DEBUG_LOG_PRESERVE
|
||||
BTM_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_BTM_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_BTM_VERBOSE_LOG_PRESERVE
|
||||
BTM_TRACE_VERBOSE
|
||||
|
||||
# L2CAP Layer
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_ERROR_LOG_PRESERVE
|
||||
L2CAP_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_WARNING_LOG_PRESERVE
|
||||
L2CAP_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_API_LOG_PRESERVE
|
||||
L2CAP_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_EVENT_LOG_PRESERVE
|
||||
L2CAP_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_DEBUG_LOG_PRESERVE
|
||||
L2CAP_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_L2CAP_VERBOSE_LOG_PRESERVE
|
||||
L2CAP_TRACE_VERBOSE
|
||||
|
||||
# GAP Layer
|
||||
CONFIG_BLE_BLUEDROID_GAP_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_ERROR_LOG_PRESERVE
|
||||
GAP_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GAP_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_WARNING_LOG_PRESERVE
|
||||
GAP_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GAP_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_API_LOG_PRESERVE
|
||||
GAP_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GAP_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_EVENT_LOG_PRESERVE
|
||||
GAP_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GAP_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_DEBUG_LOG_PRESERVE
|
||||
GAP_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GAP_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GAP_VERBOSE_LOG_PRESERVE
|
||||
GAP_TRACE_VERBOSE
|
||||
|
||||
# GATT Layer
|
||||
CONFIG_BLE_BLUEDROID_GATT_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_ERROR_LOG_PRESERVE
|
||||
GATT_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GATT_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_WARNING_LOG_PRESERVE
|
||||
GATT_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GATT_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_API_LOG_PRESERVE
|
||||
GATT_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GATT_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_EVENT_LOG_PRESERVE
|
||||
GATT_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GATT_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_DEBUG_LOG_PRESERVE
|
||||
GATT_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_GATT_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_GATT_VERBOSE_LOG_PRESERVE
|
||||
GATT_TRACE_VERBOSE
|
||||
|
||||
# SMP Layer
|
||||
CONFIG_BLE_BLUEDROID_SMP_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_ERROR_LOG_PRESERVE
|
||||
SMP_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_SMP_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_WARNING_LOG_PRESERVE
|
||||
SMP_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_SMP_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_API_LOG_PRESERVE
|
||||
SMP_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_SMP_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_EVENT_LOG_PRESERVE
|
||||
SMP_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_SMP_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_DEBUG_LOG_PRESERVE
|
||||
SMP_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_SMP_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_SMP_VERBOSE_LOG_PRESERVE
|
||||
SMP_TRACE_VERBOSE
|
||||
|
||||
# APPL Layer
|
||||
CONFIG_BLE_BLUEDROID_APPL_ERROR_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_ERROR_LOG_PRESERVE
|
||||
APPL_TRACE_ERROR
|
||||
|
||||
CONFIG_BLE_BLUEDROID_APPL_WARNING_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_WARNING_LOG_PRESERVE
|
||||
APPL_TRACE_WARNING
|
||||
|
||||
CONFIG_BLE_BLUEDROID_APPL_API_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_API_LOG_PRESERVE
|
||||
APPL_TRACE_API
|
||||
|
||||
CONFIG_BLE_BLUEDROID_APPL_EVENT_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_EVENT_LOG_PRESERVE
|
||||
APPL_TRACE_EVENT
|
||||
|
||||
CONFIG_BLE_BLUEDROID_APPL_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_DEBUG_LOG_PRESERVE
|
||||
APPL_TRACE_DEBUG
|
||||
|
||||
CONFIG_BLE_BLUEDROID_APPL_VERBOSE_LOG_COMPRESSION
|
||||
CONFIG_BLE_BLUEDROID_APPL_VERBOSE_LOG_PRESERVE
|
||||
APPL_TRACE_VERBOSE
|
||||
|
||||
)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/tag_table_function.cmake)
|
||||
|
||||
set(BLE_HOST_TAGS "")
|
||||
set(BLE_HOST_TAGS_PRESERVE "")
|
||||
tag_table_to_lists(_BLE_HOST_TAG_MAP BLE_HOST_TAGS BLE_HOST_TAGS_PRESERVE)
|
||||
set(BLE_HOST_TAGS "${BLE_HOST_TAGS}" PARENT_SCOPE)
|
||||
set(BLE_HOST_TAGS_PRESERVE "${BLE_HOST_TAGS_PRESERVE}" PARENT_SCOPE)
|
||||
@@ -1,41 +0,0 @@
|
||||
set(_BLE_MESH_TAG_MAP
|
||||
CONFIG_BLE_MESH_STACK_ERR_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_STACK_ERR_LOG_PRESERVE
|
||||
BT_ERR
|
||||
|
||||
CONFIG_BLE_MESH_STACK_WARN_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_STACK_WARN_LOG_PRESERVE
|
||||
BT_WARN
|
||||
|
||||
CONFIG_BLE_MESH_STACK_INFO_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_STACK_INFO_LOG_PRESERVE
|
||||
BT_INFO
|
||||
|
||||
CONFIG_BLE_MESH_STACK_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_STACK_DEBUG_LOG_PRESERVE
|
||||
BT_DBG
|
||||
|
||||
CONFIG_BLE_MESH_NET_BUF_ERR_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_NET_BUF_ERR_LOG_PRESERVE
|
||||
NET_BUF_ERR
|
||||
|
||||
CONFIG_BLE_MESH_NET_BUF_WARN_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_NET_BUF_WARN_LOG_PRESERVE
|
||||
NET_BUF_WARN
|
||||
|
||||
CONFIG_BLE_MESH_NET_BUF_INFO_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_NET_BUF_INFO_LOG_PRESERVE
|
||||
NET_BUF_INFO
|
||||
|
||||
CONFIG_BLE_MESH_NET_BUF_DEBUG_LOG_COMPRESSION
|
||||
CONFIG_BLE_MESH_NET_BUF_DEBUG_LOG_PRESERVE
|
||||
NET_BUF_DBG
|
||||
)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/tag_table_function.cmake)
|
||||
|
||||
set(BLE_MESH_TAGS "")
|
||||
set(BLE_MESH_TAGS_PRESERVE "")
|
||||
tag_table_to_lists(_BLE_MESH_TAG_MAP BLE_MESH_TAGS BLE_MESH_TAGS_PRESERVE)
|
||||
set(BLE_MESH_TAGS "${BLE_MESH_TAGS}" PARENT_SCOPE)
|
||||
set(BLE_MESH_TAGS_PRESERVE "${BLE_MESH_TAGS_PRESERVE}" PARENT_SCOPE)
|
||||
@@ -1,33 +0,0 @@
|
||||
# Usage:
|
||||
# set(MY_TABLE CONFIG_FOO_ON CONFIG_FOO_KEEP TAG_FOO ...)
|
||||
# tag_table_to_lists(MY_TABLE OUT_TAGS OUT_PRESERVE)
|
||||
function(tag_table_to_lists TABLE_NAME OUT_TAGS OUT_PRESERVE)
|
||||
set(_tags "")
|
||||
set(_preserve "")
|
||||
set(_map ${${TABLE_NAME}})
|
||||
|
||||
list(LENGTH _map _len)
|
||||
math(EXPR _stop "${_len} - 1")
|
||||
|
||||
foreach(i RANGE 0 ${_stop} 3)
|
||||
math(EXPR _i1 "${i} + 1")
|
||||
math(EXPR _i2 "${i} + 2")
|
||||
|
||||
list(GET _map ${i} _comp)
|
||||
list(GET _map ${_i1} _pres)
|
||||
list(GET _map ${_i2} _tag)
|
||||
|
||||
if(${_comp})
|
||||
list(APPEND _tags "${_tag}")
|
||||
if(${_pres})
|
||||
list(APPEND _preserve "${_tag}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(JOIN _tags ", " _tags_str)
|
||||
list(JOIN _preserve ", " _preserve_str)
|
||||
|
||||
set(${OUT_TAGS} "${_tags_str}" PARENT_SCOPE)
|
||||
set(${OUT_PRESERVE} "${_preserve_str}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BLE_LOG_COMPRESSION_UTILS_H
|
||||
#define _BLE_LOG_COMPRESSION_UTILS_H
|
||||
|
||||
#include "ble_log.h"
|
||||
|
||||
#define CONCAT(a, b) a##b
|
||||
#define _CONCAT(a, b) CONCAT(a, b)
|
||||
|
||||
#define _0 0
|
||||
#define _1 1
|
||||
#define _2 2
|
||||
#define _3 3
|
||||
#define _4 4
|
||||
#define _5 5
|
||||
#define _6 6
|
||||
#define _7 7
|
||||
#define _8 8
|
||||
#define _9 9
|
||||
|
||||
#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _n, X...) _n
|
||||
#define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
|
||||
#define FOR_EACH_IDX(macro, name, len, ...) \
|
||||
_CONCAT(_FOR_EACH_, COUNT_ARGS(__VA_ARGS__))(macro, name, len, __VA_ARGS__)
|
||||
|
||||
#define _FOR_EACH_0(m, n, l, ...)
|
||||
#define _FOR_EACH_1(m, n, l, i1, ...) m(n, l, i1)
|
||||
#define _FOR_EACH_2(m, n, l, i1, ...) m(n, l, i1) _FOR_EACH_1(m, n, l, __VA_ARGS__)
|
||||
#define _FOR_EACH_3(m, n, l, i1, ...) m(n, l, i1) _FOR_EACH_2(m, n, l, __VA_ARGS__)
|
||||
#define _FOR_EACH_4(m, n, l, i1, ...) m(n, l, i1) _FOR_EACH_3(m, n, l, __VA_ARGS__)
|
||||
#define _FOR_EACH_5(m, n, l, i1, ...) m(n, l, i1) _FOR_EACH_4(m, n, l, __VA_ARGS__)
|
||||
|
||||
#define _GEN_INDEX_0()
|
||||
#define _GEN_INDEX_1() _0
|
||||
#define _GEN_INDEX_2() _0, _1
|
||||
#define _GEN_INDEX_3() _0, _1, _2
|
||||
#define _GEN_INDEX_4() _0, _1, _2, _3
|
||||
#define _GEN_INDEX_5() _0, _1, _2, _3, _4
|
||||
#define GEN_INDEX(n) _CONCAT(_GEN_INDEX_, n)()
|
||||
|
||||
|
||||
enum {
|
||||
BLE_COMPRESSED_LOG_OUT_SOURCE_HOST,
|
||||
BLE_COMPRESSED_LOG_OUT_SOURCE_MESH,
|
||||
};
|
||||
|
||||
enum {
|
||||
ARG_SIZE_TYPE_U32, /* argument type with 4 bytes */
|
||||
ARG_SIZE_TYPE_STR, /* argument type with strings */
|
||||
ARG_SIZE_TYPE_U64, /* argument type with 8 bytes */
|
||||
ARG_SIZE_TYPE_LZU32, /* argument type with 4 bytes but with leading zeros */
|
||||
ARG_SIZE_TYPE_LZU64, /* argument type with 8 bytes but with leading zeros */
|
||||
ARG_SIZE_TYPE_AZU32, /* argument type with 4 bytes but all zeros */
|
||||
ARG_SIZE_TYPE_AZU64, /* argument type with 8 bytes but all zeros */
|
||||
ARG_SIZE_TYPE_MAX,
|
||||
};
|
||||
|
||||
/* The maximum number of buffers used simultaneously */
|
||||
#define LOG_CP_MAX_LOG_BUFFER_USED_SIMU 3
|
||||
|
||||
#define LOG_TYPE_ZERO_ARGS 0
|
||||
#define LOG_TYPE_HEX_ARGS 1
|
||||
#define LOG_TYPE_HEX_BUF 2
|
||||
/* This type of message is used to update log information,
|
||||
* such as there is currently a new task log */
|
||||
#define LOG_TYPE_INFO 3
|
||||
|
||||
#define LOG_TYPE_INFO_TASK_ID_UPDATE 0
|
||||
#define LOG_TYPE_INFO_NULL_BUF 1
|
||||
#define LOG_TYPE_INFO_TASK_SWITCH 2
|
||||
|
||||
typedef struct {
|
||||
volatile bool busy;
|
||||
uint8_t *buffer;
|
||||
uint16_t idx;
|
||||
uint16_t len;
|
||||
} ble_cp_log_buffer_mgmt_t;
|
||||
|
||||
#define CONTENT_CHECK(idx, buf, except_val, len)
|
||||
#define LENGTH_CHECK(idx, pbuffer_mgmt) do ( if(unlikely((idx) > (pbuffer_mgmt->len))) assert(0 && "Maximum log buffer length exceeded");) while(0)
|
||||
|
||||
#define BLE_LOG_CP_CONTENT_CHECK_ENBALE 0
|
||||
#define BLE_LOG_CP_CONTENT_CHECK_VAL 0x00
|
||||
|
||||
static inline int ble_log_cp_buffer_safe_check(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, uint16_t write_len)
|
||||
{
|
||||
if ((pbuf_mgmt->idx + write_len) > pbuf_mgmt->len) {
|
||||
printf("Maximum length of buffer(%p) idx %d write_len %d exceed\n", pbuf_mgmt, pbuf_mgmt->idx, write_len);
|
||||
return -1;
|
||||
}
|
||||
#if BLE_LOG_CP_CONTENT_CHECK_ENBALE
|
||||
for (int i = pbuf_mgmt->idx; i < pbuf_mgmt->idx + write_len; i++) {
|
||||
if (pbuf_mgmt->buffer[i] != BLE_LOG_CP_CONTENT_CHECK_VAL) {
|
||||
printf("The value(%02x) in the buffer does not match the expected(%02x)\n", pbuf_mgmt->buffer[i], BLE_LOG_CP_CONTENT_CHECK_VAL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_push_u8(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, uint8_t val)
|
||||
{
|
||||
if (ble_log_cp_buffer_safe_check(pbuf_mgmt, 1)) {
|
||||
return -1;
|
||||
}
|
||||
pbuf_mgmt->buffer[pbuf_mgmt->idx] = val;
|
||||
pbuf_mgmt->idx++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_push_u16(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, uint16_t val)
|
||||
{
|
||||
if (ble_log_cp_buffer_safe_check(pbuf_mgmt, 2)) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t *p = (uint16_t *)&(pbuf_mgmt->buffer[pbuf_mgmt->idx]);
|
||||
*p = val;
|
||||
pbuf_mgmt->idx+=2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_push_u32(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, uint32_t val)
|
||||
{
|
||||
if (ble_log_cp_buffer_safe_check(pbuf_mgmt, 4)) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t *p = (uint32_t *)&(pbuf_mgmt->buffer[pbuf_mgmt->idx]);
|
||||
*p = val;
|
||||
pbuf_mgmt->idx+=4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_push_u64(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, uint64_t val)
|
||||
{
|
||||
if (ble_log_cp_buffer_safe_check(pbuf_mgmt, 8)) {
|
||||
return -1;
|
||||
}
|
||||
uint64_t *p = (uint64_t *)&(pbuf_mgmt->buffer[pbuf_mgmt->idx]);
|
||||
*p = val;
|
||||
pbuf_mgmt->idx+=8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_push_buf(ble_cp_log_buffer_mgmt_t *pbuf_mgmt, const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
if (ble_log_cp_buffer_safe_check(pbuf_mgmt, len)) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t *p = (uint8_t *)&(pbuf_mgmt->buffer[pbuf_mgmt->idx]);
|
||||
memcpy(p, buf, len);
|
||||
pbuf_mgmt->idx+=len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_update_half_byte(ble_cp_log_buffer_mgmt_t *pbuf_mgmt,
|
||||
uint16_t idx, uint8_t new_data, uint8_t high)
|
||||
{
|
||||
if (pbuf_mgmt->idx <= idx) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t old_val = pbuf_mgmt->buffer[idx];
|
||||
if (high) {
|
||||
pbuf_mgmt->buffer[idx] = (old_val & 0x0f) | (new_data << 4);
|
||||
} else {
|
||||
pbuf_mgmt->buffer[idx] = (old_val & 0xf0) | (new_data & 0x0f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_log_cp_buffer_print(ble_cp_log_buffer_mgmt_t *pbuf_mgmt)
|
||||
{
|
||||
for (size_t i = 0; i < pbuf_mgmt->idx; i++) {
|
||||
printf("%02x ", pbuf_mgmt->buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ble_compressed_log_output(uint8_t source, uint8_t *data, uint16_t len)
|
||||
{
|
||||
return ble_log_write_hex(BLE_LOG_SRC_ENCODE, data, len);
|
||||
}
|
||||
#endif /* _BLE_LOG_COMPRESSION_UTILS_H */
|
||||
@@ -1,440 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# ruff: noqa: UP007
|
||||
"""
|
||||
Log Database Manager
|
||||
====================
|
||||
Manages the storage and retrieval of compressed log metadata using a multiprocessing-safe database.
|
||||
"""
|
||||
|
||||
import atexit
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import threading
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Union
|
||||
|
||||
LOGGER = logging.getLogger('log_db_manager')
|
||||
|
||||
|
||||
class LogDBManager:
|
||||
"""Manages log compression metadata in a multiprocessing-safe manner."""
|
||||
|
||||
# Operation result codes
|
||||
SUCCESS = 0
|
||||
LOG_EXISTS = 1
|
||||
OPERATION_FAILED = 2
|
||||
|
||||
SOURCE_LOG_UPDATE_FULL = 0
|
||||
SOURCE_LOG_UPDATE_PARTIAL = 1
|
||||
SOURCE_LOG_UPDATE_NONE = 2
|
||||
|
||||
def __init__(self, data_dir: str, sources: Mapping[str, str], logger: Union[logging.Logger, None] = None):
|
||||
"""
|
||||
Initialize the log database manager.
|
||||
|
||||
Args:
|
||||
data_dir: Directory for database files
|
||||
sources: List of log sources/modules
|
||||
logger: Optional logger instance
|
||||
"""
|
||||
self.logger = logger or LOGGER
|
||||
self.data_dir = Path(data_dir)
|
||||
self.sources = [s.upper() for s in sources.keys()]
|
||||
self.source_cfg = sources
|
||||
self.sources_exist: dict[str, bool] = {s.upper(): False for s in sources.keys()}
|
||||
self.sources_updated: dict[str, int] = {s.upper(): 0 for s in sources.keys()}
|
||||
|
||||
# Create database directory
|
||||
self.data_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Setup multiprocessing infrastructure
|
||||
self.shared_data: dict[str, Any] = dict()
|
||||
self.locks: dict[str, Any] = dict()
|
||||
self.global_lock = threading.Lock()
|
||||
|
||||
# Initialize sources
|
||||
self._initialize_sources()
|
||||
|
||||
self._closed = False
|
||||
self.stop_event = threading.Event()
|
||||
atexit.register(self.safe_close)
|
||||
|
||||
self.logger.info(f'LogDB initialized for {len(self.sources)} sources in {self.data_dir}')
|
||||
|
||||
def _initialize_sources(self) -> None:
|
||||
"""Initialize database structures for all sources."""
|
||||
with self.global_lock:
|
||||
for source in self.sources:
|
||||
# Create source-specific structures
|
||||
self.shared_data[source] = dict(
|
||||
{
|
||||
'config': '',
|
||||
'files': dict(), # file_path -> {src_hash, compressed_hash}
|
||||
'logs': dict(), # log_id -> log_data
|
||||
'index': dict(), # unique_key -> log_id
|
||||
'max_id': 0,
|
||||
}
|
||||
)
|
||||
|
||||
# Create source-specific lock
|
||||
self.locks[source] = threading.Lock()
|
||||
|
||||
# Load existing data
|
||||
self._load_source(source)
|
||||
|
||||
def _source_file_path(self, source: str) -> Path:
|
||||
"""Get file path for a source's database file."""
|
||||
return self.data_dir / f'{source}_logs.json'
|
||||
|
||||
def _file_hash(self, file_path: Union[str, Path]) -> str:
|
||||
"""Compute SHA256 hash of a file's contents."""
|
||||
hasher = hashlib.sha256()
|
||||
file_path = Path(file_path)
|
||||
try:
|
||||
with file_path.open('rb') as f:
|
||||
while chunk := f.read(8192):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
except OSError as e:
|
||||
self.logger.error(f'Failed to compute hash for {file_path}: {e}')
|
||||
return ''
|
||||
|
||||
def is_config_updated(self, source: str) -> bool:
|
||||
return bool(self.source_cfg[source] != self.shared_data[source]['config'])
|
||||
|
||||
def is_file_processed(self, source: str, src_path: Union[str, Path], compressed_path: Union[str, Path]) -> bool:
|
||||
"""
|
||||
Check if a file has already been processed.
|
||||
|
||||
Args:
|
||||
source: Log source/module
|
||||
src_path: Original source file path
|
||||
compressed_path: Compressed version path
|
||||
|
||||
Returns:
|
||||
True if file has been processed, False otherwise
|
||||
"""
|
||||
source = source.upper()
|
||||
if source not in self.shared_data:
|
||||
self.logger.error(f'Unknown source: {source}')
|
||||
return False
|
||||
|
||||
src_hash = self._file_hash(src_path)
|
||||
compressed_hash = self._file_hash(compressed_path) if Path(compressed_path).exists() else ''
|
||||
|
||||
with self.locks[source]:
|
||||
files = self.shared_data[source]['files']
|
||||
file_info = files.get(str(src_path))
|
||||
|
||||
# Check if file is registered and hashes match
|
||||
if file_info:
|
||||
if file_info.get('src_hash') == src_hash and file_info.get('compressed_hash') == compressed_hash:
|
||||
return True
|
||||
|
||||
# Update hashes if changed
|
||||
file_info['src_hash'] = src_hash
|
||||
if compressed_hash:
|
||||
file_info['compressed_hash'] = compressed_hash
|
||||
return False
|
||||
|
||||
# New file
|
||||
files[str(src_path)] = dict({'src_hash': src_hash, 'compressed_hash': compressed_hash})
|
||||
return False
|
||||
|
||||
def mark_file_processed(self, source: str, src_path: Union[str, Path], compressed_path: Union[str, Path]) -> None:
|
||||
"""
|
||||
Mark a file as successfully processed.
|
||||
|
||||
Args:
|
||||
source: Log source/module
|
||||
src_path: Original source file path
|
||||
compressed_path: Compressed version path
|
||||
"""
|
||||
source = source.upper()
|
||||
if source not in self.shared_data:
|
||||
return
|
||||
|
||||
src_hash = self._file_hash(src_path)
|
||||
compressed_hash = self._file_hash(compressed_path)
|
||||
|
||||
with self.locks[source]:
|
||||
files = self.shared_data[source]['files']
|
||||
file_info = files.get(str(src_path), dict())
|
||||
file_info.update({'src_hash': src_hash, 'compressed_hash': compressed_hash})
|
||||
files[str(src_path)] = file_info
|
||||
|
||||
def _load_source(self, source: str) -> None:
|
||||
"""Load source data from JSON file."""
|
||||
db_file = self._source_file_path(source)
|
||||
|
||||
# Create empty database if not exists
|
||||
if not db_file.exists():
|
||||
with db_file.open('w') as f:
|
||||
json.dump({'config': '', 'files': {}, 'logs': {}}, f)
|
||||
return
|
||||
|
||||
try:
|
||||
with db_file.open('r') as f:
|
||||
data = json.load(f)
|
||||
except (OSError, json.JSONDecodeError) as e:
|
||||
self.logger.error(f'Error loading {source} database: {e}')
|
||||
return
|
||||
|
||||
files = {}
|
||||
logs = {}
|
||||
indexes = {}
|
||||
|
||||
with self.locks[source]:
|
||||
source_db = self.shared_data[source]
|
||||
|
||||
# Load config
|
||||
source_db['config'] = data.get('config', '')
|
||||
|
||||
# Load files
|
||||
source_db['files'].clear()
|
||||
for path, info in data.get('files', {}).items():
|
||||
files[path] = dict(info)
|
||||
|
||||
source_db['files'].update(files)
|
||||
|
||||
# Load logs
|
||||
source_db['logs'].clear()
|
||||
source_db['index'].clear()
|
||||
max_id = 0
|
||||
|
||||
for log_id, log_data in data.get('logs', {}).items():
|
||||
log_id = int(log_id)
|
||||
logs[log_id] = dict(log_data)
|
||||
unique_key = self._log_unique_key(log_data)
|
||||
indexes[unique_key] = log_id
|
||||
if log_id > max_id:
|
||||
max_id = log_id
|
||||
source_db['logs'].update(logs)
|
||||
source_db['index'].update(indexes)
|
||||
source_db['max_id'] = max_id
|
||||
self.sources_updated[source] = len(logs)
|
||||
self.sources_exist[source] = bool(data.get('logs'))
|
||||
|
||||
self.logger.info(f'Loaded {len(data.get("logs", {}))} logs for {source}')
|
||||
|
||||
def _save_source(self, source: str) -> bool:
|
||||
"""Save source data to JSON file using atomic write."""
|
||||
db_file = self._source_file_path(source)
|
||||
|
||||
# Prepare data
|
||||
with self.locks[source]:
|
||||
source_db = self.shared_data[source]
|
||||
config = self.source_cfg[source]
|
||||
files_data = {path: dict(info) for path, info in source_db['files'].items()}
|
||||
logs_data = {log_id: dict(data) for log_id, data in source_db['logs'].items()}
|
||||
|
||||
data = {'config': config, 'files': files_data, 'logs': logs_data}
|
||||
|
||||
# Atomic write
|
||||
tmp_path = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(mode='w', dir=self.data_dir, delete=False) as tmp_file:
|
||||
json.dump(data, tmp_file, indent=2)
|
||||
tmp_path = tmp_file.name
|
||||
|
||||
# Replace original file
|
||||
os.replace(tmp_path, db_file)
|
||||
return True
|
||||
except (OSError, TypeError) as e:
|
||||
self.logger.error(f'Error saving {source} database: {e}')
|
||||
if tmp_path and Path(tmp_path).exists():
|
||||
Path(tmp_path).unlink()
|
||||
return False
|
||||
|
||||
def _log_unique_key(self, log_data: dict) -> tuple:
|
||||
"""
|
||||
Create a unique key for a log entry.
|
||||
|
||||
Args:
|
||||
log_data: Log entry dictionary
|
||||
|
||||
Returns:
|
||||
Unique key tuple
|
||||
"""
|
||||
return (log_data['tag'], log_data['format'], log_data['caller'], log_data['file'], log_data['line_number'])
|
||||
|
||||
def add_log(
|
||||
self,
|
||||
source: str,
|
||||
log_tag: str,
|
||||
log_format: str,
|
||||
log_line_number: int,
|
||||
hexify: bool,
|
||||
caller_func: str,
|
||||
caller_line: int,
|
||||
file_name: str,
|
||||
) -> tuple[int, int]:
|
||||
"""
|
||||
Add a new log entry to the database if it doesn't exist.
|
||||
|
||||
Args:
|
||||
source: Log source/module
|
||||
log_tag: Log tag
|
||||
log_format: Log format string
|
||||
log_line_number: Log Line number
|
||||
hexify: Whether the log can be hexified
|
||||
caller_func: Calling function name
|
||||
caller_line: Calling function line number
|
||||
file_name: Source file name
|
||||
|
||||
Returns:
|
||||
Tuple (result_code, log_id)
|
||||
"""
|
||||
if self._closed:
|
||||
return self.OPERATION_FAILED, 0
|
||||
|
||||
source = source.upper()
|
||||
if source not in self.shared_data:
|
||||
self.logger.error(f'Unknown source: {source}')
|
||||
return self.OPERATION_FAILED, 0
|
||||
|
||||
log_data = {
|
||||
'tag': log_tag,
|
||||
'format': log_format,
|
||||
'line_number': log_line_number,
|
||||
'hexify': hexify,
|
||||
'caller': caller_func,
|
||||
'caller_line': caller_line,
|
||||
'file': file_name,
|
||||
}
|
||||
|
||||
unique_key = self._log_unique_key(log_data)
|
||||
|
||||
with self.locks[source]:
|
||||
source_db = self.shared_data[source]
|
||||
|
||||
# Check if log exists
|
||||
if unique_key in source_db['index']:
|
||||
existing_id = source_db['index'][unique_key]
|
||||
return self.LOG_EXISTS, existing_id
|
||||
|
||||
# Create new log entry
|
||||
new_id = source_db['max_id'] + 1
|
||||
log_data['id'] = new_id
|
||||
|
||||
source_db['logs'][new_id] = dict(log_data)
|
||||
source_db['index'][unique_key] = new_id
|
||||
source_db['max_id'] = new_id
|
||||
|
||||
self.logger.info(f'Added new log [{source}]: ID={new_id}, Tag={log_tag}')
|
||||
return self.SUCCESS, new_id
|
||||
|
||||
def remove_log(self, source: str, log_id: int) -> bool:
|
||||
"""
|
||||
Remove a log entry from the database.
|
||||
|
||||
Args:
|
||||
source: Log source/module
|
||||
log_id: ID of log to remove
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
source = source.upper()
|
||||
if source not in self.shared_data:
|
||||
return False
|
||||
|
||||
with self.locks[source]:
|
||||
source_db = self.shared_data[source]
|
||||
|
||||
if log_id not in source_db['logs']:
|
||||
return False
|
||||
|
||||
# Remove from indexes
|
||||
log_data = dict(source_db['logs'][log_id])
|
||||
unique_key = self._log_unique_key(log_data)
|
||||
|
||||
if unique_key in source_db['index']:
|
||||
del source_db['index'][unique_key]
|
||||
del source_db['logs'][log_id]
|
||||
|
||||
if log_id == source_db['max_id']:
|
||||
source_db['max_id'] = max(source_db['logs'].keys()) if source_db['logs'] else 0
|
||||
|
||||
return True
|
||||
|
||||
def source_update_state(self, source: str) -> int:
|
||||
if self.is_config_updated(source):
|
||||
return self.SOURCE_LOG_UPDATE_FULL
|
||||
if self.sources_updated[source] == len(self.shared_data[source]['logs']):
|
||||
return self.SOURCE_LOG_UPDATE_NONE
|
||||
elif self.sources_updated[source] == 0 and len(self.shared_data[source]['logs']) != 0:
|
||||
return self.SOURCE_LOG_UPDATE_FULL
|
||||
else:
|
||||
return self.SOURCE_LOG_UPDATE_PARTIAL
|
||||
|
||||
def save_source(self, source: str) -> bool:
|
||||
"""Save a single source's data to file."""
|
||||
return self._save_source(source.upper())
|
||||
|
||||
def save_all(self) -> int:
|
||||
"""Save all sources' data to files."""
|
||||
self.logger.debug('Saving all sources...')
|
||||
success_count = 0
|
||||
|
||||
for source in self.sources:
|
||||
if (not self.is_config_updated(source)) and self.sources_updated[source] == len(
|
||||
self.shared_data[source]['logs']
|
||||
):
|
||||
self.logger.info(f'{source} has not updated data')
|
||||
continue
|
||||
if self._save_source(source):
|
||||
success_count += 1
|
||||
|
||||
self.logger.info(f'Saved {success_count}/{len(self.sources)} sources')
|
||||
return success_count
|
||||
|
||||
def safe_close(self) -> None:
|
||||
"""Safe close method that handles atexit callbacks."""
|
||||
if not self._closed:
|
||||
try:
|
||||
self.close()
|
||||
except Exception as e:
|
||||
# Log to stderr as logging may be shutdown
|
||||
print(f'Error during safe_close: {e}', flush=True)
|
||||
|
||||
def close(self) -> None:
|
||||
"""Cleanup resources."""
|
||||
if self._closed:
|
||||
return
|
||||
|
||||
self._closed = True
|
||||
|
||||
try:
|
||||
if not self.stop_event.is_set():
|
||||
self.stop_event.set()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.logger.info('Closing database manager...')
|
||||
self.stop_event.set()
|
||||
|
||||
# Final save
|
||||
self.logger.info('Performing final save...')
|
||||
self.save_all()
|
||||
|
||||
# Shutdown manager
|
||||
self.logger.info('Database manager closed')
|
||||
|
||||
def __enter__(self) -> 'LogDBManager':
|
||||
return self
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: Union[type[BaseException], None],
|
||||
exc_val: Union[BaseException, None],
|
||||
exc_tb: Union[TracebackType, None],
|
||||
) -> None:
|
||||
self.close()
|
||||
@@ -1,967 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# The current project needs to support environments before Python 3.9,
|
||||
# and UP007 will prohibit the use of Tuple, Union, etc.
|
||||
# ruff: noqa: UP007
|
||||
|
||||
# The current project needs to support environments before Python 3.9,
|
||||
# Therefore, it is necessary to prohibit UP006 from automatically
|
||||
# changing the annotation type
|
||||
# ruff: noqa: UP006
|
||||
# ruff: noqa: UP035
|
||||
|
||||
"""
|
||||
BLE Log Compression Utility
|
||||
===========================
|
||||
This script processes Bluetooth source files to compress logging statements.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import enum
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import textwrap
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
import tree_sitter_c as tsc
|
||||
import yaml
|
||||
from c_format_parse import parse_format_string
|
||||
from inttypes_map import TYPES_MACRO_MAP
|
||||
from LogDBManager import LogDBManager
|
||||
|
||||
try:
|
||||
import importlib.metadata as meta
|
||||
|
||||
_TS_VER = tuple(map(int, meta.version('tree-sitter').split('.')[:2]))
|
||||
except Exception:
|
||||
_TS_VER = (0, 20)
|
||||
|
||||
if _TS_VER >= (0, 21):
|
||||
from tree_sitter import Language
|
||||
from tree_sitter import Node
|
||||
from tree_sitter import Parser
|
||||
from tree_sitter import Query
|
||||
from tree_sitter import Tree
|
||||
|
||||
if _TS_VER >= (0, 25):
|
||||
from tree_sitter import QueryCursor
|
||||
else:
|
||||
from tree_sitter import Language
|
||||
from tree_sitter import Parser
|
||||
from tree_sitter import Tree
|
||||
|
||||
# Initialize logger
|
||||
LOGGER = logging.getLogger('ble_log_compression')
|
||||
|
||||
# Global parser instances
|
||||
C_LANGUAGE: Union[Language, None] = None
|
||||
CLANG_PARSER: Union[Parser, None] = None
|
||||
|
||||
# Log source enumeration
|
||||
SOURCE_ENUM_MAP = {
|
||||
'BLE_HOST': 0,
|
||||
'BLE_MESH': 1,
|
||||
}
|
||||
|
||||
# Functions that require hex formatting
|
||||
HEX_FUNCTIONS = ['bt_hex'] # Used in Mesh and Audio modules
|
||||
|
||||
# C keywords to exclude from function names
|
||||
C_KEYWORDS = {
|
||||
'auto',
|
||||
'break',
|
||||
'case',
|
||||
'char',
|
||||
'const',
|
||||
'continue',
|
||||
'default',
|
||||
'do',
|
||||
'double',
|
||||
'else',
|
||||
'enum',
|
||||
'extern',
|
||||
'float',
|
||||
'for',
|
||||
'goto',
|
||||
'if',
|
||||
'int',
|
||||
'long',
|
||||
'register',
|
||||
'return',
|
||||
'short',
|
||||
'signed',
|
||||
'sizeof',
|
||||
'static',
|
||||
'struct',
|
||||
'switch',
|
||||
'typedef',
|
||||
'union',
|
||||
'unsigned',
|
||||
'void',
|
||||
'volatile',
|
||||
'while',
|
||||
}
|
||||
|
||||
FUNC_MACROS = {'__func__', '__FUNCTION__'}
|
||||
|
||||
LINE_MACROS = {
|
||||
'__LINE__',
|
||||
}
|
||||
|
||||
BLUEDROID_LOG_MODE_LEVEL_GET = {
|
||||
'BTM': 'btm_cb.trace_level',
|
||||
'L2CAP': 'l2cb.l2cap_trace_level',
|
||||
'GAP': 'gap_cb.trace_level',
|
||||
'GATT': 'gatt_cb.trace_level',
|
||||
'SMP': 'smp_cb.trace_level',
|
||||
'APPL': 'appl_trace_level',
|
||||
}
|
||||
|
||||
|
||||
class ARG_SIZE_TYPE(enum.IntEnum):
|
||||
U32 = 0
|
||||
STR = 1
|
||||
U64 = 2
|
||||
LZU32 = 3
|
||||
LZU64 = 4
|
||||
AZU32 = 5
|
||||
AZU64 = 6
|
||||
|
||||
|
||||
def TsInit() -> Tuple[Language, Parser]:
|
||||
if _TS_VER > (0, 21):
|
||||
lang = Language(tsc.language())
|
||||
parser = Parser(lang)
|
||||
return lang, parser
|
||||
else:
|
||||
lang = Language(tsc.language(), 'c')
|
||||
parser = Parser()
|
||||
parser.set_language(lang)
|
||||
return lang, parser
|
||||
|
||||
|
||||
def TsQueryByTree(language: Language, tree: Tree, query_str: str) -> Dict[str, List[Node]]:
|
||||
if _TS_VER == (0, 21):
|
||||
captures_res = language.query(query_str).captures(tree.root_node)
|
||||
elif _TS_VER > (0, 21) and _TS_VER < (0, 25):
|
||||
captures_res = Query(language, (query_str)).captures(tree.root_node)
|
||||
else:
|
||||
captures_res = QueryCursor(Query(language, (query_str))).captures(tree.root_node)
|
||||
|
||||
captures: Dict[str, List[Node]] = {}
|
||||
if isinstance(captures_res, list):
|
||||
for node, node_type in captures_res:
|
||||
if node_type not in captures:
|
||||
captures[node_type] = []
|
||||
captures[node_type].append(node)
|
||||
else:
|
||||
captures = captures_res
|
||||
return captures
|
||||
|
||||
|
||||
class LogCompressor:
|
||||
"""Main class for BLE log compression."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.bt_component_path = Path()
|
||||
self.build_dir = Path()
|
||||
self.bt_compressed_srcs_path = Path()
|
||||
self.config: dict[str, Any] = {}
|
||||
self.module_info: dict[str, Any] = {}
|
||||
|
||||
def init_parser(self) -> Parser:
|
||||
"""Initialize tree-sitter parser for C."""
|
||||
global C_LANGUAGE, CLANG_PARSER
|
||||
|
||||
C_LANGUAGE, CLANG_PARSER = TsInit()
|
||||
|
||||
return CLANG_PARSER
|
||||
|
||||
def extract_log_calls(self, code_content: bytes, log_tags: list[str]) -> list[dict]:
|
||||
"""
|
||||
Extract log statements from C source code.
|
||||
|
||||
Args:
|
||||
code_content: Source code as bytes
|
||||
log_tags: List of log tags to search for
|
||||
|
||||
Returns:
|
||||
List of dictionaries containing log information
|
||||
"""
|
||||
parser = self.init_parser()
|
||||
tree = parser.parse(code_content)
|
||||
function_map = self._get_function_boundaries(tree)
|
||||
return self._find_log_statements(tree, log_tags, function_map)
|
||||
|
||||
def _get_function_boundaries(self, tree: Tree) -> list[tuple[str, int, int, int]]:
|
||||
"""
|
||||
Identify function boundaries in the AST.
|
||||
|
||||
Returns:
|
||||
List of tuples (function_name, start_byte, end_byte, line_number)
|
||||
"""
|
||||
function_query = """
|
||||
[
|
||||
(function_declarator
|
||||
(identifier) @func_name
|
||||
)
|
||||
(declaration
|
||||
(function_declarator
|
||||
(identifier) @func_decls
|
||||
)
|
||||
)
|
||||
]
|
||||
"""
|
||||
captures: dict[str, list[Node]] = TsQueryByTree(C_LANGUAGE, tree, function_query)
|
||||
|
||||
# Filter valid function names
|
||||
func_names = [
|
||||
node
|
||||
for node in captures.get('func_name', [])
|
||||
if node not in captures.get('func_decls', []) and node.text.decode('utf-8') not in C_KEYWORDS
|
||||
]
|
||||
|
||||
# Sort by start byte
|
||||
func_names.sort(key=lambda node: node.start_byte)
|
||||
boundaries = []
|
||||
|
||||
for i, node in enumerate(func_names):
|
||||
func_name = node.text.decode('utf-8')
|
||||
start_byte = node.start_byte
|
||||
end_byte = func_names[i + 1].start_byte if i < len(func_names) - 1 else len(tree.root_node.text)
|
||||
line_number = node.start_point[0] + 1
|
||||
boundaries.append((func_name, start_byte, end_byte, line_number))
|
||||
|
||||
return boundaries
|
||||
|
||||
def _find_log_statements(
|
||||
self, tree: Tree, log_tags: list[str], function_boundaries: list[tuple[str, int, int, int]]
|
||||
) -> list[dict]:
|
||||
"""
|
||||
Find log statements in the AST.
|
||||
|
||||
Args:
|
||||
tree: Parsed AST tree
|
||||
log_tags: List of log tags to search for
|
||||
function_boundaries: Function boundaries list
|
||||
|
||||
Returns:
|
||||
List of log information dictionaries
|
||||
"""
|
||||
# Build pattern for matching log tags
|
||||
tag_pattern = '|'.join(log_tags)
|
||||
log_query = f"""
|
||||
(expression_statement
|
||||
(call_expression
|
||||
function: (identifier) @fname
|
||||
arguments: (argument_list) @args
|
||||
(#match? @fname "^({tag_pattern})$")
|
||||
) @log_stmt
|
||||
)
|
||||
"""
|
||||
captures: dict[str, list[Node]] = TsQueryByTree(C_LANGUAGE, tree, log_query)
|
||||
log_nodes = captures.get('log_stmt', [])
|
||||
|
||||
# It is necessary to ensure that the nodes
|
||||
# are sorted according to the starting bytes,
|
||||
# because only the nodes are ordered can ensure
|
||||
# that the subsequent calculation offset is correct.
|
||||
log_nodes.sort(key=lambda node: node.start_byte)
|
||||
logs = []
|
||||
|
||||
for node in log_nodes:
|
||||
try:
|
||||
log_info = self._process_log_node(node, function_boundaries)
|
||||
if log_info:
|
||||
logs.append(log_info)
|
||||
except Exception as e:
|
||||
LOGGER.error(f'Error processing log node: {e}\n{traceback.format_exc()}')
|
||||
raise
|
||||
|
||||
return logs
|
||||
|
||||
def _process_log_node(self, node: Node, function_boundaries: list[tuple[str, int, int, int]]) -> Union[dict, None]:
|
||||
"""
|
||||
Process a log AST node and extract information.
|
||||
|
||||
Args:
|
||||
node: Log statement AST node
|
||||
function_boundaries: Function boundaries list
|
||||
|
||||
Returns:
|
||||
Log information dictionary or None if invalid
|
||||
"""
|
||||
# Extract basic information
|
||||
tag_node = node.child_by_field_name('function')
|
||||
if not tag_node:
|
||||
return None
|
||||
|
||||
tag = tag_node.text.decode('utf-8')
|
||||
|
||||
args_node = node.child_by_field_name('arguments')
|
||||
if not args_node or args_node.type != 'argument_list':
|
||||
return None
|
||||
|
||||
# Initialize log info
|
||||
log_info = {
|
||||
'tag': (tag, tag_node.start_byte, tag_node.end_byte),
|
||||
'line_number': node.start_point[0] + 1,
|
||||
'arguments': [],
|
||||
'hexify': True,
|
||||
}
|
||||
|
||||
# Process format string (first argument)
|
||||
valid_arg_childrn: list[Node] = [n for n in args_node.named_children if n.type != 'comment']
|
||||
fmt_node = valid_arg_childrn[0] if len(valid_arg_childrn) > 0 else None
|
||||
if not fmt_node:
|
||||
return None
|
||||
|
||||
if fmt_node.type == 'concatenated_string':
|
||||
log_fmt = self._process_concatenated_string(fmt_node)
|
||||
elif fmt_node.type == 'string_literal':
|
||||
log_fmt = fmt_node.text.decode('utf-8')[1:-1] # Remove quotes
|
||||
else:
|
||||
return None
|
||||
|
||||
log_info['arguments'].append((f'"{log_fmt}"', fmt_node.start_byte, fmt_node.end_byte))
|
||||
|
||||
# Parse format tokens
|
||||
tokens = parse_format_string(f'"{log_fmt}"')
|
||||
tokens_tuple_map: list[int] = []
|
||||
for idx, tk in enumerate(tokens):
|
||||
if isinstance(tk, tuple):
|
||||
tokens_tuple_map.append(idx)
|
||||
|
||||
arguments: list[Node] = valid_arg_childrn[1:]
|
||||
|
||||
if len(arguments) != len(tokens_tuple_map):
|
||||
raise SyntaxError(f'LogSyntaxError:{node.text.decode("utf-8")}')
|
||||
|
||||
# Process each argument
|
||||
for i, (token, arg_node) in enumerate(zip([t for t in tokens if isinstance(t, tuple)], arguments)):
|
||||
arg_text = arg_node.text.decode('utf-8')
|
||||
log_info['arguments'].append((arg_text, arg_node.start_byte, arg_node.end_byte))
|
||||
|
||||
# Check if argument can be hexified
|
||||
# if not self._can_be_hexified(token, arg_node):
|
||||
# log_info['hexify'] = False
|
||||
|
||||
# Handle special identifiers
|
||||
if arg_text in FUNC_MACROS:
|
||||
token_list = list(token)
|
||||
token_list[6] = '@func' # Modify conversion char to special marker
|
||||
tokens[tokens_tuple_map[i]] = tuple(token_list)
|
||||
elif arg_text in LINE_MACROS:
|
||||
token_list = list(token)
|
||||
token_list[6] = '@line'
|
||||
tokens[tokens_tuple_map[i]] = tuple(token_list)
|
||||
|
||||
# Handle hex functions
|
||||
if (
|
||||
arg_node.type == 'call_expression'
|
||||
and arg_node.child_by_field_name('function')
|
||||
and arg_node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS
|
||||
):
|
||||
# Extract arguments of the hex function
|
||||
hex_args = arg_node.child_by_field_name('arguments')
|
||||
if hex_args and hex_args.named_child_count >= 2:
|
||||
buf_node = hex_args.named_children[0]
|
||||
len_node = hex_args.named_children[1]
|
||||
token_list = list(token)
|
||||
token_list[6] = f'@hex_func@{buf_node.text.decode("utf-8")}@{len_node.text.decode("utf-8")}'
|
||||
tokens[tokens_tuple_map[i]] = tuple(token_list)
|
||||
|
||||
log_info['argu_tokens'] = tokens
|
||||
|
||||
# Find calling function
|
||||
caller_info = self._find_calling_function(node.start_byte, function_boundaries)
|
||||
if not caller_info:
|
||||
return None
|
||||
|
||||
log_info.update(caller_info)
|
||||
return log_info
|
||||
|
||||
def _process_concatenated_string(self, node: Node) -> str:
|
||||
"""Process a concatenated string node into a single string."""
|
||||
parts = []
|
||||
for child in node.named_children:
|
||||
if child.type == 'identifier':
|
||||
identifier = child.text.decode('utf-8')
|
||||
if identifier in TYPES_MACRO_MAP:
|
||||
parts.append(TYPES_MACRO_MAP[identifier])
|
||||
else:
|
||||
raise ValueError(f'Unknown format macro: {identifier}')
|
||||
elif child.type == 'string_literal':
|
||||
parts.append(child.text.decode('utf-8')[1:-1]) # Remove quotes
|
||||
else:
|
||||
raise ValueError(f'Unsupported node in concatenated string: {child.type}')
|
||||
return ''.join(parts)
|
||||
|
||||
def _can_be_hexified(self, token: tuple[int, int, str, str, str, str, str], node: Node) -> bool:
|
||||
"""Determine if a node can be represented in hex format."""
|
||||
if token[-1] != 's':
|
||||
return True
|
||||
|
||||
if node.type == 'identifier' and node.text.decode('utf-8') in FUNC_MACROS:
|
||||
return True
|
||||
|
||||
if (
|
||||
node.type == 'call_expression'
|
||||
and node.child_by_field_name('function')
|
||||
and node.child_by_field_name('function').text.decode('utf-8') in HEX_FUNCTIONS
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _find_calling_function(
|
||||
self, log_start: int, function_boundaries: list[tuple[str, int, int, int]]
|
||||
) -> Union[dict, None]:
|
||||
"""
|
||||
Find the function containing the log statement.
|
||||
|
||||
Args:
|
||||
log_start: Start byte of the log statement
|
||||
function_boundaries: List of function boundaries
|
||||
|
||||
Returns:
|
||||
Dictionary with caller information or None if not found
|
||||
"""
|
||||
for name, start, end, line in function_boundaries:
|
||||
if start <= log_start < end:
|
||||
return {'caller_name': name, 'caller_line_number': line}
|
||||
return None
|
||||
|
||||
def generate_compressed_macro(
|
||||
self, source: str, log_idx: int, tag: str, print_fmt: Union[str, None], log_info: dict
|
||||
) -> str:
|
||||
"""
|
||||
Generate a compressed log macro definition.
|
||||
|
||||
Args:
|
||||
source: Log source module
|
||||
log_idx: Unique log index
|
||||
tag: Original log tag
|
||||
print_fmt: Simplified format string
|
||||
log_info: Log information dictionary
|
||||
|
||||
Returns:
|
||||
Macro definition string
|
||||
"""
|
||||
if not log_idx:
|
||||
return ''
|
||||
|
||||
def generate_mesh_log_prefix(source: str, tag: str, print_statm: str) -> str:
|
||||
level = tag.split('_')[-1]
|
||||
mod = tag.split('_')[0]
|
||||
if level == 'ERR':
|
||||
level = 'ERROR'
|
||||
log_level = 'BLE_MESH_LOG_LEVEL_ERROR'
|
||||
elif level == 'WARN':
|
||||
level = 'WARN'
|
||||
log_level = 'BLE_MESH_LOG_LEVEL_WARN'
|
||||
elif level == 'INFO':
|
||||
level = 'INFO'
|
||||
log_level = 'BLE_MESH_LOG_LEVEL_INFO'
|
||||
elif level == 'DBG':
|
||||
level = 'DEBUG'
|
||||
log_level = 'BLE_MESH_LOG_LEVEL_DEBUG'
|
||||
else:
|
||||
LOGGER.error(f'Invalid log level {level}')
|
||||
return ''
|
||||
if mod == 'NET':
|
||||
used_log_levl = 'BLE_MESH_NET_BUF_LOG_LEVEL'
|
||||
used_log_mod = 'BLE_MESH_NET_BUF'
|
||||
else:
|
||||
used_log_levl = 'BLE_MESH_LOG_LEVEL'
|
||||
used_log_mod = 'BLE_MESH'
|
||||
return (
|
||||
f'{{do {{ if (({used_log_levl} >= {log_level}) &&'
|
||||
f' BLE_MESH_LOG_LEVEL_CHECK({used_log_mod}, {level})) {print_statm};}} while (0);}}\\\n'
|
||||
)
|
||||
|
||||
def generate_bluedroid_log_prefix(source: str, tag: str, print_statm: str) -> str:
|
||||
tag_info = tag.split('_')
|
||||
mod = tag_info[0]
|
||||
|
||||
return (
|
||||
f'{{if ({BLUEDROID_LOG_MODE_LEVEL_GET[mod]} >= BT_TRACE_LEVEL_{tag_info[-1]} &&'
|
||||
f' BT_LOG_LEVEL_CHECK({mod}, {tag_info[-1]})) {print_statm};}}\\\n'
|
||||
)
|
||||
|
||||
def generate_log_lvl_prefix(source: str, tag: str, print_statm: str) -> str:
|
||||
if source == 'BLE_MESH':
|
||||
return ' ' + generate_mesh_log_prefix(source, tag, print_statm)
|
||||
elif source == 'BLE_HOST': # only bluedroid host supported for now
|
||||
return ' ' + generate_bluedroid_log_prefix(source, tag, print_statm)
|
||||
else:
|
||||
LOGGER.error(f'Unknown source {source}')
|
||||
return ''
|
||||
|
||||
source_value = SOURCE_ENUM_MAP.get(source.upper())
|
||||
if source_value is None:
|
||||
raise ValueError(f'Invalid source: {source}')
|
||||
|
||||
macro = f'#define {tag}_{log_idx}(fmt, ...) {{\\\n'
|
||||
|
||||
if log_info['hexify']:
|
||||
# Count of arguments that are not special (__func__, __LINE__, etc.)
|
||||
arg_tokens = [t for t in log_info['argu_tokens'] if isinstance(t, tuple)]
|
||||
arg_count = len(arg_tokens)
|
||||
arguments = []
|
||||
sizes = []
|
||||
hex_func: list[str] = []
|
||||
|
||||
LOGGER.info(f'{arg_tokens}:{[a[0] for a in log_info["arguments"]]}')
|
||||
|
||||
for token, argument in zip(
|
||||
arg_tokens,
|
||||
[a[0] for a in log_info['arguments'][1:]],
|
||||
):
|
||||
# Skip special tokens
|
||||
if token[6] in ('@func', '@line'):
|
||||
arg_count -= 1
|
||||
continue
|
||||
|
||||
# Handle hex function
|
||||
if token[6].startswith('@hex_func'):
|
||||
if not hex_func:
|
||||
hex_func = []
|
||||
hex_func.append(token[6])
|
||||
arg_count -= 1
|
||||
continue
|
||||
|
||||
arguments.append(argument)
|
||||
|
||||
if token[6] == 'f' or token[5] == 'll': # float or long long
|
||||
sizes.append(f'{int(ARG_SIZE_TYPE.U64)}')
|
||||
elif token[6] == 's':
|
||||
sizes.append(f'{int(ARG_SIZE_TYPE.STR)}')
|
||||
else:
|
||||
sizes.append(f'{int(ARG_SIZE_TYPE.U32)}')
|
||||
|
||||
if arg_count > 0:
|
||||
size_str = ', '.join(sizes)
|
||||
arg_str = ', '.join(arguments).replace('\n', '')
|
||||
macro += generate_log_lvl_prefix(
|
||||
source,
|
||||
tag,
|
||||
(f'BLE_LOG_COMPRESSED_HEX_PRINT({source_value}, {log_idx}, {arg_count}, {size_str}, {arg_str})'),
|
||||
)
|
||||
|
||||
for idx, item in enumerate(hex_func):
|
||||
# hex_func format: @hex_func@buf@len
|
||||
parts = item.split('@')
|
||||
if len(parts) >= 4:
|
||||
buf = parts[2]
|
||||
buf_len = parts[3]
|
||||
macro += generate_log_lvl_prefix(
|
||||
source,
|
||||
tag,
|
||||
(f'BLE_LOG_COMPRESSED_HEX_PRINT_BUF({source_value}, {log_idx}, {idx}, {buf}, {buf_len})'),
|
||||
)
|
||||
else:
|
||||
macro += generate_log_lvl_prefix(
|
||||
source, tag, f'BLE_LOG_COMPRESSED_HEX_PRINT_WITH_ZERO_ARGUMENTS({source_value}, {log_idx})'
|
||||
)
|
||||
for idx, item in enumerate(hex_func):
|
||||
# hex_func format: @hex_func@buf@len
|
||||
parts = item.split('@')
|
||||
if len(parts) >= 4:
|
||||
buf = parts[2]
|
||||
buf_len = parts[3]
|
||||
macro += generate_log_lvl_prefix(
|
||||
source,
|
||||
tag,
|
||||
(f'BLE_LOG_COMPRESSED_HEX_PRINT_BUF({source_value}, {log_idx}, {idx}, {buf}, {buf_len})'),
|
||||
)
|
||||
if (
|
||||
'tags_with_preserve' in self.module_info[source]
|
||||
and tag in self.module_info[source]['tags_with_preserve']
|
||||
):
|
||||
macro += f' {tag}(fmt, ##__VA_ARGS__);\\\n'
|
||||
else:
|
||||
# Non-hexified log
|
||||
print_fmt = print_fmt or 'NULL'
|
||||
macro += f' BLE_LOG_COMPRESSED_PRINT({source_value}, {log_idx}, "{print_fmt}", ##__VA_ARGS__); \\\n'
|
||||
|
||||
macro += '}\n'
|
||||
return macro
|
||||
|
||||
def compress_file(self, file_info: tuple[str, str]) -> list[tuple[str, int, str]]:
|
||||
"""
|
||||
Process a single file for log compression.
|
||||
|
||||
Args:
|
||||
file_info: Tuple of (module_name, file_path)
|
||||
|
||||
Returns:
|
||||
List of generated macros (module, log_id, macro)
|
||||
"""
|
||||
module, file_path = file_info
|
||||
generated_macros = []
|
||||
|
||||
try:
|
||||
with open(file_path, 'rb') as f:
|
||||
content = f.read()
|
||||
|
||||
new_content = bytearray(content)
|
||||
logs = self.extract_log_calls(content, self.module_info[module]['tags'])
|
||||
LOGGER.info(f'Processing {file_path} - found {len(logs)} logs')
|
||||
offset = 0 # Track cumulative changes due to tag replacements
|
||||
|
||||
for log in logs:
|
||||
tag = log['tag'][0]
|
||||
|
||||
# Extract existing index if present
|
||||
if match := re.fullmatch(r'(.+)_([0-9A-F]{8})', tag):
|
||||
tag_base = match.group(1)
|
||||
file_index = match.group(2)
|
||||
else:
|
||||
tag_base = tag
|
||||
file_index = None
|
||||
|
||||
# Generate simplified format string
|
||||
no_buf_fmt: str = ''
|
||||
simple_fmt_list: list[str] = []
|
||||
hex_buffer_cnt = 0
|
||||
for token in log['argu_tokens']:
|
||||
if isinstance(token, tuple):
|
||||
if '@func' in token[6] or '@line' in token[6]:
|
||||
continue
|
||||
if '@hex_func' in token[6]:
|
||||
simple_fmt_list.append(f'@hex_buffer{hex_buffer_cnt}')
|
||||
no_buf_fmt += f'@hex_buffer{hex_buffer_cnt}'
|
||||
hex_buffer_cnt += 1
|
||||
continue
|
||||
simple_fmt_list.append(token[2])
|
||||
no_buf_fmt += token[2]
|
||||
else:
|
||||
no_buf_fmt += token
|
||||
simple_fmt_str = ' '.join(simple_fmt_list) if simple_fmt_list else None
|
||||
|
||||
# Add to database
|
||||
result, db_index = self.db_manager.add_log(
|
||||
source=module,
|
||||
log_tag=tag_base,
|
||||
log_format=no_buf_fmt if log['hexify'] else log['arguments'][0][0],
|
||||
log_line_number=log['line_number'],
|
||||
hexify=log['hexify'],
|
||||
caller_func=log['caller_name'],
|
||||
caller_line=log['caller_line_number'],
|
||||
file_name=os.path.basename(file_path),
|
||||
)
|
||||
|
||||
LOGGER.info(f'Got log tag {tag}, generated or quired idx {db_index}')
|
||||
|
||||
if result == LogDBManager.SUCCESS:
|
||||
LOGGER.info(f'Added new log: {db_index} - {tag_base}')
|
||||
elif result == LogDBManager.LOG_EXISTS:
|
||||
if file_index:
|
||||
if int(file_index, 16) != db_index:
|
||||
LOGGER.info(f'Updating index: {file_index} -> {db_index}')
|
||||
else:
|
||||
LOGGER.info(f'duplicate index: {file_index} == {db_index}')
|
||||
continue
|
||||
else:
|
||||
LOGGER.info(f'Recovery log index {db_index}')
|
||||
else:
|
||||
LOGGER.error(f'Database error for log: {tag_base}')
|
||||
continue
|
||||
|
||||
# Update tag in content
|
||||
new_tag_bytes = f'{tag_base}_{db_index}'.encode()
|
||||
tag_start, tag_end = log['tag'][1], log['tag'][2]
|
||||
new_content[offset + tag_start : offset + tag_end] = new_tag_bytes
|
||||
offset += len(new_tag_bytes) - (tag_end - tag_start)
|
||||
|
||||
# Generate macro if this is a new log or index changed
|
||||
if result == LogDBManager.SUCCESS or file_index or self.db_manager.is_config_updated(module):
|
||||
macro = self.generate_compressed_macro(module, db_index, tag_base, simple_fmt_str, log)
|
||||
generated_macros.append((module, db_index, macro))
|
||||
|
||||
# Write updated content
|
||||
with open(file_path, 'wb') as f_out:
|
||||
f_out.write(new_content)
|
||||
|
||||
except Exception as e:
|
||||
LOGGER.error(f'Error processing {file_path}: {e}\n{traceback.format_exc()}')
|
||||
raise
|
||||
|
||||
return generated_macros
|
||||
|
||||
def prepare_source_files(self, srcs: list[str]) -> None:
|
||||
"""
|
||||
Prepare source files for processing.
|
||||
|
||||
Args:
|
||||
srcs: List of source file paths
|
||||
"""
|
||||
for module, info in self.module_info.items():
|
||||
code_dirs = '|'.join(info['code_path'])
|
||||
pattern = re.compile(f'({code_dirs}).*\\.c$')
|
||||
info['files_to_process'] = []
|
||||
compressed_file_cnt = 0
|
||||
total_cnt = 0
|
||||
for src in srcs:
|
||||
if pattern.match(src):
|
||||
src_path = self.bt_component_path / src
|
||||
dest_path = self.bt_compressed_srcs_path / src
|
||||
temp_path = f'{dest_path}.tmp'
|
||||
total_cnt += 1
|
||||
# Skip if already processed
|
||||
if self.db_manager.is_file_processed(
|
||||
module, src_path, temp_path
|
||||
) and not self.db_manager.is_config_updated(module):
|
||||
compressed_file_cnt += 1
|
||||
continue
|
||||
|
||||
# Ensure directory exists
|
||||
os.makedirs(os.path.dirname(temp_path), exist_ok=True)
|
||||
shutil.copy2(src_path, temp_path)
|
||||
info['files_to_process'].append(temp_path)
|
||||
LOGGER.info(f'Prepared: {src}')
|
||||
LOGGER.info(f'Compressed cnt {compressed_file_cnt} {total_cnt}')
|
||||
if compressed_file_cnt == total_cnt:
|
||||
print(
|
||||
f'All source files in module {module} have been compressed\n', flush=True, end='', file=sys.stdout
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f'Found {len(info["files_to_process"])} source files in module {module} requiring compression\n',
|
||||
flush=True,
|
||||
end='',
|
||||
file=sys.stdout,
|
||||
)
|
||||
LOGGER.info('Source file preparation complete')
|
||||
|
||||
def generate_log_index_header(self, module: str, macros: list[tuple[int, str]]) -> None:
|
||||
"""
|
||||
Generate or update the log index header file.
|
||||
|
||||
Args:
|
||||
module: Module name
|
||||
macros: List of (log_id, macro_definition)
|
||||
"""
|
||||
# header_path = self.bt_component_path / self.module_info[module]['log_index_path']
|
||||
header_path = self.build_dir / Path('ble_log') / Path('include') / self.module_info[module]['log_index_file']
|
||||
# Create directory if needed
|
||||
header_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
update_state = self.db_manager.source_update_state(source=module)
|
||||
if update_state == self.db_manager.SOURCE_LOG_UPDATE_NONE:
|
||||
return
|
||||
elif update_state == self.db_manager.SOURCE_LOG_UPDATE_FULL:
|
||||
# Header template
|
||||
header_content = (
|
||||
textwrap.dedent(f"""
|
||||
/*
|
||||
* SPDX-FileCopyrightText: {datetime.now().year} Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __{module.upper()}_INTERNAL_LOG_INDEX_H
|
||||
#define __{module.upper()}_INTERNAL_LOG_INDEX_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Compression function declarations
|
||||
extern int ble_log_compressed_hex_print
|
||||
(uint32_t source, uint32_t log_index, size_t args_size_cnt, ...);
|
||||
extern int ble_log_compressed_hex_print_buf
|
||||
(uint8_t source, uint32_t log_index, uint8_t buf_idx, const uint8_t *buf, size_t len);
|
||||
|
||||
// Compression macros
|
||||
#define BLE_LOG_COMPRESSED_HEX_PRINT(source, log_index, args_cnt, ...) \\
|
||||
ble_log_compressed_hex_print(source, log_index, args_cnt, ##__VA_ARGS__)
|
||||
#define BLE_LOG_COMPRESSED_HEX_PRINT_BUF(source, log_index, buf_idx, buf, len) \\
|
||||
ble_log_compressed_hex_print_buf(source, log_index, buf_idx, (const uint8_t *)buf, len)
|
||||
#define BLE_LOG_COMPRESSED_HEX_PRINT_WITH_ZERO_ARGUMENTS(source, log_index) \\
|
||||
ble_log_compressed_hex_print(source, log_index, 0)
|
||||
""").strip()
|
||||
+ '\n\n'
|
||||
)
|
||||
# Add sorted macros
|
||||
for log_id, macro_def in sorted(macros, key=lambda x: x[0]):
|
||||
header_content += macro_def + '\n'
|
||||
|
||||
header_content += f'#endif // __{module.upper()}_INTERNAL_LOG_INDEX_H\n'
|
||||
|
||||
with open(header_path, 'w') as f:
|
||||
f.write(header_content)
|
||||
else:
|
||||
append_content = ''
|
||||
log_idx_set: dict[int, int] = dict()
|
||||
for log_id, macro_def in sorted(macros, key=lambda x: x[0]):
|
||||
append_content += macro_def + '\n'
|
||||
log_idx_set[log_id] = 1
|
||||
with open(header_path, encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
log_idx_pattern = re.compile(r'#define .+(\d+)\(fmt,')
|
||||
for idx, line in enumerate(lines):
|
||||
if line.strip().startswith('#define'):
|
||||
res = log_idx_pattern.match(line)
|
||||
if res:
|
||||
li = int(res.group(1))
|
||||
if li in log_idx_set:
|
||||
raise ValueError(
|
||||
f'The generated log index{li} andlog_index in the header file have duplicates'
|
||||
)
|
||||
|
||||
if line.strip().startswith('#endif'):
|
||||
break
|
||||
else:
|
||||
raise RuntimeError('#endif not found')
|
||||
lines.insert(idx, append_content)
|
||||
with open(header_path, 'w', encoding='utf-8') as f:
|
||||
f.writelines(lines)
|
||||
LOGGER.info(f'Generated log index header: {header_path}')
|
||||
|
||||
def load_config(self, config_path: str, module_names: list[str]) -> None:
|
||||
"""
|
||||
Load and validate log configuration.
|
||||
|
||||
Args:
|
||||
config_path: Path to configuration file
|
||||
module_names: List of module names to load
|
||||
"""
|
||||
with open(config_path, encoding='utf-8') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# Extract global config
|
||||
log_config = config.get('log_config', {})
|
||||
for key, value in log_config.items():
|
||||
if key != 'modules':
|
||||
self.config[key] = value
|
||||
|
||||
# Extract module configs
|
||||
modules = log_config.get('modules', {})
|
||||
for module in module_names:
|
||||
if module in modules:
|
||||
self.module_info[module] = modules[module]
|
||||
print(f'Found module {module} for compression\n', flush=True, end='', file=sys.stdout)
|
||||
else:
|
||||
LOGGER.warning(f"Skipping module '{module}' - config not found")
|
||||
|
||||
def main(self) -> int:
|
||||
"""Main entry point for the compression utility."""
|
||||
parser = argparse.ArgumentParser(description='BLE Log Compression Utility')
|
||||
subparsers = parser.add_subparsers(dest='command', required=True)
|
||||
|
||||
compress_parser = subparsers.add_parser('compress')
|
||||
compress_parser.add_argument('--srcs', required=True, help='Semicolon-separated source file paths')
|
||||
compress_parser.add_argument('--bt_path', required=True, help='Bluetooth component root path')
|
||||
compress_parser.add_argument('--module', required=True, help='Semicolon-separated module names')
|
||||
compress_parser.add_argument('--build_path', required=True, help='Build output directory')
|
||||
compress_parser.add_argument('--compressed_srcs_path', required=True, help='Directory for processed sources')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Setup paths
|
||||
self.bt_component_path = Path(args.bt_path)
|
||||
self.build_dir = Path(args.build_path)
|
||||
self.bt_compressed_srcs_path = Path(args.compressed_srcs_path)
|
||||
|
||||
# Create directories
|
||||
(self.build_dir / 'ble_log').mkdir(parents=True, exist_ok=True)
|
||||
self.bt_compressed_srcs_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Configure logging
|
||||
log_file = self.build_dir / 'ble_log' / f'ble_script_log_{datetime.now().strftime("%y%m%d_%H%M%S")}.log'
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[logging.FileHandler(log_file, mode='w')],
|
||||
)
|
||||
|
||||
# Load configuration
|
||||
modules = args.module.split(';')
|
||||
config_path = self.build_dir / 'ble_log/module_info.yml'
|
||||
self.load_config(str(config_path), modules)
|
||||
|
||||
# Initialize database
|
||||
db_path = self.build_dir / self.config.get('db_path', 'log_db')
|
||||
db_manager = LogDBManager(
|
||||
data_dir=str(db_path),
|
||||
sources={source: str(config) for source, config in self.module_info.items()},
|
||||
logger=LOGGER,
|
||||
)
|
||||
|
||||
self.db_manager = db_manager
|
||||
|
||||
# Prepare source files
|
||||
src_list = args.srcs.split(';')
|
||||
self.prepare_source_files(src_list)
|
||||
|
||||
# Collect files to process
|
||||
files_to_process = []
|
||||
for module, info in self.module_info.items():
|
||||
files_to_process.extend([(module, path) for path in info['files_to_process']])
|
||||
|
||||
if not files_to_process:
|
||||
LOGGER.info('No files to process')
|
||||
print('No source files require compression; exiting log compression\n', flush=True, end='', file=sys.stdout)
|
||||
for root, _, files in os.walk(self.bt_compressed_srcs_path):
|
||||
for name in files:
|
||||
if name.endswith('.tmp'):
|
||||
file_src = os.path.join(root, name)
|
||||
dst_path = os.path.join(root, name[: -len('.tmp')])
|
||||
shutil.copy2(file_src, dst_path)
|
||||
LOGGER.info(f'Recovery src {file_src} dst {dst_path}')
|
||||
db_manager.close()
|
||||
return 0
|
||||
|
||||
all_macros: dict[str, list[tuple[int, str]]] = {}
|
||||
files_to_process.sort(key=lambda x: x[1])
|
||||
try:
|
||||
compressed_log_count = 0
|
||||
for needs_compressed_file in files_to_process:
|
||||
file_macros = self.compress_file(needs_compressed_file)
|
||||
compressed_log_count += len(file_macros)
|
||||
for module, log_id, macro in file_macros:
|
||||
all_macros.setdefault(module, []).append((log_id, macro))
|
||||
print(f'{compressed_log_count} ble log(s) compressed\n', flush=True, end='', file=sys.stdout)
|
||||
except Exception as e:
|
||||
LOGGER.error(f'Processing failed: {e}')
|
||||
db_manager.close()
|
||||
return 1
|
||||
|
||||
# Generate headers
|
||||
for module, macros in all_macros.items():
|
||||
self.generate_log_index_header(module, macros)
|
||||
print('Header file for compressed logs generated\n', flush=True, end='', file=sys.stdout)
|
||||
|
||||
# Mark files as processed
|
||||
for module, info in self.module_info.items():
|
||||
for temp_path in info['files_to_process']:
|
||||
src_path = self.bt_component_path / os.path.relpath(temp_path[:-4], self.bt_compressed_srcs_path)
|
||||
db_manager.mark_file_processed(module, src_path, temp_path)
|
||||
for root, _, files in os.walk(self.bt_compressed_srcs_path):
|
||||
for name in files:
|
||||
if name.endswith('.tmp'):
|
||||
file_src = os.path.join(root, name)
|
||||
dst_path = os.path.join(root, name[: -len('.tmp')])
|
||||
shutil.copy2(file_src, dst_path)
|
||||
LOGGER.info(f'Recovery src {file_src} dst {dst_path}')
|
||||
db_manager.close()
|
||||
LOGGER.info('Compression completed successfully')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('Log compression underway, please wait...\n', flush=True, end='', file=sys.stdout)
|
||||
compressor = LogCompressor()
|
||||
exit(compressor.main())
|
||||
@@ -1,268 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# ruff: noqa: UP007
|
||||
"""
|
||||
Format String Parser
|
||||
====================
|
||||
Parses C-style format strings and handles argument formatting for log compression.
|
||||
"""
|
||||
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
|
||||
def parse_format_string(format_str: str) -> list[Union[str, tuple[int, int, str, str, str, str, str]]]:
|
||||
"""
|
||||
Parse a format string into tokens.
|
||||
|
||||
Args:
|
||||
format_str: C-style format string
|
||||
|
||||
Returns:
|
||||
List of tokens (strings or format spec tuples)
|
||||
"""
|
||||
tokens: list[Union[str, tuple[int, int, str, str, str, str, str]]] = []
|
||||
i = 0
|
||||
n = len(format_str)
|
||||
|
||||
while i < n:
|
||||
if format_str[i] == '%':
|
||||
start = i
|
||||
i += 1
|
||||
|
||||
# Handle escaped %
|
||||
if i < n and format_str[i] == '%':
|
||||
tokens.append('%')
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Parse flags
|
||||
flags = ''
|
||||
while i < n and format_str[i] in '-+ #0':
|
||||
flags += format_str[i]
|
||||
i += 1
|
||||
|
||||
# Parse width
|
||||
width = ''
|
||||
while i < n and format_str[i].isdigit():
|
||||
width += format_str[i]
|
||||
i += 1
|
||||
|
||||
# Parse precision
|
||||
precision = ''
|
||||
if i < n and format_str[i] == '.':
|
||||
i += 1
|
||||
while i < n and format_str[i].isdigit():
|
||||
precision += format_str[i]
|
||||
i += 1
|
||||
|
||||
# Parse length modifier
|
||||
length = ''
|
||||
if i < n and format_str[i] in 'zhl':
|
||||
length += format_str[i]
|
||||
i += 1
|
||||
# Handle double length (e.g., ll)
|
||||
if i < n and format_str[i] == 'l' and length == 'l':
|
||||
length += 'l'
|
||||
i += 1
|
||||
|
||||
if i < n and format_str[i] in 'diuoxXfcsplL':
|
||||
conv_char = format_str[i]
|
||||
i += 1
|
||||
full_spec = format_str[start:i]
|
||||
tokens.append((start, i, full_spec, flags, width, length, conv_char))
|
||||
else:
|
||||
tokens.append(format_str[start:i])
|
||||
else:
|
||||
# Regular text
|
||||
start = i
|
||||
while i < n and format_str[i] != '%':
|
||||
i += 1
|
||||
tokens.append(format_str[start:i])
|
||||
|
||||
return tokens
|
||||
|
||||
|
||||
def format_integer(value: int, conv_char: str, flags: str, width: str, length_mod: str) -> str:
|
||||
"""
|
||||
Format an integer value according to format specifiers.
|
||||
|
||||
Args:
|
||||
value: Integer value
|
||||
conv_char: Conversion character (d, i, u, o, x, X)
|
||||
flags: Format flags
|
||||
width: Minimum width
|
||||
length_mod: Length modifier
|
||||
|
||||
Returns:
|
||||
Formatted string
|
||||
"""
|
||||
# Determine base
|
||||
base = 10
|
||||
uppercase = False
|
||||
if conv_char in 'xX':
|
||||
base = 16
|
||||
uppercase = conv_char == 'X'
|
||||
elif conv_char == 'o':
|
||||
base = 8
|
||||
|
||||
# Generate number string
|
||||
if base == 16:
|
||||
num_str = format(value, 'X' if uppercase else 'x')
|
||||
elif base == 8:
|
||||
num_str = format(value, 'o')
|
||||
else: # decimal
|
||||
num_str = str(value)
|
||||
|
||||
# Add prefix
|
||||
prefix = ''
|
||||
if '#' in flags and value != 0:
|
||||
if base == 16:
|
||||
prefix = '0X' if uppercase else '0x'
|
||||
elif base == 8:
|
||||
prefix = '0'
|
||||
|
||||
# Apply width and padding
|
||||
total_len = len(prefix) + len(num_str)
|
||||
width_val = int(width) if width else 0
|
||||
|
||||
if width_val > total_len:
|
||||
padding = width_val - total_len
|
||||
if '0' in flags and '-' not in flags:
|
||||
num_str = num_str.zfill(padding + len(num_str))
|
||||
else:
|
||||
pad_char = ' ' * padding
|
||||
if '-' in flags:
|
||||
num_str = prefix + num_str + pad_char
|
||||
prefix = ''
|
||||
else:
|
||||
num_str = pad_char + prefix + num_str
|
||||
prefix = ''
|
||||
|
||||
return prefix + num_str
|
||||
|
||||
|
||||
def parse_compressed_arguments(byte_sequence: bytes, format_str: str) -> str:
|
||||
"""
|
||||
Parse compressed log arguments into formatted string.
|
||||
|
||||
Args:
|
||||
byte_sequence: Compressed argument bytes
|
||||
format_str: Original format string
|
||||
|
||||
Returns:
|
||||
Formatted log string
|
||||
|
||||
Raises:
|
||||
ValueError: If the input is invalid
|
||||
"""
|
||||
if len(byte_sequence) < 2:
|
||||
raise ValueError('Insufficient bytes for header')
|
||||
|
||||
# Parse header
|
||||
header = (byte_sequence[0] << 8) | byte_sequence[1]
|
||||
type_flag = (header >> 15) & 0x01
|
||||
arg_count = header & 0x7FFF
|
||||
|
||||
if type_flag != 1:
|
||||
raise ValueError(f'Unsupported type flag: {type_flag}')
|
||||
|
||||
# Parse size list
|
||||
size_bytes_needed = (arg_count + 1) // 2
|
||||
if len(byte_sequence) < 2 + size_bytes_needed:
|
||||
raise ValueError('Insufficient bytes for size list')
|
||||
|
||||
size_bytes = byte_sequence[2 : 2 + size_bytes_needed]
|
||||
arg_sizes = []
|
||||
|
||||
for i in range(arg_count):
|
||||
byte_index = i // 2
|
||||
if i % 2 == 0:
|
||||
size = (size_bytes[byte_index] >> 4) & 0x0F
|
||||
else:
|
||||
size = size_bytes[byte_index] & 0x0F
|
||||
arg_sizes.append(size)
|
||||
|
||||
# Parse arguments
|
||||
args = []
|
||||
pos = 2 + size_bytes_needed
|
||||
|
||||
for size in arg_sizes:
|
||||
if pos + size > len(byte_sequence):
|
||||
raise ValueError('Insufficient bytes for arguments')
|
||||
|
||||
args.append(byte_sequence[pos : pos + size])
|
||||
pos += size
|
||||
|
||||
# Parse format string
|
||||
tokens = parse_format_string(format_str)
|
||||
output = []
|
||||
arg_index = 0
|
||||
|
||||
for token in tokens:
|
||||
if isinstance(token, tuple):
|
||||
start, end, flags, width, precision, length_mod, conv_char = token
|
||||
|
||||
if conv_char == '%':
|
||||
output.append('%')
|
||||
else:
|
||||
if arg_index >= len(args):
|
||||
raise ValueError('Not enough arguments for format string')
|
||||
|
||||
arg_bytes = args[arg_index]
|
||||
arg_index += 1
|
||||
|
||||
# Character type
|
||||
if conv_char == 'c':
|
||||
# Pad to 4 bytes for unpacking
|
||||
padded = arg_bytes.ljust(4, b'\x00')
|
||||
char_code = struct.unpack('>I', padded)[0]
|
||||
output.append(chr(char_code))
|
||||
|
||||
# Pointer type
|
||||
elif conv_char == 'p':
|
||||
ptr_value = int.from_bytes(arg_bytes, 'big', signed=False)
|
||||
output.append(hex(ptr_value))
|
||||
|
||||
# Floating point types
|
||||
elif conv_char in 'fFeEgGaA':
|
||||
if len(arg_bytes) == 4:
|
||||
float_value = struct.unpack('>f', arg_bytes)[0]
|
||||
elif len(arg_bytes) == 8:
|
||||
float_value = struct.unpack('>d', arg_bytes)[0]
|
||||
else:
|
||||
raise ValueError(f'Unsupported float size: {len(arg_bytes)} bytes')
|
||||
output.append(str(float_value))
|
||||
|
||||
# Integer types
|
||||
elif conv_char in 'diuoxX':
|
||||
signed = conv_char in 'di'
|
||||
|
||||
# Determine expected size
|
||||
if length_mod == 'll':
|
||||
expected_size = 8
|
||||
elif length_mod in ('l', 'z', 'j', 't') or conv_char == 'p':
|
||||
expected_size = 4
|
||||
else:
|
||||
expected_size = len(arg_bytes)
|
||||
|
||||
# Pad to expected size
|
||||
if len(arg_bytes) < expected_size:
|
||||
if signed and arg_bytes and (arg_bytes[0] & 0x80):
|
||||
# Sign extension for negative numbers
|
||||
pad = b'\xff' * (expected_size - len(arg_bytes))
|
||||
else:
|
||||
pad = b'\x00' * (expected_size - len(arg_bytes))
|
||||
arg_bytes = pad + arg_bytes
|
||||
elif len(arg_bytes) > expected_size:
|
||||
arg_bytes = arg_bytes[:expected_size]
|
||||
|
||||
# Convert to integer
|
||||
int_value = int.from_bytes(arg_bytes, 'big', signed=signed)
|
||||
output.append(format_integer(int_value, conv_char, flags, width, length_mod))
|
||||
else:
|
||||
raise ValueError(f'Unsupported conversion: {conv_char}')
|
||||
else:
|
||||
output.append(token)
|
||||
|
||||
return ''.join(output)
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
log_config:
|
||||
db_path: "ble_log/ble_log_database"
|
||||
|
||||
modules:
|
||||
BLE_MESH:
|
||||
description: "BLE Mesh"
|
||||
code_path: [@BLE_MESH_CODE_PATH@]
|
||||
log_index_file: @BLE_MESH_LOG_INDEX_HEADER@
|
||||
tags: [@BLE_MESH_TAGS@]
|
||||
tags_with_preserve: [@BLE_MESH_TAGS_PRESERVE@]
|
||||
|
||||
BLE_HOST:
|
||||
description: "BLE Host"
|
||||
code_path: [@HOST_CODE_PATH@]
|
||||
log_index_file: @HOST_LOG_INDEX_HEADER@
|
||||
tags: [@BLE_HOST_TAGS@]
|
||||
tags_with_preserve: [@BLE_HOST_TAGS_PRESERVE@]
|
||||
@@ -1,139 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
try:
|
||||
import tree_sitter_c
|
||||
except ModuleNotFoundError:
|
||||
tree_sitter_c = None
|
||||
try:
|
||||
import tree_sitter
|
||||
except ModuleNotFoundError:
|
||||
tree_sitter = None
|
||||
import platform
|
||||
import sys
|
||||
from importlib.metadata import version
|
||||
from pathlib import Path
|
||||
|
||||
from ble_log_compress import TsInit
|
||||
from ble_log_compress import TsQueryByTree
|
||||
|
||||
IDF_PATH = Path(Path(__file__).resolve().parent / Path('../../../../../../')).resolve()
|
||||
|
||||
TEST_C_STR = b"""
|
||||
void test_func(void);
|
||||
int main(void) {
|
||||
printf("Hello world\n");
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
|
||||
TEST_FUNCTION_QUERY = """
|
||||
[
|
||||
(function_declarator
|
||||
(identifier) @func_name
|
||||
)
|
||||
(declaration
|
||||
(function_declarator
|
||||
(identifier) @func_decls
|
||||
)
|
||||
)
|
||||
]
|
||||
"""
|
||||
TEST_LOG_QUERY = """
|
||||
(expression_statement
|
||||
(call_expression
|
||||
function: (identifier) @fname
|
||||
arguments: (argument_list) @args
|
||||
(#match? @fname "^(printf)$")
|
||||
) @log_stmt
|
||||
)
|
||||
"""
|
||||
|
||||
|
||||
def check_py_version(min_version: str = '3.8.0') -> None:
|
||||
cur_str = platform.python_version()
|
||||
cur_tuple = tuple(map(int, cur_str.split('.')))
|
||||
min_tuple = tuple(map(int, min_version.split('.')))
|
||||
|
||||
if min_tuple > cur_tuple:
|
||||
print(
|
||||
('Please use Python 3.8 or above'),
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
|
||||
def validate() -> None:
|
||||
if tree_sitter is None:
|
||||
print(
|
||||
(
|
||||
'tree_sitter import failed, please check whether the package is installed correctly,'
|
||||
'Please refer to the file:'
|
||||
f'{IDF_PATH}/components/bt/common/ble_log/log_compression/scripts/install.en.md'
|
||||
' for installation instructions.'
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
if tree_sitter_c is None:
|
||||
print(
|
||||
(
|
||||
'tree_sitter_c import failed, '
|
||||
'please check whether the package is installed correctly,'
|
||||
'Please refer to the file:'
|
||||
f'{IDF_PATH}/components/bt/common/ble_log/log_compression/scripts/install.en.md'
|
||||
' for installation instructions.'
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
|
||||
def test_parse() -> None:
|
||||
try:
|
||||
lang, parser = TsInit()
|
||||
tree = parser.parse(TEST_C_STR)
|
||||
captures = TsQueryByTree(lang, tree, TEST_LOG_QUERY)
|
||||
|
||||
assert len(captures.keys()) == 3
|
||||
assert len(captures.values()) == 3
|
||||
assert 'log_stmt' in captures.keys()
|
||||
assert 'fname' in captures.keys()
|
||||
assert 'args' in captures.keys()
|
||||
assert captures['log_stmt'][0].type == 'call_expression'
|
||||
assert captures['log_stmt'][0].start_point == (3, 4)
|
||||
assert captures['log_stmt'][0].end_point == (4, 2)
|
||||
|
||||
captures = TsQueryByTree(lang, tree, TEST_FUNCTION_QUERY)
|
||||
print(captures, file=sys.stderr)
|
||||
assert len(captures.keys()) == 2
|
||||
assert len(captures.values()) == 2
|
||||
assert 'func_decls' in captures.keys()
|
||||
assert 'func_name' in captures.keys()
|
||||
assert len(captures['func_name']) == 2
|
||||
assert len(captures['func_decls']) == 1
|
||||
assert captures['func_name'][0].type == 'identifier'
|
||||
assert captures['func_name'][0].start_point == (1, 5)
|
||||
assert captures['func_name'][0].end_point == (1, 14)
|
||||
|
||||
except Exception:
|
||||
print(
|
||||
(
|
||||
f'Code parsing error,'
|
||||
f'please provide the following information to Espressif to help you solve the problem'
|
||||
f'tree-sitter version: {version(tree_sitter)} '
|
||||
f'tree-sitter-c version: {version(tree_sitter_c)} '
|
||||
f'python version: {platform.python_version()} ',
|
||||
f'os_system: {platform.system()} ',
|
||||
f'os_release: {platform.release()} ',
|
||||
f'os_version: {platform.version()} ',
|
||||
f'machine: {platform.machine()}',
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
|
||||
check_py_version()
|
||||
validate()
|
||||
test_parse()
|
||||
exit(0)
|
||||
@@ -1,166 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
"""
|
||||
用于适配标准化打印
|
||||
file_path: /usr/include/inttypes.h
|
||||
"""
|
||||
|
||||
__PRI64_PREFIX = 'll'
|
||||
__PRIPTR_PREFIX = ''
|
||||
|
||||
TYPES_MACRO_MAP = {
|
||||
'PRId8': 'd',
|
||||
'PRId16': 'd',
|
||||
'PRId32': 'd',
|
||||
'PRId64': __PRI64_PREFIX + 'd',
|
||||
'PRIdLEAST8': 'd',
|
||||
'PRIdLEAST16': 'd',
|
||||
'PRIdLEAST32': 'd',
|
||||
'PRIdLEAST64': __PRI64_PREFIX + 'd',
|
||||
'PRIdFAST8': 'd',
|
||||
'PRIdFAST16': __PRIPTR_PREFIX + 'd',
|
||||
'PRIdFAST32': __PRIPTR_PREFIX + 'd',
|
||||
'PRIdFAST64': __PRI64_PREFIX + 'd',
|
||||
'PRIi8': 'i',
|
||||
'PRIi16': 'i',
|
||||
'PRIi32': 'i',
|
||||
'PRIi64': __PRI64_PREFIX + 'i',
|
||||
'PRIiLEAST8': 'i',
|
||||
'PRIiLEAST16': 'i',
|
||||
'PRIiLEAST32': 'i',
|
||||
'PRIiLEAST64': __PRI64_PREFIX + 'i',
|
||||
'PRIiFAST8': 'i',
|
||||
'PRIiFAST16': __PRIPTR_PREFIX + 'i',
|
||||
'PRIiFAST32': __PRIPTR_PREFIX + 'i',
|
||||
'PRIiFAST64': __PRI64_PREFIX + 'i',
|
||||
'PRIo8': 'o',
|
||||
'PRIo16': 'o',
|
||||
'PRIo32': 'o',
|
||||
'PRIo64': __PRI64_PREFIX + 'o',
|
||||
'PRIoLEAST8': 'o',
|
||||
'PRIoLEAST16': 'o',
|
||||
'PRIoLEAST32': 'o',
|
||||
'PRIoLEAST64': __PRI64_PREFIX + 'o',
|
||||
'PRIoFAST8': 'o',
|
||||
'PRIoFAST16': __PRIPTR_PREFIX + 'o',
|
||||
'PRIoFAST32': __PRIPTR_PREFIX + 'o',
|
||||
'PRIoFAST64': __PRI64_PREFIX + 'o',
|
||||
'PRIu8': 'u',
|
||||
'PRIu16': 'u',
|
||||
'PRIu32': 'u',
|
||||
'PRIu64': __PRI64_PREFIX + 'u',
|
||||
'PRIuLEAST8': 'u',
|
||||
'PRIuLEAST16': 'u',
|
||||
'PRIuLEAST32': 'u',
|
||||
'PRIuLEAST64': __PRI64_PREFIX + 'u',
|
||||
'PRIuFAST8': 'u',
|
||||
'PRIuFAST16': __PRIPTR_PREFIX + 'u',
|
||||
'PRIuFAST32': __PRIPTR_PREFIX + 'u',
|
||||
'PRIuFAST64': __PRI64_PREFIX + 'u',
|
||||
'PRIx8': 'x',
|
||||
'PRIx16': 'x',
|
||||
'PRIx32': 'x',
|
||||
'PRIx64': __PRI64_PREFIX + 'x',
|
||||
'PRIxLEAST8': 'x',
|
||||
'PRIxLEAST16': 'x',
|
||||
'PRIxLEAST32': 'x',
|
||||
'PRIxLEAST64': __PRI64_PREFIX + 'x',
|
||||
'PRIxFAST8': 'x',
|
||||
'PRIxFAST16': __PRIPTR_PREFIX + 'x',
|
||||
'PRIxFAST32': __PRIPTR_PREFIX + 'x',
|
||||
'PRIxFAST64': __PRI64_PREFIX + 'x',
|
||||
'PRIX8': 'X',
|
||||
'PRIX16': 'X',
|
||||
'PRIX32': 'X',
|
||||
'PRIX64': __PRI64_PREFIX + 'X',
|
||||
'PRIXLEAST8': 'X',
|
||||
'PRIXLEAST16': 'X',
|
||||
'PRIXLEAST32': 'X',
|
||||
'PRIXLEAST64': __PRI64_PREFIX + 'X',
|
||||
'PRIXFAST8': 'X',
|
||||
'PRIXFAST16': __PRIPTR_PREFIX + 'X',
|
||||
'PRIXFAST32': __PRIPTR_PREFIX + 'X',
|
||||
'PRIXFAST64': __PRI64_PREFIX + 'X',
|
||||
'PRIdMAX': __PRI64_PREFIX + 'd',
|
||||
'PRIiMAX': __PRI64_PREFIX + 'i',
|
||||
'PRIoMAX': __PRI64_PREFIX + 'o',
|
||||
'PRIuMAX': __PRI64_PREFIX + 'u',
|
||||
'PRIxMAX': __PRI64_PREFIX + 'x',
|
||||
'PRIXMAX': __PRI64_PREFIX + 'X',
|
||||
'PRIdPTR': __PRIPTR_PREFIX + 'd',
|
||||
'PRIiPTR': __PRIPTR_PREFIX + 'i',
|
||||
'PRIoPTR': __PRIPTR_PREFIX + 'o',
|
||||
'PRIuPTR': __PRIPTR_PREFIX + 'u',
|
||||
'PRIxPTR': __PRIPTR_PREFIX + 'x',
|
||||
'PRIXPTR': __PRIPTR_PREFIX + 'X',
|
||||
'SCNd8': 'hhd',
|
||||
'SCNd16': 'hd',
|
||||
'SCNd32': 'd',
|
||||
'SCNd64': __PRI64_PREFIX + 'd',
|
||||
'SCNdLEAST8': 'hhd',
|
||||
'SCNdLEAST16': 'hd',
|
||||
'SCNdLEAST32': 'd',
|
||||
'SCNdLEAST64': __PRI64_PREFIX + 'd',
|
||||
'SCNdFAST8': 'hhd',
|
||||
'SCNdFAST16': __PRIPTR_PREFIX + 'd',
|
||||
'SCNdFAST32': __PRIPTR_PREFIX + 'd',
|
||||
'SCNdFAST64': __PRI64_PREFIX + 'd',
|
||||
'SCNi8': 'hhi',
|
||||
'SCNi16': 'hi',
|
||||
'SCNi32': 'i',
|
||||
'SCNi64': __PRI64_PREFIX + 'i',
|
||||
'SCNiLEAST8': 'hhi',
|
||||
'SCNiLEAST16': 'hi',
|
||||
'SCNiLEAST32': 'i',
|
||||
'SCNiLEAST64': __PRI64_PREFIX + 'i',
|
||||
'SCNiFAST8': 'hhi',
|
||||
'SCNiFAST16': __PRIPTR_PREFIX + 'i',
|
||||
'SCNiFAST32': __PRIPTR_PREFIX + 'i',
|
||||
'SCNiFAST64': __PRI64_PREFIX + 'i',
|
||||
'SCNu8': 'hhu',
|
||||
'SCNu16': 'hu',
|
||||
'SCNu32': 'u',
|
||||
'SCNu64': __PRI64_PREFIX + 'u',
|
||||
'SCNuLEAST8': 'hhu',
|
||||
'SCNuLEAST16': 'hu',
|
||||
'SCNuLEAST32': 'u',
|
||||
'SCNuLEAST64': __PRI64_PREFIX + 'u',
|
||||
'SCNuFAST8': 'hhu',
|
||||
'SCNuFAST16': __PRIPTR_PREFIX + 'u',
|
||||
'SCNuFAST32': __PRIPTR_PREFIX + 'u',
|
||||
'SCNuFAST64': __PRI64_PREFIX + 'u',
|
||||
'SCNo8': 'hho',
|
||||
'SCNo16': 'ho',
|
||||
'SCNo32': 'o',
|
||||
'SCNo64': __PRI64_PREFIX + 'o',
|
||||
'SCNoLEAST8': 'hho',
|
||||
'SCNoLEAST16': 'ho',
|
||||
'SCNoLEAST32': 'o',
|
||||
'SCNoLEAST64': __PRI64_PREFIX + 'o',
|
||||
'SCNoFAST8': 'hho',
|
||||
'SCNoFAST16': __PRIPTR_PREFIX + 'o',
|
||||
'SCNoFAST32': __PRIPTR_PREFIX + 'o',
|
||||
'SCNoFAST64': __PRI64_PREFIX + 'o',
|
||||
'SCNx8': 'hhx',
|
||||
'SCNx16': 'hx',
|
||||
'SCNx32': 'x',
|
||||
'SCNx64': __PRI64_PREFIX + 'x',
|
||||
'SCNxLEAST8': 'hhx',
|
||||
'SCNxLEAST16': 'hx',
|
||||
'SCNxLEAST32': 'x',
|
||||
'SCNxLEAST64': __PRI64_PREFIX + 'x',
|
||||
'SCNxFAST8': 'hhx',
|
||||
'SCNxFAST16': __PRIPTR_PREFIX + 'x',
|
||||
'SCNxFAST32': __PRIPTR_PREFIX + 'x',
|
||||
'SCNxFAST64': __PRI64_PREFIX + 'x',
|
||||
'SCNdMAX': __PRI64_PREFIX + 'd',
|
||||
'SCNiMAX': __PRI64_PREFIX + 'i',
|
||||
'SCNoMAX': __PRI64_PREFIX + 'o',
|
||||
'SCNuMAX': __PRI64_PREFIX + 'u',
|
||||
'SCNxMAX': __PRI64_PREFIX + 'x',
|
||||
'SCNdPTR': __PRIPTR_PREFIX + 'd',
|
||||
'SCNiPTR': __PRIPTR_PREFIX + 'i',
|
||||
'SCNoPTR': __PRIPTR_PREFIX + 'o',
|
||||
'SCNuPTR': __PRIPTR_PREFIX + 'u',
|
||||
'SCNxPTR': __PRIPTR_PREFIX + 'x',
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
tree_sitter~=0.21; python_version == "3.8"
|
||||
tree_sitter_c~=0.21; python_version == "3.8"
|
||||
tree_sitter>=0.23,<=0.23.2; python_version == "3.9"
|
||||
tree_sitter_c>=0.23,<0.23.5; python_version == "3.9"
|
||||
tree-sitter~=0.25; python_version >= "3.10"
|
||||
tree-sitter-c~=0.24; python_version >= "3.10"
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_H__
|
||||
#define __BLE_LOG_H__
|
||||
|
||||
/* ------- */
|
||||
/* BLE Log */
|
||||
/* ------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* TYPEDEF */
|
||||
/* CRITICAL:
|
||||
* The number of BLE Log source code will directly determine the number of statistic manager
|
||||
* memory requirements, keep it as less as possible; it's recommended to use subcode for more
|
||||
* log data structure decoding */
|
||||
typedef enum {
|
||||
/* Internal */
|
||||
BLE_LOG_SRC_INTERNAL = 0,
|
||||
|
||||
/* Custom */
|
||||
BLE_LOG_SRC_CUSTOM,
|
||||
|
||||
/* BLE Stack */
|
||||
BLE_LOG_SRC_LL_TASK,
|
||||
BLE_LOG_SRC_LL_HCI,
|
||||
BLE_LOG_SRC_LL_ISR,
|
||||
BLE_LOG_SRC_HOST,
|
||||
BLE_LOG_SRC_HCI,
|
||||
BLE_LOG_SRC_ENCODE,
|
||||
|
||||
BLE_LOG_SRC_MAX,
|
||||
} ble_log_src_t;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_init(void);
|
||||
void ble_log_deinit(void);
|
||||
bool ble_log_enable(bool enable);
|
||||
void ble_log_flush(void);
|
||||
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len);
|
||||
void ble_log_dump_to_console(void);
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append, uint32_t flag);
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
bool ble_log_sync_enable(bool enable);
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
#endif /* __BLE_LOG_H__ */
|
||||
@@ -11,9 +11,8 @@
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
// Public enums
|
||||
enum {
|
||||
@@ -27,22 +26,21 @@ enum {
|
||||
BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY_ISR,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LL_HCI,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO,
|
||||
BLE_LOG_SPI_OUT_SOURCE_MESH,
|
||||
BLE_LOG_SPI_OUT_SOURCE_USER = 0x10,
|
||||
BLE_LOG_SPI_OUT_SOURCE_SSC = 0xFD,
|
||||
BLE_LOG_SPI_OUT_SOURCE_SYNC,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LOSS,
|
||||
};
|
||||
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_NONE 0
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_ERROR 1
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_WARN 2
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_INFO 3
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_DEBUG 4
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_VERBOSE 5
|
||||
#define BLE_LOG_SPI_OUT_STR(x) #x
|
||||
#define BLE_LOG_SPI_OUT_XSTR(x) BLE_LOG_SPI_OUT_STR(x)
|
||||
#define BLE_LOG_SPI_OUT_BUILD_PREFIX(LEVEL, TAG) "[" BLE_LOG_SPI_OUT_XSTR(LEVEL) "][" TAG "]"
|
||||
enum {
|
||||
BLE_LOG_SPI_OUT_LEVEL_NONE = 0,
|
||||
BLE_LOG_SPI_OUT_LEVEL_ERROR,
|
||||
BLE_LOG_SPI_OUT_LEVEL_WARN,
|
||||
BLE_LOG_SPI_OUT_LEVEL_INFO,
|
||||
BLE_LOG_SPI_OUT_LEVEL_DEBUG,
|
||||
BLE_LOG_SPI_OUT_LEVEL_VERBOSE,
|
||||
BLE_LOG_SPI_OUT_LEVEL_MAX,
|
||||
};
|
||||
|
||||
// Public functions
|
||||
int ble_log_spi_out_init(void);
|
||||
@@ -54,11 +52,12 @@ void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_ap
|
||||
void ble_log_spi_out_ll_log_ev_proc(void);
|
||||
void ble_log_spi_out_ts_sync_start(void);
|
||||
void ble_log_spi_out_ts_sync_stop(void);
|
||||
int ble_log_spi_out_printf(uint8_t source, const char *format, ...);
|
||||
int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...);
|
||||
int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len);
|
||||
void ble_log_spi_out_dump_all(void);
|
||||
void ble_log_spi_out_enable(bool enable);
|
||||
void ble_log_spi_out_flush(void);
|
||||
void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len);
|
||||
int ble_log_spi_out_host_write(uint8_t source, const char *prefix, const char *format, ...);
|
||||
int ble_log_spi_out_hci_write(uint8_t source, const uint8_t *addr, uint16_t len);
|
||||
int ble_log_spi_out_mesh_write(const char *prefix, const char *format, ...);
|
||||
|
||||
#endif // __BT_SPI_OUT_H__
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BT_SPI_OUT_H__
|
||||
#define __BT_SPI_OUT_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/uhci.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/uart_vfs.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
// Public enums
|
||||
enum {
|
||||
BLE_LOG_UHCI_OUT_SOURCE_ESP = 0,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_ESP_ISR = 6,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_LL_HCI = 8,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_USER = 0x10,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_LOSS = 0xFF,
|
||||
};
|
||||
|
||||
// Public functions
|
||||
int ble_log_uhci_out_init(void);
|
||||
void ble_log_uhci_out_deinit(void);
|
||||
void ble_log_uhci_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,
|
||||
const uint8_t *addr_append, uint32_t flag);
|
||||
void ble_log_uhci_out_ll_log_ev_proc(void);
|
||||
void ble_log_uhci_out_dump_all(void);
|
||||
|
||||
#endif // __BT_SPI_OUT_H__
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ------- */
|
||||
/* BLE Log */
|
||||
/* ------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm.h"
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_util.h"
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
#include "ble_log_ts.h"
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool ble_log_inited = false;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_init(void)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (ble_log_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
/* Initialize BLE Log TS */
|
||||
if (!ble_log_ts_init()) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* Initialize BLE Log Runtime */
|
||||
if (!ble_log_rt_init()) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize BLE Log LBM */
|
||||
if (!ble_log_lbm_init()) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize BLE Log peripheral interface */
|
||||
if (!ble_log_prph_init(BLE_LOG_LBM_CNT)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialization done */
|
||||
ble_log_inited = true;
|
||||
ble_log_enable(true);
|
||||
|
||||
/* Write initialization done log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_INIT_DONE,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_deinit(void)
|
||||
{
|
||||
ble_log_enable(false);
|
||||
ble_log_inited = false;
|
||||
|
||||
/* CRITICAL:
|
||||
* BLE Log peripheral interface must be deinitialized at first,
|
||||
* because there's a risky scenario that may cause severe peripheral
|
||||
* driver fault - if a log buffer is sent to peripheral driver, and
|
||||
* ble_log_deinit is called; in this case, if LBM is deinitialized
|
||||
* before peripheral interface, the log buffer may be freed before
|
||||
* peripheral driver completing tx, and the result would be faulty */
|
||||
ble_log_prph_deinit();
|
||||
|
||||
/* Deinitialize BLE Log LBM */
|
||||
ble_log_lbm_deinit();
|
||||
|
||||
/* Deinitialize BLE Log Runtime */
|
||||
ble_log_rt_deinit();
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
/* Deinitialize BLE Log TS */
|
||||
ble_log_ts_deinit();
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
}
|
||||
@@ -1,557 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ------------------------------- */
|
||||
/* BLE Log - Log Buffer Management */
|
||||
/* ------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_lbm.h"
|
||||
#include "ble_log_rt.h"
|
||||
|
||||
#if CONFIG_SOC_ESP_NIMBLE_CONTROLLER
|
||||
#include "os/os_mbuf.h"
|
||||
#endif /* CONFIG_SOC_ESP_NIMBLE_CONTROLLER */
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC volatile uint32_t lbm_ref_count = 0;
|
||||
BLE_LOG_STATIC bool lbm_inited = false;
|
||||
BLE_LOG_STATIC bool lbm_enabled = false;
|
||||
BLE_LOG_STATIC ble_log_lbm_ctx_t *lbm_ctx = NULL;
|
||||
BLE_LOG_STATIC ble_log_stat_mgr_t *stat_mgr_ctx[BLE_LOG_SRC_MAX] = {0};
|
||||
|
||||
/* PRIVATE FUNCTION DECLARATION */
|
||||
BLE_LOG_STATIC ble_log_lbm_t *ble_log_lbm_acquire(void);
|
||||
BLE_LOG_STATIC void ble_log_lbm_release(ble_log_lbm_t *lbm);
|
||||
BLE_LOG_STATIC
|
||||
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||
const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, bool omdata);
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
BLE_LOG_STATIC void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* ------------------------- */
|
||||
/* PRIVATE INTERFACE */
|
||||
/* ------------------------- */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
ble_log_lbm_t *ble_log_lbm_acquire(void)
|
||||
{
|
||||
ble_log_lbm_t *lbm = NULL;
|
||||
ble_log_lbm_t *atomic_pool;
|
||||
ble_log_lbm_t *spin_lbm;
|
||||
int atomic_pool_size;
|
||||
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
atomic_pool = lbm_ctx->atomic_pool_isr;
|
||||
spin_lbm = &(lbm_ctx->spin_isr);
|
||||
atomic_pool_size = BLE_LOG_LBM_ATOMIC_ISR_CNT;
|
||||
} else {
|
||||
atomic_pool = lbm_ctx->atomic_pool_task;
|
||||
spin_lbm = &(lbm_ctx->spin_task);
|
||||
atomic_pool_size = BLE_LOG_LBM_ATOMIC_TASK_CNT;
|
||||
}
|
||||
|
||||
/* Try to acquire atomic LBM first */
|
||||
for (int i = 0; i < atomic_pool_size; i++) {
|
||||
lbm = &atomic_pool[i];
|
||||
if (ble_log_cas_acquire(&(lbm->atomic_lock))) {
|
||||
return lbm;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback to spinlock LBM */
|
||||
lbm = spin_lbm;
|
||||
BLE_LOG_ACQUIRE_SPIN_LOCK(&(lbm->spin_lock));
|
||||
return lbm;
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_lbm_release(ble_log_lbm_t *lbm)
|
||||
{
|
||||
switch (lbm->lock_type) {
|
||||
case BLE_LOG_LBM_LOCK_ATOMIC:
|
||||
ble_log_cas_release(&(lbm->atomic_lock));
|
||||
break;
|
||||
case BLE_LOG_LBM_LOCK_SPIN:
|
||||
BLE_LOG_RELEASE_SPIN_LOCK(&lbm->spin_lock);
|
||||
break;
|
||||
case BLE_LOG_LBM_LOCK_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||
const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, bool omdata)
|
||||
{
|
||||
/* Preparation before writing */
|
||||
uint8_t *buf = (*trans)->buf + (*trans)->pos;
|
||||
uint16_t payload_len = len + len_append;
|
||||
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||
uint32_t frame_sn = BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn));
|
||||
ble_log_frame_head_t frame_head = {
|
||||
.length = payload_len,
|
||||
.frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, frame_sn),
|
||||
};
|
||||
|
||||
/* Memory operation */
|
||||
BLE_LOG_MEMCPY(buf, &frame_head, BLE_LOG_FRAME_HEAD_LEN);
|
||||
if (len) {
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN, addr, len);
|
||||
}
|
||||
if (len_append) {
|
||||
#if CONFIG_SOC_ESP_NIMBLE_CONTROLLER
|
||||
if (omdata) {
|
||||
os_mbuf_copydata((struct os_mbuf *)addr_append, 0,
|
||||
len_append, buf + BLE_LOG_FRAME_HEAD_LEN + len);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_SOC_ESP_NIMBLE_CONTROLLER */
|
||||
{
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data integrity check */
|
||||
#if CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN + payload_len);
|
||||
#else /* !CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||
/* Note:
|
||||
* Minimum data integrity check is still required for log parsing reliability,
|
||||
* which can be achieved by validating the checksum of frame head only */
|
||||
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN);
|
||||
#endif /* CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + payload_len, &checksum, BLE_LOG_FRAME_TAIL_LEN);
|
||||
|
||||
/* Update peripheral transport */
|
||||
(*trans)->pos += payload_len + BLE_LOG_FRAME_OVERHEAD;
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_stat_mgr_update(src_code, payload_len, false);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* Queue trans if full */
|
||||
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost)
|
||||
{
|
||||
/* Get statistic manager by source code */
|
||||
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||
|
||||
/* Update statistics */
|
||||
uint32_t bytes_cnt = len + BLE_LOG_FRAME_OVERHEAD;
|
||||
if (lost) {
|
||||
stat_mgr->enh_stat.lost_frame_cnt++;
|
||||
stat_mgr->enh_stat.lost_bytes_cnt += bytes_cnt;
|
||||
} else {
|
||||
stat_mgr->enh_stat.written_frame_cnt++;
|
||||
stat_mgr->enh_stat.written_bytes_cnt += bytes_cnt;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* -------------------------- */
|
||||
/* INTERNAL INTERFACE */
|
||||
/* -------------------------- */
|
||||
bool ble_log_lbm_init(void)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (lbm_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize LBM context */
|
||||
lbm_ctx = (ble_log_lbm_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_lbm_ctx_t));
|
||||
if (!lbm_ctx) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(lbm_ctx, 0, sizeof(ble_log_lbm_ctx_t));
|
||||
|
||||
/* Initialize peripheral transport for common LBMs */
|
||||
ble_log_lbm_t *lbm;
|
||||
for (int i = 0; i < BLE_LOG_LBM_COMMON_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_common_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||
CONFIG_BLE_LOG_LBM_TRANS_SIZE)) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize lock types for atomic pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_ATOMIC_CNT; i++) {
|
||||
lbm_ctx->atomic_pool[i].lock_type = BLE_LOG_LBM_LOCK_ATOMIC;
|
||||
}
|
||||
|
||||
/* Initialize lock types for spin pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_SPIN_MAX; i++) {
|
||||
lbm_ctx->spin_pool[i].lock_type = BLE_LOG_LBM_LOCK_SPIN;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||
lbm = &(lbm_ctx->lbm_ll_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||
CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE)) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize lock types for LL pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||
lbm_ctx->lbm_ll_pool[i].lock_type = BLE_LOG_LBM_LOCK_NONE;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* Initialize statistic manager context */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
stat_mgr_ctx[i] = (ble_log_stat_mgr_t *)BLE_LOG_MALLOC(sizeof(ble_log_stat_mgr_t));
|
||||
if (!stat_mgr_ctx[i]) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
|
||||
/* Initialization done */
|
||||
lbm_ref_count = 0;
|
||||
lbm_inited = true;
|
||||
lbm_enabled = false;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_lbm_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_lbm_deinit(void)
|
||||
{
|
||||
/* Set inited flag to false to prevent new references */
|
||||
lbm_inited = false;
|
||||
lbm_enabled = false;
|
||||
|
||||
/* Disable module and wait for all references to be released */
|
||||
uint32_t time_waited = 0;
|
||||
while (lbm_ref_count > 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
|
||||
/* Release statistic manager context */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
if (stat_mgr_ctx[i]) {
|
||||
BLE_LOG_FREE(stat_mgr_ctx[i]);
|
||||
stat_mgr_ctx[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release LBM */
|
||||
if (lbm_ctx) {
|
||||
/* Release peripheral transport for common pools */
|
||||
ble_log_lbm_t *lbm;
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
ble_log_prph_trans_deinit(&(lbm->trans[j]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Release LBM context */
|
||||
BLE_LOG_FREE(lbm_ctx);
|
||||
lbm_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note:
|
||||
* The function below should be private, but when UART redirection is required,
|
||||
* it would be a waste to implement get transport function again, thus
|
||||
* make it available internally */
|
||||
BLE_LOG_IRAM_ATTR
|
||||
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len)
|
||||
{
|
||||
/* Check if available buffer can contain incoming log */
|
||||
ble_log_prph_trans_t **trans;
|
||||
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||
trans = &(lbm->trans[lbm->trans_idx]);
|
||||
if (!(*trans)->prph_owned) {
|
||||
/* Return if there's enough free space in current transport */
|
||||
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) >= (log_len + BLE_LOG_FRAME_OVERHEAD)) {
|
||||
return trans;
|
||||
}
|
||||
|
||||
/* Queue transport if there's insufficient free space */
|
||||
if ((*trans)->pos) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
}
|
||||
|
||||
/* Current transport unavailable, switch to the other */
|
||||
lbm->trans_idx = !lbm->trans_idx;
|
||||
}
|
||||
|
||||
/* Both ping-pong buffers are unavailable */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
void ble_log_write_enh_stat(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_enabled) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
ble_log_enh_stat_t *enh_stat = &(stat_mgr_ctx[i]->enh_stat);
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)enh_stat, sizeof(ble_log_enh_stat_t));
|
||||
}
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* ------------------------ */
|
||||
/* PUBLIC INTERFACE */
|
||||
/* ------------------------ */
|
||||
bool ble_log_enable(bool enable)
|
||||
{
|
||||
if (!lbm_inited) {
|
||||
return false;
|
||||
}
|
||||
lbm_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ble_log_flush(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_inited) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
/* Write enhanced statistics before module disable */
|
||||
ble_log_write_enh_stat();
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* Write BLE Log flush log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_FLUSH,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
|
||||
/* Disable module and wait for all other references to release */
|
||||
bool lbm_enabled_copy = lbm_enabled;
|
||||
lbm_enabled = false;
|
||||
uint32_t time_waited = 0;
|
||||
while (lbm_ref_count > 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
|
||||
/* Queue transports with logs */
|
||||
ble_log_lbm_t *lbm;
|
||||
ble_log_prph_trans_t **trans;
|
||||
|
||||
/* Flush pools */
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
int trans_idx = lbm->trans_idx;
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = &(lbm->trans[trans_idx]);
|
||||
if (!(*trans)->prph_owned && (*trans)->pos) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
trans_idx = !trans_idx;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for transportation to finish */
|
||||
time_waited = 0;
|
||||
bool in_progress;
|
||||
do {
|
||||
in_progress = false;
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = &(lbm->trans[j]);
|
||||
in_progress |= (*trans)->prph_owned;
|
||||
}
|
||||
}
|
||||
if (in_progress) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
} while (in_progress);
|
||||
|
||||
/* Reset statistics manager after all operations complete */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
/* Reinitialize enhanced statistics fields */
|
||||
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
|
||||
/* Resume enable status */
|
||||
lbm_enabled = lbm_enabled_copy;
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
}
|
||||
|
||||
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
size_t payload_len = len + sizeof(uint32_t);
|
||||
if (!lbm_enabled) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Get transport */
|
||||
ble_log_lbm_t *lbm = ble_log_lbm_acquire();
|
||||
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||
if (!trans) {
|
||||
ble_log_lbm_release(lbm);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Write transport */
|
||||
uint32_t os_ts = pdTICKS_TO_MS(BLE_LOG_IN_ISR()?
|
||||
xTaskGetTickCountFromISR():
|
||||
xTaskGetTickCount());
|
||||
ble_log_lbm_write_trans(trans, src_code, (const uint8_t *)&os_ts,
|
||||
sizeof(uint32_t), addr, len, false);
|
||||
|
||||
/* Release */
|
||||
ble_log_lbm_release(lbm);
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return true;
|
||||
|
||||
exit:
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
if (lbm_inited) {
|
||||
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
BLE_LOG_IRAM_ATTR
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append, uint32_t flag)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
size_t payload_len = len + len_append;
|
||||
|
||||
/* Source code shall be determined before LBM enable status check */
|
||||
ble_log_src_t src_code;
|
||||
bool use_ll_task = false;
|
||||
if (flag & BIT(BLE_LOG_LL_FLAG_ISR)) {
|
||||
src_code = BLE_LOG_SRC_LL_ISR;
|
||||
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI)) {
|
||||
src_code = BLE_LOG_SRC_LL_HCI;
|
||||
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI_UPSTREAM)) {
|
||||
src_code = BLE_LOG_SRC_HCI;
|
||||
} else {
|
||||
src_code = BLE_LOG_SRC_LL_TASK;
|
||||
use_ll_task = true;
|
||||
}
|
||||
bool omdata = flag & BIT(BLE_LOG_LL_FLAG_OMDATA);
|
||||
|
||||
if (!lbm_enabled) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Determine LBM by flag */
|
||||
ble_log_lbm_t *lbm;
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
/* Reuse common LBM acquire logic */
|
||||
lbm = ble_log_lbm_acquire();
|
||||
} else {
|
||||
lbm = (use_ll_task)? &(lbm_ctx->lbm_ll_task): &(lbm_ctx->lbm_ll_hci);
|
||||
}
|
||||
|
||||
/* Get transport */
|
||||
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||
if (!trans) {
|
||||
ble_log_lbm_release(lbm);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Write transport */
|
||||
ble_log_lbm_write_trans(trans, src_code, addr, len, addr_append, len_append, omdata);
|
||||
|
||||
ble_log_lbm_release(lbm);
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
|
||||
exit:
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
if (lbm_inited) {
|
||||
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
void ble_log_dump_to_console(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_inited) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
int trans_idx;
|
||||
ble_log_lbm_t *lbm;
|
||||
ble_log_prph_trans_t *trans;
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
BLE_LOG_CONSOLE("[BLE_LOG_DUMP_START:\n");
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
trans_idx = lbm->trans_idx;
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = lbm->trans[trans_idx];
|
||||
BLE_LOG_FEED_WDT();
|
||||
|
||||
for (int k = 0; k < trans->size; k++) {
|
||||
BLE_LOG_CONSOLE("%02x ", trans->buf[k]);
|
||||
if (!(k & 0xFF)) {
|
||||
BLE_LOG_FEED_WDT();
|
||||
}
|
||||
}
|
||||
trans_idx = !trans_idx;
|
||||
}
|
||||
}
|
||||
BLE_LOG_CONSOLE("\n:BLE_LOG_DUMP_END]\n\n");
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Runtime */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm.h"
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool rt_inited = false;
|
||||
BLE_LOG_STATIC TaskHandle_t rt_task_handle = NULL;
|
||||
BLE_LOG_STATIC QueueHandle_t rt_queue_handle = NULL;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_STATIC bool rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* PRIVATE FUNCTION */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
ble_log_prph_trans_t *trans = NULL;
|
||||
uint32_t curr_os_ts = 0;
|
||||
uint32_t last_hook_os_ts = 0;
|
||||
#ifndef UNIT_TEST
|
||||
while (1)
|
||||
#endif /* !UNIT_TEST */
|
||||
{
|
||||
/* CRITICAL:
|
||||
* Blocking queue receive is mandatory for light sleep support */
|
||||
if (xQueueReceive(rt_queue_handle, &trans, portMAX_DELAY) == pdTRUE) {
|
||||
ble_log_prph_send_trans(trans);
|
||||
}
|
||||
|
||||
/* Task hook */
|
||||
curr_os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
if ((curr_os_ts - last_hook_os_ts) < BLE_LOG_TASK_HOOK_TIMEOUT_MS) {
|
||||
#ifndef UNIT_TEST
|
||||
continue;
|
||||
#else /* UNIT_TEST */
|
||||
return;
|
||||
#endif /* !UNIT_TEST */
|
||||
}
|
||||
last_hook_os_ts = curr_os_ts;
|
||||
|
||||
/* Write BLE Log info log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_INFO,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
if (rt_ts_enabled) {
|
||||
ble_log_ts_info_t *ts_info = NULL;
|
||||
ble_log_ts_info_update(&ts_info);
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)ts_info, sizeof(ble_log_ts_info_t));
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_write_enh_stat();
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
}
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_rt_init(void)
|
||||
{
|
||||
if (rt_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CRITICAL:
|
||||
* Queue must be initialized before creating task */
|
||||
rt_queue_handle = xQueueCreate(BLE_LOG_LBM_CNT, sizeof(ble_log_prph_trans_t *));
|
||||
if (!rt_queue_handle) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize task */
|
||||
if (xTaskCreate(ble_log_rt_task, "ble_log", BLE_LOG_TASK_STACK_SIZE, NULL,
|
||||
BLE_LOG_TASK_PRIO, &rt_task_handle) != pdTRUE) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rt_inited = true;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_rt_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_rt_deinit(void)
|
||||
{
|
||||
rt_inited = false;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* CRITICAL:
|
||||
* Task must be deinitialized before deinitializing queue */
|
||||
if (rt_task_handle) {
|
||||
vTaskDelete(rt_task_handle);
|
||||
rt_task_handle = NULL;
|
||||
}
|
||||
|
||||
/* Release task queue */
|
||||
if (rt_queue_handle) {
|
||||
vQueueDelete(rt_queue_handle);
|
||||
rt_queue_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans)
|
||||
{
|
||||
(*trans)->prph_owned = true;
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
xQueueSendFromISR(rt_queue_handle, trans, NULL);
|
||||
} else {
|
||||
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
bool ble_log_sync_enable(bool enable)
|
||||
{
|
||||
if (!rt_inited) {
|
||||
return false;
|
||||
}
|
||||
rt_ts_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ----------------------------------- */
|
||||
/* BLE Log - Timestamp Synchronization */
|
||||
/* ----------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool ts_inited = false;
|
||||
BLE_LOG_STATIC ble_log_ts_info_t *ts_info = NULL;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_ts_init(void)
|
||||
{
|
||||
if (ts_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize toggle IO */
|
||||
gpio_config_t sync_io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT(CONFIG_BLE_LOG_SYNC_IO_NUM),
|
||||
};
|
||||
if (gpio_config(&sync_io_conf) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize sync data */
|
||||
ts_info = (ble_log_ts_info_t *)BLE_LOG_MALLOC(sizeof(ble_log_ts_info_t));
|
||||
if (!ts_info) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(ts_info, 0, sizeof(ble_log_ts_info_t));
|
||||
ts_info->int_src_code = BLE_LOG_INT_SRC_TS;
|
||||
|
||||
ts_inited = true;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_ts_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_ts_deinit(void)
|
||||
{
|
||||
ts_inited = false;
|
||||
|
||||
/* Release sync data */
|
||||
if (ts_info) {
|
||||
BLE_LOG_FREE(ts_info);
|
||||
ts_info = NULL;
|
||||
}
|
||||
|
||||
/* Release toggle IO */
|
||||
gpio_reset_pin(CONFIG_BLE_LOG_SYNC_IO_NUM);
|
||||
}
|
||||
|
||||
void ble_log_ts_info_update(ble_log_ts_info_t **info)
|
||||
{
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
ts_info->io_level = !ts_info->io_level;
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, ts_info->io_level);
|
||||
ts_info->lc_ts = BLE_LOG_GET_LC_TS;
|
||||
ts_info->esp_ts = esp_timer_get_time();
|
||||
ts_info->os_ts = pdTICKS_TO_MS(xTaskGetTickCountFromISR());
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
|
||||
*info = ts_info;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Utility */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
/* VARIABLE */
|
||||
#ifndef UNIT_TEST
|
||||
portMUX_TYPE ble_log_spin_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif /* !UNIT_TEST */
|
||||
|
||||
/* INTERNAL INTERFACE */
|
||||
BLE_LOG_IRAM_ATTR uint32_t ble_log_fast_checksum(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
size_t i = 0;
|
||||
|
||||
/* Step 1: Sum up until 4-byte aligned */
|
||||
while (((uintptr_t)(data + i) & 0x3) && (i < len)) {
|
||||
sum += data[i++];
|
||||
}
|
||||
|
||||
/* Step 2: Sum up 4-byte aligned blocks */
|
||||
const uint32_t *p32 = (const uint32_t *)(data + i);
|
||||
size_t blocks = (len - i) / 4;
|
||||
for (size_t b = 0; b < blocks; b++) {
|
||||
uint32_t v = p32[b];
|
||||
sum += (v & 0xFF)
|
||||
+ ((v >> 8) & 0xFF)
|
||||
+ ((v >> 16) & 0xFF)
|
||||
+ ((v >> 24) & 0xFF);
|
||||
}
|
||||
i += blocks * 4;
|
||||
|
||||
/* Step 3: Sum up remaining bytes */
|
||||
while (i < len) {
|
||||
sum += data[i++];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_LBM_H__
|
||||
#define __BLE_LOG_LBM_H__
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* BLE Log - Log Buffer Management */
|
||||
/* --------------------------------------- */
|
||||
|
||||
/* ---------------- */
|
||||
/* Includes */
|
||||
/* ---------------- */
|
||||
#include "ble_log_prph.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
/* ------------------------- */
|
||||
/* Log Frame Defines */
|
||||
/* ------------------------- */
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
uint32_t frame_meta;
|
||||
} __attribute__((packed)) ble_log_frame_head_t;
|
||||
|
||||
#define BLE_LOG_FRAME_HEAD_LEN (sizeof(ble_log_frame_head_t))
|
||||
#define BLE_LOG_FRAME_TAIL_LEN (sizeof(uint32_t))
|
||||
#define BLE_LOG_FRAME_OVERHEAD (BLE_LOG_FRAME_HEAD_LEN + BLE_LOG_FRAME_TAIL_LEN)
|
||||
#define BLE_LOG_MAKE_FRAME_META(src_code, sn) ((src_code & 0xFF) | (sn << 8))
|
||||
|
||||
/* ---------------------------------- */
|
||||
/* Log Buffer Manager Defines */
|
||||
/* ---------------------------------- */
|
||||
typedef enum {
|
||||
BLE_LOG_LBM_LOCK_NONE,
|
||||
BLE_LOG_LBM_LOCK_SPIN,
|
||||
BLE_LOG_LBM_LOCK_ATOMIC,
|
||||
BLE_LOG_LBM_LOCK_MUTEX,
|
||||
} ble_log_lbm_lock_t;
|
||||
|
||||
typedef struct {
|
||||
int trans_idx;
|
||||
ble_log_prph_trans_t *trans[BLE_LOG_TRANS_PING_PONG_BUF_CNT];
|
||||
ble_log_lbm_lock_t lock_type;
|
||||
union {
|
||||
/* BLE_LOG_LBM_LOCK_NONE */
|
||||
void *none;
|
||||
/* BLE_LOG_LBM_LOCK_SPIN */
|
||||
portMUX_TYPE spin_lock;
|
||||
/* BLE_LOG_LBM_LOCK_ATOMIC */
|
||||
volatile bool atomic_lock;
|
||||
/* BLE_LOG_LBM_LOCK_MUTEX */
|
||||
SemaphoreHandle_t mutex;
|
||||
};
|
||||
} ble_log_lbm_t;
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* Log Buffer Manager Pool Defines */
|
||||
/* --------------------------------------- */
|
||||
enum {
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
BLE_LOG_LBM_LL_TASK,
|
||||
BLE_LOG_LBM_LL_HCI,
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
BLE_LOG_LBM_LL_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
BLE_LOG_LBM_SPIN_TASK = 0,
|
||||
BLE_LOG_LBM_SPIN_ISR,
|
||||
BLE_LOG_LBM_SPIN_MAX,
|
||||
};
|
||||
|
||||
#define BLE_LOG_LBM_ATOMIC_TASK_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||
#define BLE_LOG_LBM_ATOMIC_ISR_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||
#define BLE_LOG_LBM_ATOMIC_CNT (BLE_LOG_LBM_ATOMIC_TASK_CNT +\
|
||||
BLE_LOG_LBM_ATOMIC_ISR_CNT)
|
||||
#define BLE_LOG_LBM_COMMON_CNT (BLE_LOG_LBM_ATOMIC_CNT + BLE_LOG_LBM_SPIN_MAX)
|
||||
#define BLE_LOG_LBM_CNT (BLE_LOG_LBM_COMMON_CNT + BLE_LOG_LBM_LL_MAX)
|
||||
#define BLE_LOG_TRANS_CNT (BLE_LOG_LBM_CNT * BLE_LOG_TRANS_PING_PONG_BUF_CNT)
|
||||
|
||||
/* ------------------------------------------ */
|
||||
/* Log Buffer Manager Context Defines */
|
||||
/* ------------------------------------------ */
|
||||
typedef struct {
|
||||
union {
|
||||
ble_log_lbm_t lbm_pool[BLE_LOG_LBM_CNT];
|
||||
struct {
|
||||
union {
|
||||
ble_log_lbm_t lbm_common_pool[BLE_LOG_LBM_COMMON_CNT];
|
||||
struct {
|
||||
union {
|
||||
ble_log_lbm_t spin_pool[BLE_LOG_LBM_SPIN_MAX];
|
||||
struct {
|
||||
ble_log_lbm_t spin_task;
|
||||
ble_log_lbm_t spin_isr;
|
||||
};
|
||||
};
|
||||
union {
|
||||
ble_log_lbm_t atomic_pool[BLE_LOG_LBM_ATOMIC_CNT];
|
||||
struct {
|
||||
ble_log_lbm_t atomic_pool_task[BLE_LOG_LBM_ATOMIC_TASK_CNT];
|
||||
ble_log_lbm_t atomic_pool_isr[BLE_LOG_LBM_ATOMIC_ISR_CNT];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
union {
|
||||
ble_log_lbm_t lbm_ll_pool[BLE_LOG_LBM_LL_MAX];
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
struct {
|
||||
ble_log_lbm_t lbm_ll_task;
|
||||
ble_log_lbm_t lbm_ll_hci;
|
||||
};
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
};
|
||||
};
|
||||
};
|
||||
} ble_log_lbm_ctx_t;
|
||||
|
||||
/* ---------------------------------------- */
|
||||
/* Enhanced Statistics Data Defines */
|
||||
/* ---------------------------------------- */
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
typedef struct {
|
||||
uint8_t int_src_code;
|
||||
uint8_t src_code;
|
||||
uint32_t written_frame_cnt;
|
||||
uint32_t lost_frame_cnt;
|
||||
uint32_t written_bytes_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
} __attribute__((packed)) ble_log_enh_stat_t;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* Log Statistics Manager Context */
|
||||
/* -------------------------------------- */
|
||||
typedef struct {
|
||||
uint32_t frame_sn;
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_enh_stat_t enh_stat;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
} ble_log_stat_mgr_t;
|
||||
|
||||
#define BLE_LOG_GET_FRAME_SN(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_RELAXED)
|
||||
|
||||
/* -------------------------- */
|
||||
/* Link Layer Defines */
|
||||
/* -------------------------- */
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
enum {
|
||||
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||
BLE_LOG_LL_FLAG_END,
|
||||
BLE_LOG_LL_FLAG_TASK,
|
||||
BLE_LOG_LL_FLAG_ISR,
|
||||
BLE_LOG_LL_FLAG_HCI,
|
||||
BLE_LOG_LL_FLAG_RAW,
|
||||
BLE_LOG_LL_FLAG_OMDATA,
|
||||
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||
};
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* --------------------------- */
|
||||
/* Internal Interfaces */
|
||||
/* --------------------------- */
|
||||
bool ble_log_lbm_init(void);
|
||||
void ble_log_lbm_deinit(void);
|
||||
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len);
|
||||
void ble_log_lbm_enable(bool enable);
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
void ble_log_write_enh_stat(void);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
#endif /* __BLE_LOG_LBM_H__ */
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_PRPH_H__
|
||||
#define __BLE_LOG_PRPH_H__
|
||||
|
||||
/* ------------------------------ */
|
||||
/* BLE Log - Peripheral Interface */
|
||||
/* ------------------------------ */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
volatile bool prph_owned;
|
||||
uint8_t *buf;
|
||||
uint16_t size;
|
||||
uint16_t pos;
|
||||
|
||||
/* Peripheral implementation specific context */
|
||||
void *ctx;
|
||||
} ble_log_prph_trans_t;
|
||||
|
||||
#define BLE_LOG_TRANS_FREE_SPACE(trans) (trans->size - trans->pos)
|
||||
#define BLE_LOG_TRANS_PING_PONG_BUF_CNT (2)
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_prph_init(size_t trans_cnt);
|
||||
void ble_log_prph_deinit(void);
|
||||
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size);
|
||||
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans);
|
||||
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans);
|
||||
|
||||
#endif /* __BLE_LOG_PRPH_H__ */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_RT_H__
|
||||
#define __BLE_LOG_RT_H__
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Runtime */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
/* MACRO */
|
||||
#define BLE_LOG_TASK_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||
#define BLE_LOG_TASK_STACK_SIZE (1024)
|
||||
#define BLE_LOG_TASK_HOOK_TIMEOUT_MS (1000)
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_rt_init();
|
||||
void ble_log_rt_deinit(void);
|
||||
void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans);
|
||||
|
||||
#endif /* __BLE_LOG_RT_H__ */
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_TS_H__
|
||||
#define __BLE_LOG_TS_H__
|
||||
|
||||
/* ----------------------------------- */
|
||||
/* BLE Log - Timestamp Synchronization */
|
||||
/* ----------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/* MACRO */
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
/* ESP BLE Controller Gen 2 */
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
|
||||
defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) || defined(CONFIG_IDF_TARGET_ESP32H4)
|
||||
extern uint32_t r_ble_lll_timer_current_tick_get(void);
|
||||
#define BLE_LOG_GET_LC_TS r_ble_lll_timer_current_tick_get()
|
||||
/* ESP BLE Controller Gen 1 */
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||
extern uint32_t r_os_cputime_get32(void);
|
||||
#define BLE_LOG_GET_LC_TS r_os_cputime_get32()
|
||||
/* Legacy BLE Controller (Wait for support) */
|
||||
// #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// extern uint32_t lld_read_clock_us(void);
|
||||
// #define BLE_LOG_GET_LC_TS lld_read_clock_us()
|
||||
#else /* Other targets */
|
||||
#define BLE_LOG_GET_LC_TS 0
|
||||
#endif /* BLE targets */
|
||||
#else /* !CONFIG_BLE_LOG_LL_ENABLED */
|
||||
#define BLE_LOG_GET_LC_TS 0
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
uint8_t int_src_code;
|
||||
uint8_t io_level;
|
||||
uint32_t lc_ts;
|
||||
uint32_t esp_ts;
|
||||
uint32_t os_ts;
|
||||
} __attribute__((packed)) ble_log_ts_info_t;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_ts_init(void);
|
||||
void ble_log_ts_deinit(void);
|
||||
void ble_log_ts_info_update(ble_log_ts_info_t **ts_info);
|
||||
|
||||
#endif /* __BLE_LOG_TS_H__ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user