From ca59e4aa4082bb09620871bc5044be24bd729e01 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 13:42:52 -0400 Subject: [PATCH 01/28] Fix #286: support state save, require Arduino_LoRaWAN v0.9.0-1 or later --- README.md | 8 +-- assets/CatenaBase.plantuml | 4 +- keywords.txt | 4 +- src/CatenaBase.h | 8 ++- src/CatenaStm32L0.h | 16 ++++- src/CatenaWingFram2k.h | 19 +++++- src/Catena_FramStorage.h | 1 + src/Catena_Mx25v8035f.h | 8 +-- src/lib/CatenaBase_NetSave.cpp | 64 +++++++++++-------- src/lib/CatenaBase_registerCommands.cpp | 11 ++-- src/lib/Catena_FramStorage.cpp | 6 +- .../CatenaWingFram2k_LoRaWAN_storage.cpp | 28 ++++---- .../stm32l0/CatenaStm32L0_LoRaWAN_storage.cpp | 26 ++++---- 13 files changed, 126 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index de4bd7c..f68c024 100644 --- a/README.md +++ b/README.md @@ -188,11 +188,11 @@ The first figure just gives relationships; the second has details about the memb **Catena STM32 Class Relationships:** -[![**Catena STM32 Class Relationships**:](http://www.plantuml.com/plantuml/png/xLbhRzf85_wCVyLKVVKsINC1qbpKzwrKIY122mG1sNweAZIs3-2DFUET6KFPRlxx7WyClWH3gYgxYRHV6ZpFSoxduSoPmVqe5HKg2dphv8rbTRWR-V2-LASA6Fr49Ho7FcKQjveHSvJ7sNkhr8iNRpjj8c0C0fW3HF98u9yn5wJVg5rr6iU1IsAAurCfYUlHYQ31iLMowZnS26yoLUXe042eu_0Wf6pXiGbfj-gDxg11nfuFoAr5Qie54eSWn89qE1TmI3hrUelKkGYve756fIwVGM238DLovTAokbo1JAVf1NG2adWipgrpfNEZ0iW46A0BS8cz826LAav1JJsfuoDVSQkafbWTY1cwfufCbGhVdvpCv_ErDCUO_ubvE2IKkGHhjUsbCon3W8nyxVkstvR7X0odiISgYUB41k9o5eV02DGdoWj07fAvfwQesbZhgwpIZFeHbW2kX-dgp6BVP4Q5HsqV4HjyFZz6rq0mdm2DTC7hByCgpJqVtGF-i-0HcMCERoHX02wunvRrviIoNlq7MEojezMKv0CfhzS6AZYjuaebMQ61goaMevXpI1qW7SVnbjr3lbiMjQKIr56h9aZQ2a52tY8O8TYuRPs_6zbHNEj8_Uy1WW-eNHQvPTxl4RIkrcPVlcw2ZQs1WKK1kUar-hLXgtizQhPhruC4wBLhm-PDlvDQ_ouLLPvp7w7YfzMH8jXJ2fiyQFfq8aVNe73FTADOhhtzZ8NDkKySpgI2Rw78shqTjIJQeV0hendtN3AWO-XXkcgyMesjZGYVLdMI0umvM4XSDG6DolTBVhqsR7Hh8rECDbX7vw9rzS1EHqUMKSs4drA1ridwKao3xWos8gwbG-WcZFSREj4oP8el0DFM6GqtLs73n6C5mYphMNLXbmQmjqyqiidHm0S87pfg2XgGWmce-4Cw_v3xVlfPO29IWRYnVmD7hH3gkdNScvIv9lsUu3DFUfnXsGEry47NcLzSaNLB8LwpmpIbnSOynxXHb1PGT7PTK0CwWsOTvsDO05pnETi03K36JlD1iRGsxzFFbEKgDFiXjVaFmkGXvhpEQM-qothAioP9GmpZSLJ8geTHozr4TGOWFEhtWRgBKZ1AFMauEvS84lIsMvhskE-Zi0s6_GQ8fPydA-zA00rQ3DUXZZ0uYWkahZylQQigbso4CyynvSZi0GIpUqIZ1Hin68McPatJQaWwW_JsDEkJp8ZGWiNmlVNA6vEzpBp74s1_ys2FyMg5VCzk6QBR8xqlKmlholWCXF1Sw51vjsRTvLbHtGSgOiuXIHO7e1ApWbcMtzEFQxcZPM7zOHsbxoj7Am8CZsKhhOmv6ukbqOHdgSnk8GgBtj4EJQ1g2g9JnhhD2LlhrjetrwDUgviwTgzQrwrXhPsiFj1bx7EgIBmpVxMfIe_jr_aXdvzw-aJQE0gts-eveOtrMAjrxs2n4cDpkP_HA3uKgdTFMU_R_0cKEC2bJvohEe-OslklRJukIztMvCugRUpnfdWuSjPEVwxxszW7-M9_egBKFYfGgvWKIKFApuP7YdMvMomDPCh7-P5CaO8cUdTszkr9swT8XlkYXCuhposXqsUMq6NvwHBQFNepgRohu2OhZfg-1c--1Rz-z23Kx5qth2Dp-IjoExaRhRoEVa6t6spglTlMrVfQC-hKUcIcmmsv2VZbwmOxwVq18qLOdXnBcXEj-kEY_IlQ6OhsI7cARki_BaR-bhjtG9RhCsCgltpTtrQOuVr3gft_d6fFByg3Z2-UVyQxxYIv0xRoc8B-PfdFAo-iCJ3ZoelBkFhYChvuSHbVlhICJr_QphiiLrvSnbjtNj7rssFFefOT5_3KUyt__tbqb7aNLdmqRJNMZDrnapZQEF_QfP2HlAcmSYQ6PNvCRCUhYESSPWbdkmZdkmWNvKTAk5p9QzWkMvadGp0_jRUWvvMjw6angdyHMbOI9HUrOYKXSY7BnT0MgsenT54CNLf9BRdQobPIIAwmIZ6qxjXxysNb_ZFn0odlMrFF1H8ibup1H_mJ1VvV)](https://www.plantuml.com/plantuml/svg/xLdhSzf64F_C_HMNIQUn7Jy0nuz9cvaG6JnC0JE0cm-P37EI5b0jwTIx4uIc_j-xEX1w65bsEqdicNunQFUtZ_snktVWzr8neKBF9KUl2EboEtJXRSLW2dpsWKau35pcQprfXRwb7Ew_9PL-9BpkTgY02GZmBQ2IXm9V9bpGGRDnqMqUUZQD89RBfAIsmwQ2UOUaGWmUB8KpdIbqD0IWpBAu5p1_wVXJscaRpTwmIIUE2uXjX6h61G978CIITZaNi4-xXj6c1XS15opAgDBZS_1C4BHUhPqJqkCAP3fDnsDJaDJnezow5pet9e1EmGTq0JOrbpHWKaKfg9aZTNp4AqugQeRLWPYZUwReJAdWxT7HOh7OK7E8-H_53_kK-JR5MarpvGpB4213L_k-7dJa8QMZMUI9IQeuDO7Qt8z2O0JcKkLu8FVfmb4pP6sY-LMaCcTkY2M0xM2wEhF8DvqpuJ3JHOq9BbySeckWc8-7Hb71oOT1AWl7HVU0VvOyf0lCuPMaFe0DzY4Xhuu8UV4J-96thcPJqdUqkf4DbNTSHqajaJ3FrX3YCymvO1RGhcKvg-wXNmbXfbI2MMhT14bRePBIrwWCKTcyRf--6PjXLEjO_N97Wm_8NLPpxJj_Xj2-s9Xz-hnD7Tl6Ql13ZrxrcuF6gDsx7BSwZSjXekXt6gFMrQ2Rad-LYYd7kWsHyUFwM57iAOLDxhLSDfNZIr0uCxqmecjdDsDXSkvIY_jImPT0PErUZziIxP3ujT6SEpOTiWdqCLqrMKiZwvY43-iwwHx672ubIkE0CSktAxpH63LxZN5SZ3ROHEUYVN77JaT7LCnQ77x615edyXMPiROqs1gueGvLLq4qR-X4qv0fla2PjivmkBqA4wQENq3Cgfvr5_QO1pkxL6ksEHgw0C5THot1FBet1HMzIUSVSDTDFmjCH2eGL-OVOAcrXjcsWRF9V3jElo_ut94Ezx7ieLgweElC2zTWtLAeRvX16jBs9po7k5AC5K1qTZrGGpQ7be7xCIXGNF25lqKr11avpGV5qZfym3uoFrTXF0-fuTyBaeS8ypB7VSnTrbCUDKqQOXIjeqAK4OHjUnlK6e9mc3i0PYyhtZZrfDNPlKGHeCTkPThdhel4DdtiDq1T-dcwzgu4CA_jenmCL8Ebk43evlqAjgvoXKPrvZc27CGpWChiZ6XjmI1wuo2kMSCq6vBD8HdFH3xDh0XDMAI-9I-S2Tt9x7iy0NQtB_P8Nw_HhzcHeRezqdEP4cmgutCGmh6Xo-JD1dMJHuM62qn4c7sQ28UW4hE2NPQVwOUrtC6giC78GEe7ojACW8_7CacOISx6Ocequ4aoKqv4GT6bxT02fcOWkbMiEpvX6xr6v-fot6_tKiVkHVkoFMfq4kaTNYOkPuf6a_cxoLHwRR_CB_dyrjCdqjrLM6ghzuGsrckjqRk1vPgCxUL-HAFeKAZVVCjwN-TFeCG1YZvmhWmU-chdPpD-kohrlYQtrcbZZxV4tPMpSVhVkh-3VP0lzbzNb9cZ0hQAGQ7CWFAxePoiytAoj29JFkwFP8iKDD6RavCltxHzYcYuBKhejFRK4Zf-OWcTLtz8GkLREPFbcnhENt52wHlozWlooqViI4INNRuEudjXaTlfpNZjTVmRkjrYO_IlsnUR6y-us-ZJkGutud70Jv-ts4ddBnWhwkV14QKvqkgF9-r_qawGj0VIKtYHVpmPkGlmpXvToUUngVpqUVU-mcBS3sBjzF6iVLTIxcPyzjGpBh-kvCxUsaCA-iuqdzQUMMDWnhLdbt7zsMLyzkmoFdzk6Hy_jyaxhpxnoIk_jAP-9lprxuE3p4zB9Ukyo5WZokCcSRHn_bUCGaJonP_aJ69KV06_Nrz7VSvX5d1I1ZWj0vnL7qZXIfBdi5CbcQSO47zpBTRYzD-hFIxMwYzOX2HHSb5h90cH2rajLjrZLIzMdHMhpabIIwwsAaaAoHMsQUdR-1F9_GFk7QtkafbZ0_LMejZWFRw4dliF "Click for SVG image of Class Relationships") +[![**Catena STM32 Class Relationships**:](http://www.plantuml.com/plantuml/png/xLbhRzf85_xC_8gf-kfjakO2fBcekvLA2OdG0a50jX-g2etj0tXZptXdngHiD_zzZmUCBy4uLTLj8ksN1i_pdCjvE7DcSDyhpQGEVOySlIAaAvpGWxUL9jF0sGUcu33m63SukGovhLt1tv9AFrgywNQeX0b8u3PG9KA9VoP2qa6hST5j7VeEZIYsnvIYZikcalc7f4AQ8bX8TphJw6W8G9bj2pzWVE7oAUsqcwtUi4KdhWV8ROHw9YGIHo3bWdQ5aB1FkyrccpQ538HaKKQLdfY3Ru6azMhjd92UqA3IQRe-cuAYBezowrwOt9W4EWKEw08SQYrem9IEKj0pLvduoDU2LFGCgmCvH_TCqvdMmTkZexkxkxKqXvZ_KVomJnbtADPgMKjdM8O45Nh6zysWemuf7SqYJqnHBQW5r14y2e4Hc4UrwuFQftUkdg5g4wEl9fKvyq8i0HmNqpMPHRxfd4cNMHuY5dZYxX1T0yLyV3IA2aw-35AvSprq3_ZFGeJq3dDufIW7SC0v9EJL4I4l_WSyyjOrQYhwZbRNQqFj7zTnfPQiCDyn5C8PvXmm6sZNjjrbzz2lX31BQSbilMg2fAqGfFGrWY62hPlswPkn5KQrZlKl3n1yGEsoo0rt_moXVR4s-_Hv4npRnZ3mqAVN_TQWCMhthiQNdSRLC07wdSReydhGJQr_LPffrxuFKV7Z-bXJx2cDJUvVUcognbUWSS_qmaYkdTsCXIM4Hst1bOOlWSpQlHwt5TgXy2kZkN0TEcGJw6EwUh9QDTOh4JwiwgHx67EuKBWQ1unLlb_ocurHgzSOnyKOWtLq8TiN3-nCT6J5giNXPqoYTRA-53D6IuEjY6lf4BeEels6JemCcU8BmBHrHiFDLLWmTNc1CCjwLbtOOpxix5A3R78qz022Xuuk9VFftXHqz26TVo0yB_qiCH6bGLvRVu2jLmXpd2RkJSQTEFs-57DNkO9ZsKEzyC3KcLzSaKrB8TwmWZIbpISYnxZMZ1LGJ7Ozq4CsXo6eYB0T7MgcCnaWZ25ojZ689NR4W7raFAuqjozIGs0lI1uYpij4w8o6MKzvrZHfZ54qbWfPpI1iEvkezX2aoxm1C6THySUf9mDdvnD5Wjb-IzE-y3mKkCMnxm2nzFDqvLrBO7wRupeq4GPR2udKzUSbRLNbaermvZcY7CHx0S7iNZ5emORqnq5Siw4PDHIRGx9Da_LfPbGOmIBudhnm9tGdC_Vn9DZTFE0Zl5wZNxDRXvhsIE_FrCAwCZ47ALq7kapThbctULROz839YBDFayKXwCIiOARbz_RZMkvWMTXWr4Jf1zesYW37uvaaoYHdPB4qXl0abIaNeg3eqdQu1APd8BjLh3i-QHkzHkVwQjnlzrB7xqNxgZrgT9BL1xfCFC4qZNRcxnRJwV7zCZ_iyzFFd4mFHsAfhPaJnjYCjKRl5XOhCJQN-n6DeiEXVliZwtsTFuaI1xZqGGZT527NE_-tue_BKhSrkRrA6tlyKZuSEMkdtzVz7Uo3VB7VKL5g7nMhLK0ALOQKdmtbOfsNYsM0JFauFv8fKj14RqvEllpGzYcIuRueeTFQKqle-8abT5xzMGcLJELCbczgkF-A4qhVb3TVb5y-UaOQTjdbwo2-5nQvdTwELrx7lw7R3JRD_atxOdtZ6NSRVJetuKOY3lZfymOxvVu5OqrvdXn9cXEj_fzetoxQ2OhsI7cAB_BVAaR-0hopHvVhyzXKVVgykwsmcFUJL3lzVjL-h2WFCZvxwXcNNrToPs_jiGNzYpAVrfvPOs36jMUNSVtPPNpsx38-VsuP7p-tdNTUhJsxZBVll8ABiCkVG2sb5_3KAyzV_puuoBmcApkQ2emDepnk4iSOvz_853AIbnWaPnApuXyJs_4wuZc7MS996U6qZ71MVQI4ovMyXfqgoJp5XFXN-1RqjBOLFTw6uez5Gf8ekQWraeJ8XQmMGrkiwiNGMJ5qJf9QShLLIL98hh1QCRJksFluoyhzV-CxMjqbCzS1wY-NOeFt-2VqlNy0)](https://www.plantuml.com/plantuml/svg/xLbhRzf85_xC_8gf-kfjakO2fBcekvLA2OdG0a50jX-g2etj0tXZptXdngHiD_zzZmUCBy4uLTLj8ksN1i_pdCjvE7DcSDyhpQGEVOySlIAaAvpGWxUL9jF0sGUcu33m63SukGovhLt1tv9AFrgywNQeX0b8u3PG9KA9VoP2qa6hST5j7VeEZIYsnvIYZikcalc7f4AQ8bX8TphJw6W8G9bj2pzWVE7oAUsqcwtUi4KdhWV8ROHw9YGIHo3bWdQ5aB1FkyrccpQ538HaKKQLdfY3Ru6azMhjd92UqA3IQRe-cuAYBezowrwOt9W4EWKEw08SQYrem9IEKj0pLvduoDU2LFGCgmCvH_TCqvdMmTkZexkxkxKqXvZ_KVomJnbtADPgMKjdM8O45Nh6zysWemuf7SqYJqnHBQW5r14y2e4Hc4UrwuFQftUkdg5g4wEl9fKvyq8i0HmNqpMPHRxfd4cNMHuY5dZYxX1T0yLyV3IA2aw-35AvSprq3_ZFGeJq3dDufIW7SC0v9EJL4I4l_WSyyjOrQYhwZbRNQqFj7zTnfPQiCDyn5C8PvXmm6sZNjjrbzz2lX31BQSbilMg2fAqGfFGrWY62hPlswPkn5KQrZlKl3n1yGEsoo0rt_moXVR4s-_Hv4npRnZ3mqAVN_TQWCMhthiQNdSRLC07wdSReydhGJQr_LPffrxuFKV7Z-bXJx2cDJUvVUcognbUWSS_qmaYkdTsCXIM4Hst1bOOlWSpQlHwt5TgXy2kZkN0TEcGJw6EwUh9QDTOh4JwiwgHx67EuKBWQ1unLlb_ocurHgzSOnyKOWtLq8TiN3-nCT6J5giNXPqoYTRA-53D6IuEjY6lf4BeEels6JemCcU8BmBHrHiFDLLWmTNc1CCjwLbtOOpxix5A3R78qz022Xuuk9VFftXHqz26TVo0yB_qiCH6bGLvRVu2jLmXpd2RkJSQTEFs-57DNkO9ZsKEzyC3KcLzSaKrB8TwmWZIbpISYnxZMZ1LGJ7Ozq4CsXo6eYB0T7MgcCnaWZ25ojZ689NR4W7raFAuqjozIGs0lI1uYpij4w8o6MKzvrZHfZ54qbWfPpI1iEvkezX2aoxm1C6THySUf9mDdvnD5Wjb-IzE-y3mKkCMnxm2nzFDqvLrBO7wRupeq4GPR2udKzUSbRLNbaermvZcY7CHx0S7iNZ5emORqnq5Siw4PDHIRGx9Da_LfPbGOmIBudhnm9tGdC_Vn9DZTFE0Zl5wZNxDRXvhsIE_FrCAwCZ47ALq7kapThbctULROz839YBDFayKXwCIiOARbz_RZMkvWMTXWr4Jf1zesYW37uvaaoYHdPB4qXl0abIaNeg3eqdQu1APd8BjLh3i-QHkzHkVwQjnlzrB7xqNxgZrgT9BL1xfCFC4qZNRcxnRJwV7zCZ_iyzFFd4mFHsAfhPaJnjYCjKRl5XOhCJQN-n6DeiEXVliZwtsTFuaI1xZqGGZT527NE_-tue_BKhSrkRrA6tlyKZuSEMkdtzVz7Uo3VB7VKL5g7nMhLK0ALOQKdmtbOfsNYsM0JFauFv8fKj14RqvEllpGzYcIuRueeTFQKqle-8abT5xzMGcLJELCbczgkF-A4qhVb3TVb5y-UaOQTjdbwo2-5nQvdTwELrx7lw7R3JRD_atxOdtZ6NSRVJetuKOY3lZfymOxvVu5OqrvdXn9cXEj_fzetoxQ2OhsI7cAB_BVAaR-0hopHvVhyzXKVVgykwsmcFUJL3lzVjL-h2WFCZvxwXcNNrToPs_jiGNzYpAVrfvPOs36jMUNSVtPPNpsx38-VsuP7p-tdNTUhJsxZBVll8ABiCkVG2sb5_3KAyzV_puuoBmcApkQ2emDepnk4iSOvz_853AIbnWaPnApuXyJs_4wuZc7MS996U6qZ71MVQI4ovMyXfqgoJp5XFXN-1RqjBOLFTw6uez5Gf8ekQWraeJ8XQmMGrkiwiNGMJ5qJf9QShLLIL98hh1QCRJksFluoyhzV-CxMjqbCzS1wY-NOeFt-2VqlNy0 "Click for SVG image of Class Relationships") **Catena STM32 Class Hierarchy (full detail):** -[![**Catena STM32 Class Hierarchy (full detail):**](http://www.plantuml.com/plantuml/png/xLbhRzf85_xC_8gf-kfjakO2fBcexrkfb4245WW2ilrGLMXi7y0Rs-ET6KFPRlxx7WyClWH3gYgxYRHV6ZpFSoxduSoPmVqe5HCgyZroyeQG3dSY3zwNwan1m3un2SUXnmADasOKsChbmNjIwiMBjvqs5J060O4DLF98u9yn5xJVg5rr6iU-GsEAxJ4fgUEoYM3-CIcHEWyNmfrC5JeQ051cszmFMR1mWmbjj-gDxg11nwu7oAr5Qie54eSWn89sE1TmI3lrUelMkGYvO756fIwVWM-1eDLovPAGBbSWqscwFfk0f6uGvzQvqhan0NG20Q0BSAYre26JAav1JLsfuoDVSL9IKwmEn0pTCqMdIeNlJqxcy_bQccFC_yGy758ME1HhjQobCon3W8myxVkstvR7b0wdiIScgUBK0khm80w14PX7bUk3FAHpLqrHjR7MLv7IZ7aHbW2EY-dgp6BVTCQ4oomF4GiyFZz6rq0n7n-DTC7hBuEKvgw7xW7_MV28pZ67Dv8600uunuIyEI7arNyWYBrrj9gIVg2LzTf0-QVLx0hp7Lme4n8mp3baDj2ERRlBxg7V2M6ML8BPQjK4ILiXIEbR12C46xUjytSZAufh7Qd_FK3m0RNB8hU1-ti4hQkrsPUlcs1ZQs088f_Uz1hzsh3LlHursxNhGGBqshLXywRVIQr_buefrxwFKF7JwaXHx2c5JUutFJQHesjGk6UwKIpNtdx6mkBSepOFf89leSZQlHsr9DgXy2kZ6NSTEc1Zw66wQhnQZQsD29zMTT83Z3bOI5mr0OtAzqj-lJPiT6iZKumsM4VdedNrm4v7HvPHpOIVCe7MoVfIJ8Fk3BOYhgL3w2QCzniwqJ9aYYy0qzOP3JTNOS743Gg4MTQpwi8kys5ldsfaawE11n0-TDGKpAS74r3nXtJ-8VUyzBF0HAG2SMFz1hPQ8SnnwhWtMU2Oz7k2prpfyW3B7gY51xhE_EAAh5iAyPeLfYcjOCnpZ1l5M055PzS5DM0pQDPnFeO5m1MV1nkW0SZOQJuebjRcVVQP1QR2t7v8RVw3C7c8EQzpsXljifxoh4dI4CDu71Mowc7KSZPHxG48btbzOCwYv8zIJnhEpYMA1BtjbgOzxdaeR2F0VWF4qi-JbNSbWFcj0DUXZZ3OYWkahZylQQigbso4CyynvSZi0GIpUqIZ1HlH7uMcPatJQaWsW_JsDEkJp8ZGWiNmFNdbZkbUPjxZ2R2_UR37UBL2lsUt3DNjaTwNgOLrPNm6GhWET9YyMxFkygoexW4JCUUG9ei3K8bPmIpBxEb7jzpHih3-i8xIzvMj5O40ZsMILiQSZSNIQCApL6Qt40L5xso79Z0r1T4fOztcXArrQ-sRwr6lrKqTkrUjwzQmravM7-WozZXJDDwPlrfCfSVsw_oGpqyzVI9j7eLRRVMSqCPwhDMwTx1OYR6vtCze51yArRkdhFTj_WHA7E3I9yvLdKU1slklPJukIztMvFOgRUpnfdWuSjPEVwxxszW7-M9_egBKFYfMgu0KoGmfFnjsYtMvMomDPCh7-P5CaO8cUdTszkr9swT8XlkYXCuhposXqsUMq6Nv2HFQENepgRohu2OhZfg-1c--1Rz-z23Kx5qth2Dp-IjoExaRhRoEVa6t6spglTlMrVfQC-hKUdIcmmsv2VZbwmOxwVu18qM3F3cMD2TQzST5-rUqCnJjaV8KtTP_N8pyBNVlW2xNPyPKVlcwlwqmm_k7L3l_ETMUNfG76Lyyzunttqbo1spbCGNzpJAVLrvOOs36bHUNSVN5PNpnuZA-V6aPdxwqdNTPhhouZBVklABhjniyWrfsNi1JxpN__-VHKUPTsFQZgT1OCtR7JU9eu_nhbq96ygQ2v4mCo_oOs8vN4Syvp1BETX7ETn4koe-KSBcIrx1T9fadGp0_jRUWvvMjwEas57yH4f94oKMja2H4BcIv6DfYLIs6BegXIvBKagkjJ992SeLLYg5rnzwRBoltduaVQ7cVJ5q7gBzSCWOVyK_aUty1)](http://www.plantuml.com/plantuml/svg/xLbhRzf85_xC_8gf-kfjakO2fBcexrkfb4245WW2ilrGLMXi7y0Rs-ET6KFPRlxx7WyClWH3gYgxYRHV6ZpFSoxduSoPmVqe5HCgyZroyeQG3dSY3zwNwan1m3un2SUXnmADasOKsChbmNjIwiMBjvqs5J060O4DLF98u9yn5xJVg5rr6iU-GsEAxJ4fgUEoYM3-CIcHEWyNmfrC5JeQ051cszmFMR1mWmbjj-gDxg11nwu7oAr5Qie54eSWn89sE1TmI3lrUelMkGYvO756fIwVWM-1eDLovPAGBbSWqscwFfk0f6uGvzQvqhan0NG20Q0BSAYre26JAav1JLsfuoDVSL9IKwmEn0pTCqMdIeNlJqxcy_bQccFC_yGy758ME1HhjQobCon3W8myxVkstvR7b0wdiIScgUBK0khm80w14PX7bUk3FAHpLqrHjR7MLv7IZ7aHbW2EY-dgp6BVTCQ4oomF4GiyFZz6rq0n7n-DTC7hBuEKvgw7xW7_MV28pZ67Dv8600uunuIyEI7arNyWYBrrj9gIVg2LzTf0-QVLx0hp7Lme4n8mp3baDj2ERRlBxg7V2M6ML8BPQjK4ILiXIEbR12C46xUjytSZAufh7Qd_FK3m0RNB8hU1-ti4hQkrsPUlcs1ZQs088f_Uz1hzsh3LlHursxNhGGBqshLXywRVIQr_buefrxwFKF7JwaXHx2c5JUutFJQHesjGk6UwKIpNtdx6mkBSepOFf89leSZQlHsr9DgXy2kZ6NSTEc1Zw66wQhnQZQsD29zMTT83Z3bOI5mr0OtAzqj-lJPiT6iZKumsM4VdedNrm4v7HvPHpOIVCe7MoVfIJ8Fk3BOYhgL3w2QCzniwqJ9aYYy0qzOP3JTNOS743Gg4MTQpwi8kys5ldsfaawE11n0-TDGKpAS74r3nXtJ-8VUyzBF0HAG2SMFz1hPQ8SnnwhWtMU2Oz7k2prpfyW3B7gY51xhE_EAAh5iAyPeLfYcjOCnpZ1l5M055PzS5DM0pQDPnFeO5m1MV1nkW0SZOQJuebjRcVVQP1QR2t7v8RVw3C7c8EQzpsXljifxoh4dI4CDu71Mowc7KSZPHxG48btbzOCwYv8zIJnhEpYMA1BtjbgOzxdaeR2F0VWF4qi-JbNSbWFcj0DUXZZ3OYWkahZylQQigbso4CyynvSZi0GIpUqIZ1HlH7uMcPatJQaWsW_JsDEkJp8ZGWiNmFNdbZkbUPjxZ2R2_UR37UBL2lsUt3DNjaTwNgOLrPNm6GhWET9YyMxFkygoexW4JCUUG9ei3K8bPmIpBxEb7jzpHih3-i8xIzvMj5O40ZsMILiQSZSNIQCApL6Qt40L5xso79Z0r1T4fOztcXArrQ-sRwr6lrKqTkrUjwzQmravM7-WozZXJDDwPlrfCfSVsw_oGpqyzVI9j7eLRRVMSqCPwhDMwTx1OYR6vtCze51yArRkdhFTj_WHA7E3I9yvLdKU1slklPJukIztMvFOgRUpnfdWuSjPEVwxxszW7-M9_egBKFYfMgu0KoGmfFnjsYtMvMomDPCh7-P5CaO8cUdTszkr9swT8XlkYXCuhposXqsUMq6Nv2HFQENepgRohu2OhZfg-1c--1Rz-z23Kx5qth2Dp-IjoExaRhRoEVa6t6spglTlMrVfQC-hKUdIcmmsv2VZbwmOxwVu18qM3F3cMD2TQzST5-rUqCnJjaV8KtTP_N8pyBNVlW2xNPyPKVlcwlwqmm_k7L3l_ETMUNfG76Lyyzunttqbo1spbCGNzpJAVLrvOOs36bHUNSVN5PNpnuZA-V6aPdxwqdNTPhhouZBVklABhjniyWrfsNi1JxpN__-VHKUPTsFQZgT1OCtR7JU9eu_nhbq96ygQ2v4mCo_oOs8vN4Syvp1BETX7ETn4koe-KSBcIrx1T9fadGp0_jRUWvvMjwEas57yH4f94oKMja2H4BcIv6DfYLIs6BegXIvBKagkjJ992SeLLYg5rnzwRBoltduaVQ7cVJ5q7gBzSCWOVyK_aUty1 "Click for SVG image of Class Hierarchy") +[![**Catena STM32 Class Hierarchy (full detail):**](http://www.plantuml.com/plantuml/png/xLbRRzf857vcViLKNMsJD1SWpKNThLHAI8GM20AoVQWgDBOFu8qzuvqPaxBT_FSz7Z2-14EYgcsGzgN1yttdSZxEd1dSzqepgKFV8qUl26aB9_JWRQdED73sWIau33p63KukGsvhL_2tfDID5c_QBIfX11Au3LI9KEAVaP2qrwXTj1k7laCZYkqnfQZZih5a_Y4faRe8Pj8TJpGwwWDGPjl23nYVkNnCMyrwezDlq97h0N9hePu8YSG1I3cZRI4axDDslTwaTI438LcKKQaZfk1R86crN3adf2Cqg7IQhi_6eAZBezpQ5oOt9e6EWGEw08TQCnemfQCKzCHL9ZxojI0bFS7gG4xHFTDqedNmzkZexkvkASqXvdyKF-nJnXsAjLhMt1cM8K65dl5zqskfGqe7ayWJKrGBQW5r18z2O0JcKUtweFRfdQidgDh8wAj9QSgy44i0nyLqJMQHRpfbqcMMXuW5dhWxHDT0CHyVZQA2ao-3bEvS3zq3_ZCJ8Rt375ufoW4SS0u9UNL4o8jVW4VUsaPDHT_HodAjh_tZQdQ5-Gukb0dX37CEc0sqRTlkl7leLqAOfRHajbuqGT9M25Bw6i4GmSPDy_JDq0gZMeVwjmS8Fg1sMUI6kt-7qBnOcdtwl0gERMCOUEZJwswZLniqErV3orRjgfy0tLPjS7dTQwVMlohDj6lVXwZuSNMeAVQKnYRtBpqsLiChqBXdEc4aryvkni8ImgEsu4h3bq1cxLuFcmhjKFY5qLIu3ksp4NGnNJrQh4RMiGWV5dNIFOpPdobSZGF6Aj_F-VNQeD6f3UDYZC4okf3DYmTs9ZgoOjNYy1CcqJfPduiPenk3BOXBwH2w3gBzXawC39dY2y2qTKR3rLLOC7PvWJ3pUXPTs64-xEnIWwnorFS0WeUEBYNpwTuOTFGXdNyWF2_zB34HfK5UMt-1hHS8Svmwxat6dJZzhXHJLxc2OzbzFVF0r9bVN91DIo5Uiu8qfSb78iUuremLK4ns7T1zDeK-g8Ym7krhfZCP88mXShOnY2MsH8zzP3nNQRmlKaDWBqWU8ixBHEYCXbbFUTOuQOn1D9OAMVKWR3ghg7OVfCky7Z1dLlA7gIS3P-SJHOBPVdFJhl0y5BZ1iUy0iVJpUE5TIs1-a-Cwr146Mmk9rENdEMrHvPoDSEOveXp4Um71x5unQC66z8T1NBEX6JKKcqAoJPFrSMPK6C4Y-9wyS4Tq9pFtyIJONJtW8xnQeL-pMuUQzaZlpzJ2iZ8n1IbT1zfCtIvPjtbMMFU0oOYpJvF5FkZ4h62cvVVsurhkO5vORr17wNlQDee0n-EP9CeaPsInD8RmB9NPB4H1qHlRuHAOde1ibx7k-AIjTMgjwwjXjzb97RyNpQlceDPALX_eCl84qpJQcNzQJAV7zylyiCzFFtCoFHo96stDd336PgpLEhSmMuYnkjoFQ1GT3jNRxrdlw_n9b3Z0fGz2wBe8kTxvrOe_pajTr-Js8ctiyKlvSEGidNvRzxUm3_B5VaD5gNrKe5OnALGPKdusR1RhVBDO1iYKZ_CZcI85JVJcvEJBTssV8XdkYn8whJotX8wVMKBdvP-Lq8QfdCdoJGNtNt52wPloweloooVCI6HlkdmTnFV28hVZs-72w_0FTBl2fjwzQLuiRpp3TgrBfoRSGCG1FtrUOQVSVs2eAS-J8qbpebN_5-tfefsWQ8-Kf_WY_rGnyXVWdJqwNv_6fkhJvzrrXSMydwJQwTDL-x6YFCZuxBbdlFcwaZjxAuyjw0VAV5hPiiR0Z2jRbt5rwp8-sxgCpxSju-DjstddvShMPRn-vnLSX5t-36hPU05FlVBy_T-3Wynhiar7Ku6nOMoEcyGnnlatCeMCv2K6oPd4hFZ7n7gyYdZEOPPmiebmkebmLdwaXFELl8QjCiaynOJuL_WQzBIo5ZrUX-AFHKAIABce5PA4o8Ki5qDhhAh5q5anT4wIMdArbKbIIAwmIZ6qxDZx-ClA_N_ZErhU9HFN0UhFbsA3z_WdzBt_0000)](https://www.plantuml.com/plantuml/svg/xLbRRzf857vcViLKNMsJD1SWpKNThLHAI8GM20AoVQWgDBOFu8qzuvqPaxBT_FSz7Z2-14EYgcsGzgN1yttdSZxEd1dSzqepgKFV8qUl26aB9_JWRQdED73sWIau33p63KukGsvhL_2tfDID5c_QBIfX11Au3LI9KEAVaP2qrwXTj1k7laCZYkqnfQZZih5a_Y4faRe8Pj8TJpGwwWDGPjl23nYVkNnCMyrwezDlq97h0N9hePu8YSG1I3cZRI4axDDslTwaTI438LcKKQaZfk1R86crN3adf2Cqg7IQhi_6eAZBezpQ5oOt9e6EWGEw08TQCnemfQCKzCHL9ZxojI0bFS7gG4xHFTDqedNmzkZexkvkASqXvdyKF-nJnXsAjLhMt1cM8K65dl5zqskfGqe7ayWJKrGBQW5r18z2O0JcKUtweFRfdQidgDh8wAj9QSgy44i0nyLqJMQHRpfbqcMMXuW5dhWxHDT0CHyVZQA2ao-3bEvS3zq3_ZCJ8Rt375ufoW4SS0u9UNL4o8jVW4VUsaPDHT_HodAjh_tZQdQ5-Gukb0dX37CEc0sqRTlkl7leLqAOfRHajbuqGT9M25Bw6i4GmSPDy_JDq0gZMeVwjmS8Fg1sMUI6kt-7qBnOcdtwl0gERMCOUEZJwswZLniqErV3orRjgfy0tLPjS7dTQwVMlohDj6lVXwZuSNMeAVQKnYRtBpqsLiChqBXdEc4aryvkni8ImgEsu4h3bq1cxLuFcmhjKFY5qLIu3ksp4NGnNJrQh4RMiGWV5dNIFOpPdobSZGF6Aj_F-VNQeD6f3UDYZC4okf3DYmTs9ZgoOjNYy1CcqJfPduiPenk3BOXBwH2w3gBzXawC39dY2y2qTKR3rLLOC7PvWJ3pUXPTs64-xEnIWwnorFS0WeUEBYNpwTuOTFGXdNyWF2_zB34HfK5UMt-1hHS8Svmwxat6dJZzhXHJLxc2OzbzFVF0r9bVN91DIo5Uiu8qfSb78iUuremLK4ns7T1zDeK-g8Ym7krhfZCP88mXShOnY2MsH8zzP3nNQRmlKaDWBqWU8ixBHEYCXbbFUTOuQOn1D9OAMVKWR3ghg7OVfCky7Z1dLlA7gIS3P-SJHOBPVdFJhl0y5BZ1iUy0iVJpUE5TIs1-a-Cwr146Mmk9rENdEMrHvPoDSEOveXp4Um71x5unQC66z8T1NBEX6JKKcqAoJPFrSMPK6C4Y-9wyS4Tq9pFtyIJONJtW8xnQeL-pMuUQzaZlpzJ2iZ8n1IbT1zfCtIvPjtbMMFU0oOYpJvF5FkZ4h62cvVVsurhkO5vORr17wNlQDee0n-EP9CeaPsInD8RmB9NPB4H1qHlRuHAOde1ibx7k-AIjTMgjwwjXjzb97RyNpQlceDPALX_eCl84qpJQcNzQJAV7zylyiCzFFtCoFHo96stDd336PgpLEhSmMuYnkjoFQ1GT3jNRxrdlw_n9b3Z0fGz2wBe8kTxvrOe_pajTr-Js8ctiyKlvSEGidNvRzxUm3_B5VaD5gNrKe5OnALGPKdusR1RhVBDO1iYKZ_CZcI85JVJcvEJBTssV8XdkYn8whJotX8wVMKBdvP-Lq8QfdCdoJGNtNt52wPloweloooVCI6HlkdmTnFV28hVZs-72w_0FTBl2fjwzQLuiRpp3TgrBfoRSGCG1FtrUOQVSVs2eAS-J8qbpebN_5-tfefsWQ8-Kf_WY_rGnyXVWdJqwNv_6fkhJvzrrXSMydwJQwTDL-x6YFCZuxBbdlFcwaZjxAuyjw0VAV5hPiiR0Z2jRbt5rwp8-sxgCpxSju-DjstddvShMPRn-vnLSX5t-36hPU05FlVBy_T-3Wynhiar7Ku6nOMoEcyGnnlatCeMCv2K6oPd4hFZ7n7gyYdZEOPPmiebmkebmLdwaXFELl8QjCiaynOJuL_WQzBIo5ZrUX-AFHKAIABce5PA4o8Ki5qDhhAh5q5anT4wIMdArbKbIIAwmIZ6qxDZx-ClA_N_ZErhU9HFN0UhFbsA3z_WdzBt_0000 "Click for SVG image of Class Hierarchy") #### SAMD Classes @@ -200,11 +200,11 @@ The first figure just gives relationships; the second has details about the memb **Catena SAMD Class Relationships:** -[![**Catena SAMD Class Relationships**:](http://www.plantuml.com/plantuml/png/xLbhRzfC5lxC_8gfkjecQIv0cekwMwdKWGWj40Ha-w6gqDW-W3UsnpipXhBT_FVtU63m9JYaglesaTulJJpFSoxdoJd70_qe5HCg3dnoyeQGBdTZ7zvNBAOWP9-OXEF8Pw76IIiE7UNny3sfz9F3ssw72fY0WD01AdaiyCU42pfeDgwwpUF0fGd5yPcKrFNOLB3Wc5I8nQEbyAOpXOw609Gv3WyY5YwzS4exRQlP6pRfnFC1kOrOpRX0uWY4MD8kvm8EQTUosjJY8kA29HbLUdmEWGs2rgkrIq9wN87Cfka5R0gIUc6IM_TAvyO4q2c4W2x0fVQIHaog90KrywIEZtp5IKNDi3eGStJF59qf5Rq_ELai5XjfZZ7_4_DmI5deKgpLjbVEi0m1ClQrxzj1HnvJEfebdfYaYbCRgCl390H6O3vLNW3oa2uyDKFL9bfVHIfpviTO0hWUfgipItpJEHCUitr4RF3vuXXT0yLy0ZJI1M_-6AIoy7nq3_ZFaiTqWJcyaJG4SC4z9kJD2I6l_WPXugshrPJq0wrkpeOgEAtdJrZWua6Da91XpX5pW7OTnrjr3_rE2BEb4inHwoP8smf1IjyY62FOl6sVlnlRSLBhMFtZ0O8Fg5qUkGsz_yRGljgOVVcw3JQs1eOm3kXDlpbeZDgzwt6hqxWUfa2_qnYrRWRTpFbtgPZodFiO5J-jZnN5dbBOv47BPrCvlWQ5CzEB4xdszdCMDkS-TNWe5NoBHDxkxRWjqGw5NnlDkUVI8Pj07zDLa_LfOcr4-BIkanvWpE5Iuga9Q5I-N_6jngZPQunDCTfW4vsBzjK3EnqTMKOr4tx615gdvoin3Reps9guaGwXcoYPDtIYPSWLNm9chNCQRg_2XgaNbWYpgcVTXJqMmDu-rSWsHqCV87heg2LOG0-ce99Vilb7tFUppm8JaGh4ZVqVSDGQOQvhuMooq3NfzmMVUzBZ8POzL4iVT9t5mpLPjnJY3JlAKjhXX1SODugn4ehEhWTgoERGid0_HYN05L-4Mw0XoCHfCIYMrk43zfc5fiB2F6I6_o1A7nBEwuBsHhkyfo9hcZR4A5b7fImhYjlkDgep1E4nVm3CNLQ2SUP9m_czH96WnsvbskU-Zy8sG-mtG2pxF5rxLm9Oq0xn72o4mL5S87Np-ugshdB5HZZtd52Ep0mWc9yHZPOCOZ2EJCsQfjMGR0xPyJJdqzoAq88by3rvvKteNcxVuyBVtxxO4xnUez_p8qDrUsJdCdEmgOpFGGZFXIwJTnlMNP4LMpumaN0EQNeu19MQbUoouam_hUMELeKDHXPAFr2ELWH2rvkGh3BctLWkZIOyIsLs2r5Qz8vsQ05JCn3TAjPjth2DNgDpSptkjtkPr-vL-xezQdJIqmUwJ7pE54qcyzysKzcr_Rguv8jRJx-H7gx2dRPwJsXZlTOQlJjOhiNONkvdD4fU2lMxNrdls-8RA7M0HvyuLnQFGxNtTzlykYhriIPtrcbZZxV4mvMpSVfptT_1FYWM-nCLPUQeHAroKYnpfE9ks2tMvMwnD90h7_T7kaLAckZTsTctNze-PJBSboLqNdjk2Pq-iuGkgxybeTrREPVbknhENtb2sHlozWlowoVlICtUTVawClV2ChVJk_7Qw_XVw7QBZTM_RLzjRZpZRgDFvphSY9k0NxvkiPFU_s2iQ5Wa9v8MHAl_9TgFYtQ6eZrHdlAB_0-BKRW0xntGrVdScCelN_SVAypmVfDgvp-lsYyLvM765yyzuztNbSAxj_RKWlv4cSzhBwmnCEFQYyku_k8oldXn6L--j8nFNzhaNLQV-UJjlhHclYRyv_-FZd9VBUrOvsN6ch4xRXf76nU_nIXbf1_yIS74iCm5_76yZdZ1OPvmjejmlejmKNsYXAkJeeQTAiaz6OBvv5gEulG_YfwMe_e35Y5fb4BK6ab3549Mow57hEhbq4KvT4dIMWgrLKbQIA6mJKlVcxz8uJ_WFj3gFfbvBj1WTMGCFkAFEF3_0000)](https://www.plantuml.com/plantuml/svg/xLbhRzfC5lxC_8gfkjecQIv0cekwMwdKWGWj40Ha-w6gqDW-W3UsnpipXhBT_FVtU63m9JYaglesaTulJJpFSoxdoJd70_qe5HCg3dnoyeQGBdTZ7zvNBAOWP9-OXEF8Pw76IIiE7UNny3sfz9F3ssw72fY0WD01AdaiyCU42pfeDgwwpUF0fGd5yPcKrFNOLB3Wc5I8nQEbyAOpXOw609Gv3WyY5YwzS4exRQlP6pRfnFC1kOrOpRX0uWY4MD8kvm8EQTUosjJY8kA29HbLUdmEWGs2rgkrIq9wN87Cfka5R0gIUc6IM_TAvyO4q2c4W2x0fVQIHaog90KrywIEZtp5IKNDi3eGStJF59qf5Rq_ELai5XjfZZ7_4_DmI5deKgpLjbVEi0m1ClQrxzj1HnvJEfebdfYaYbCRgCl390H6O3vLNW3oa2uyDKFL9bfVHIfpviTO0hWUfgipItpJEHCUitr4RF3vuXXT0yLy0ZJI1M_-6AIoy7nq3_ZFaiTqWJcyaJG4SC4z9kJD2I6l_WPXugshrPJq0wrkpeOgEAtdJrZWua6Da91XpX5pW7OTnrjr3_rE2BEb4inHwoP8smf1IjyY62FOl6sVlnlRSLBhMFtZ0O8Fg5qUkGsz_yRGljgOVVcw3JQs1eOm3kXDlpbeZDgzwt6hqxWUfa2_qnYrRWRTpFbtgPZodFiO5J-jZnN5dbBOv47BPrCvlWQ5CzEB4xdszdCMDkS-TNWe5NoBHDxkxRWjqGw5NnlDkUVI8Pj07zDLa_LfOcr4-BIkanvWpE5Iuga9Q5I-N_6jngZPQunDCTfW4vsBzjK3EnqTMKOr4tx615gdvoin3Reps9guaGwXcoYPDtIYPSWLNm9chNCQRg_2XgaNbWYpgcVTXJqMmDu-rSWsHqCV87heg2LOG0-ce99Vilb7tFUppm8JaGh4ZVqVSDGQOQvhuMooq3NfzmMVUzBZ8POzL4iVT9t5mpLPjnJY3JlAKjhXX1SODugn4ehEhWTgoERGid0_HYN05L-4Mw0XoCHfCIYMrk43zfc5fiB2F6I6_o1A7nBEwuBsHhkyfo9hcZR4A5b7fImhYjlkDgep1E4nVm3CNLQ2SUP9m_czH96WnsvbskU-Zy8sG-mtG2pxF5rxLm9Oq0xn72o4mL5S87Np-ugshdB5HZZtd52Ep0mWc9yHZPOCOZ2EJCsQfjMGR0xPyJJdqzoAq88by3rvvKteNcxVuyBVtxxO4xnUez_p8qDrUsJdCdEmgOpFGGZFXIwJTnlMNP4LMpumaN0EQNeu19MQbUoouam_hUMELeKDHXPAFr2ELWH2rvkGh3BctLWkZIOyIsLs2r5Qz8vsQ05JCn3TAjPjth2DNgDpSptkjtkPr-vL-xezQdJIqmUwJ7pE54qcyzysKzcr_Rguv8jRJx-H7gx2dRPwJsXZlTOQlJjOhiNONkvdD4fU2lMxNrdls-8RA7M0HvyuLnQFGxNtTzlykYhriIPtrcbZZxV4mvMpSVfptT_1FYWM-nCLPUQeHAroKYnpfE9ks2tMvMwnD90h7_T7kaLAckZTsTctNze-PJBSboLqNdjk2Pq-iuGkgxybeTrREPVbknhENtb2sHlozWlowoVlICtUTVawClV2ChVJk_7Qw_XVw7QBZTM_RLzjRZpZRgDFvphSY9k0NxvkiPFU_s2iQ5Wa9v8MHAl_9TgFYtQ6eZrHdlAB_0-BKRW0xntGrVdScCelN_SVAypmVfDgvp-lsYyLvM765yyzuztNbSAxj_RKWlv4cSzhBwmnCEFQYyku_k8oldXn6L--j8nFNzhaNLQV-UJjlhHclYRyv_-FZd9VBUrOvsN6ch4xRXf76nU_nIXbf1_yIS74iCm5_76yZdZ1OPvmjejmlejmKNsYXAkJeeQTAiaz6OBvv5gEulG_YfwMe_e35Y5fb4BK6ab3549Mow57hEhbq4KvT4dIMWgrLKbQIA6mJKlVcxz8uJ_WFj3gFfbvBj1WTMGCFkAFEF3_0000 "Click for SVG image of SAMD Class Relationships") +[![**Catena SAMD Class Relationships**:](http://www.plantuml.com/plantuml/png/xLbjRzf84FxC_egjUhecQLw0D2_gNQLIGY9qG12GwuUgGcjx05_iNT_kcfJhvR_VUC7u9HWILMs3T5-QU9vdNkR9x7YXxvLcKeU-HuvU4T8MJkZ1srATQU3i0rDm67YC6vnSXjpMhk1lIQaR6M_QBIfX11Au3LI9KEAFaP2qrwXTj1k7laCZYkqnfQZZih5a_Y4faRe8Pj8TJpG6wWDGPjl23nYVkNnCMyrwezDlq97h0N9hePu8YSG1I3cZRI4axDDslTwaTI438LbKKQaZfk1R86crN3adf2Cqg7IPhi_6eAZBezhQ5wOs9e6EWGE608TQCnemfQCIzCHL9Z_ojI0bFS7kG4unFDDqedNmzkZexkvkASqXrdyKF-nJnXsAlLhMF1Ys8K65debzqskfGqe7aoWIKrGBQW5r18zIO0RcKUtweFRfdQidgDh8wAj9QSgy45i0nyLoJMLHR3fbqcMMXuW5dhWxnD10iHuVdQA6apy6ATsv7eO7_6ScGdg7DRnIb0Cuu1mIykg8a1U_08-YjOsQYhwZvQMjh_tZQjR2V0SD5K8umve3PWDjsxOxdnxwbH1cAIsPhHT3a8mLWfI-HZ14i77JF7qpjCAerw7-xG623wXT5hdXxjyXD2-MRfy-hu9ZtnW67lhqkjlerGRDpjNmibMxwYT0jrKRN5xtsYdxLwMPTktx41K_hWurnPdIEEJ-fSV6QdW56izC9upasjdDU5X2UDGMN6du4iYit-jXKw4V2hzmcWhNeNqsWYwMgqSBQ-GTY_1XqIVTmvpzcK9hd31M-NxEhzS6ZKvj63TZ79RPXMnUFF0psP4LgnQddp29tebzBcQCRaos82wbG-WwYCuR1Z4oP9el0DFU6GrNTs71sEK5mipxMKnXX_cmiqiDiYfGtmC87WQwbCodUsFGqI_f-WFXUUbdYOKe3VBQ-WjilK2OuzJnR3BknELtfPYwoXKSs-xhcGUcpxnnGJOZXNZD2jAK9X-97EDQCrP0CTLrGFVP5FgW8i9wjA-PpbI0CAR8-SOWjjWIFVQHyLodyRb8BO6z87c8E2yJeJCQPYFbMUDaC0RHMYfarOEmwQoYsdsGBlDwm9nPoH-cdWoStKyK2URupLsxmlDGu0R7kGF4qi_ZHNGjWVbDZdQe8mos5XAfoz_dj4MNSpR2cUU8SX2V1GIpPyMW1GVI7mPnpuPcr51i2ianJUpZpAemWaNmFNdXZkXEPk_ZujzTlU0Zl5gXNxD7XvhnI9_Fb67PcPY2bAu3RQPkbwpRF2kiUy1anDcdYR4FEd4hs6dvi_suaJkODzORr57wdhQD8i3nzKmIPP9tPB4qXl0ibTaiH67J6yRX4fYUW6oNiU_uJLlhr5hNLyDkivDw_Luqhvg3MYknFj1bv0ccQNGo_xIOJg_lb_bbdzz-vitqS2Lkz3LxmZYRjLRhtC9i8SRgTZ-YK_HogDv-ptvVvzz4IG0qVH12rqN8zSwlLlphlDLrGsuloiOPlvGFLyuowBTDVmld8D_iDtIKEaS5QXMJGfKXvNV3Ph7EDujbW4pxk3-IBL8mH6zEJhvyr_4fak6-gA3JodChwFYP5NHU_ba5RTZAcIhVLF3y5HUKlYcllYY_VCAEHFQcozT1V2yi2Zk-7IwY3l_0i2jywjsRviNonZDirxfqQj8DH9pmq-SLVihz1uQQyZmvaZGdMlL_qPuksWcAzaXvYY_oJnKZVm7UsQDp-pHsLPy-xwvhBERz9DLEdwxQZnNbGSLdpx_YJTULtBktyjY6Vg3CfvKj6moikB9r5LUthkAphQluVDigFjwsatTUhcnTnUjFNi55sENFefSD5_3KLvw__tjmaFcQRDEhgS3PC3RdJV8Ov_mtCeMCv4iCadE9MV67YVLu5V5Sm2pXP1FXT1FXhFn82UUMl8QjCiaynOJuK_WQzBIo5ZrUX-A7HKAIBBci5PAaoAKi5qDhlAh5q5anT4wINdAzbKdIIAwnIZ6qdDZx-8-L-__6TxIyIoQk0zIVcsA7z_WZzBt_0000)](https://www.plantuml.com/plantuml/svg/xLbjRzf84FxC_egjUhecQLw0D2_gNQLIGY9qG12GwuUgGcjx05_iNT_kcfJhvR_VUC7u9HWILMs3T5-QU9vdNkR9x7YXxvLcKeU-HuvU4T8MJkZ1srATQU3i0rDm67YC6vnSXjpMhk1lIQaR6M_QBIfX11Au3LI9KEAFaP2qrwXTj1k7laCZYkqnfQZZih5a_Y4faRe8Pj8TJpG6wWDGPjl23nYVkNnCMyrwezDlq97h0N9hePu8YSG1I3cZRI4axDDslTwaTI438LbKKQaZfk1R86crN3adf2Cqg7IPhi_6eAZBezhQ5wOs9e6EWGE608TQCnemfQCIzCHL9Z_ojI0bFS7kG4unFDDqedNmzkZexkvkASqXrdyKF-nJnXsAlLhMF1Ys8K65debzqskfGqe7aoWIKrGBQW5r18zIO0RcKUtweFRfdQidgDh8wAj9QSgy45i0nyLoJMLHR3fbqcMMXuW5dhWxnD10iHuVdQA6apy6ATsv7eO7_6ScGdg7DRnIb0Cuu1mIykg8a1U_08-YjOsQYhwZvQMjh_tZQjR2V0SD5K8umve3PWDjsxOxdnxwbH1cAIsPhHT3a8mLWfI-HZ14i77JF7qpjCAerw7-xG623wXT5hdXxjyXD2-MRfy-hu9ZtnW67lhqkjlerGRDpjNmibMxwYT0jrKRN5xtsYdxLwMPTktx41K_hWurnPdIEEJ-fSV6QdW56izC9upasjdDU5X2UDGMN6du4iYit-jXKw4V2hzmcWhNeNqsWYwMgqSBQ-GTY_1XqIVTmvpzcK9hd31M-NxEhzS6ZKvj63TZ79RPXMnUFF0psP4LgnQddp29tebzBcQCRaos82wbG-WwYCuR1Z4oP9el0DFU6GrNTs71sEK5mipxMKnXX_cmiqiDiYfGtmC87WQwbCodUsFGqI_f-WFXUUbdYOKe3VBQ-WjilK2OuzJnR3BknELtfPYwoXKSs-xhcGUcpxnnGJOZXNZD2jAK9X-97EDQCrP0CTLrGFVP5FgW8i9wjA-PpbI0CAR8-SOWjjWIFVQHyLodyRb8BO6z87c8E2yJeJCQPYFbMUDaC0RHMYfarOEmwQoYsdsGBlDwm9nPoH-cdWoStKyK2URupLsxmlDGu0R7kGF4qi_ZHNGjWVbDZdQe8mos5XAfoz_dj4MNSpR2cUU8SX2V1GIpPyMW1GVI7mPnpuPcr51i2ianJUpZpAemWaNmFNdXZkXEPk_ZujzTlU0Zl5gXNxD7XvhnI9_Fb67PcPY2bAu3RQPkbwpRF2kiUy1anDcdYR4FEd4hs6dvi_suaJkODzORr57wdhQD8i3nzKmIPP9tPB4qXl0ibTaiH67J6yRX4fYUW6oNiU_uJLlhr5hNLyDkivDw_Luqhvg3MYknFj1bv0ccQNGo_xIOJg_lb_bbdzz-vitqS2Lkz3LxmZYRjLRhtC9i8SRgTZ-YK_HogDv-ptvVvzz4IG0qVH12rqN8zSwlLlphlDLrGsuloiOPlvGFLyuowBTDVmld8D_iDtIKEaS5QXMJGfKXvNV3Ph7EDujbW4pxk3-IBL8mH6zEJhvyr_4fak6-gA3JodChwFYP5NHU_ba5RTZAcIhVLF3y5HUKlYcllYY_VCAEHFQcozT1V2yi2Zk-7IwY3l_0i2jywjsRviNonZDirxfqQj8DH9pmq-SLVihz1uQQyZmvaZGdMlL_qPuksWcAzaXvYY_oJnKZVm7UsQDp-pHsLPy-xwvhBERz9DLEdwxQZnNbGSLdpx_YJTULtBktyjY6Vg3CfvKj6moikB9r5LUthkAphQluVDigFjwsatTUhcnTnUjFNi55sENFefSD5_3KLvw__tjmaFcQRDEhgS3PC3RdJV8Ov_mtCeMCv4iCadE9MV67YVLu5V5Sm2pXP1FXT1FXhFn82UUMl8QjCiaynOJuK_WQzBIo5ZrUX-A7HKAIBBci5PAaoAKi5qDhlAh5q5anT4wINdAzbKdIIAwnIZ6qdDZx-8-L-__6TxIyIoQk0zIVcsA7z_WZzBt_0000 "Click for SVG image of SAMD Class Relationships") **Catena SAMD Class Hierarchy (full detail):** -[![**Catena SAMD Class Hierarchy (full detail):**](http://www.plantuml.com/plantuml/png/xLbjSzf64FxC_OhBfDFOZby0no-JDZCXCdYO0cO0Dnyo6UOaBQ1Qqgbt9mXD_T-xEX1wCRBiTfBOC_qIM_Sy-xAFTrS7UIyL4ohqN7BqYf0kjqCNtbOCfi1d7vY4my1bliP9A_GjvN3_BQdqeyFhReSAc800tm8gUIZmnuGBEcWsBhhDGy-c4SLocPJKTjXKCE-GL8Z1WwLmfZE5ZeO0b5aMzmBcBnr_IZjjezaRDkd4SG6vZL3Dk43Y28HOqYxd0lPfrp3QrE0Yu8956LLwV0wU2OBMgxLpGdfSWKodwNXi2f8wVfHRzqBdnWJGAVY0Bi2cvf86JAee1JLpf8wFVCL9HSsmEX1pTCyKdIaLl3qwMYmM6saECV-Z-66VCj-cMAjfhfnX6G9aw6hVruEEFAHqD8iyCKaLfoPGc_jH28p0NAeS3-G-NJXgXgfDjBwALERC3R44i1rCLsSM-QPp9XnckeYOuFB58Re6YlbuQ1GLdFmnI6NXkEWUy9yb3-a2StWbgGzWWtr8oAiZGbxy17xahQlLbFGThMtEXiexhkD9DJbXdgqfn6UOSy0ie5tBSbRTGxyImaof1BFKkWcIjaAGqjS8XWWshzkdRyPc6DKwLh_SGV01jSiYrxxpPmZjYutPfy_RuDWsXi4FFNhLRmuQetRlSjpgD2w72T3lD4Qjgq4tTVvLAgOSwpP4nO_hOqMnfnGskTTosLIEBq7XpFJ2IAwTtOo5oRbBBUvB1Ly2aRLxFMvBj4FXrqPpxjXqo2RGntJLP7qQMSSYV5ZNIVSmvd0fyJGE6Ajyk-8RZL6prnZ7nMY3JNGksXTtx7HqPCMgnU5dJA1rShuICqPBWws96-aGkWgYUKCdMePCyGLWsZgZuVOgJ9WwVe4mgthMNTXZ7kpiKeriSpHq0OAxZbg2UNHl2Yhw9Pr_m5qt_Imm4Qb0N9b_WANM2BDj0sUJ-NQSVb_mkICTxcFPGxLqGTUPFroJTKiXtZ23DANjJtYESQKOAw3ex7gWXcmEBGFtOr00NF25lmKQWeoSveDYQHq-O1-PdwimdeVKyEy5oKF4UPdJFjOkwodFcYODCOhMKI7B2CAslOrg3K4up1q0ivSLRvnwqd1sBr4awB5RcVQvwwAmJH_x3H1BFq_NtfK0vhLzF0S3OR0K5qZT_BwYhQjSiH7EF4UKWtW64CpEY4OB1j4R1t7DcgRLa6mEoNWcvzFCYj22HV0jUU5Cw4vct-F2tzs-s2EyNgDVioD3TNkavp9riAcCpq48nuOkapSRrasU5HekC15nzcboE0ILc1NiijnCFx3b3bQ53KO6IZzGbbO4VDkPa4IPvDrOB8qcF4bboeKeBBga7Lh0r0n4jufrns_OHg_HkReSzzkzr6ltedtP7ZKwoUaTNIOkPuf6a_cxoLHwRR_CB_dyrjDlfBkhiDHMxmbjhDTQetS3oxKOsylzY4RHIw5-yothVPr_0oKEyEW3vyhWeQzsVZRZNrUbtjVarZfjxF6MkBjoDax_M_Tti0_onVxhYZ9pLAnM0IcK6L9-DvIBTLukbWOovUF-IBP8GHEzEJdvyatRfqY6swA4JcjFBQ7Z9vRGUVM795I-bJDPlgdX_1KdbBuXRxyWltp4ZaHssUNh8BuN5hcTtepNNiU_eTijDaR_kdsnkV6Ckuq-dUjm8nu7_FHvYvrq_eAnedwU74cQ4wt-lsYF5-q4HNkWFCKN-KUBaRi0x-pHrVayDfMVFk_ULrZC-q6gdJvUjUygojsCpvvwnkNNbToxj_RGWhwZpAUrPzOOc77jsMLSVtOPdpsxZC-VMyR7pstopgjFVFBABwsfhmb__VlW8FFLKiawBpBMZFAuIHnjdFyMev2HVF0dEPEO5L_0xyVhYESSPWadPOJJCi9PzO4Ihaxo6dQg9FCK4-9FhiKeJl-zw74ngZzW4P94oKMjaIH4BcIr6Bh7gbuCdHL3voIf9LTRbII5v0hRjFHj_1V9_GVSErhT9JF71kgjZcA3z_WZzDn_0000)](https://www.plantuml.com/plantuml/svg/xLbjSzf64FxC_OhBfDFOZby0no-JDZCXCdYO0cO0Dnyo6UOaBQ1Qqgbt9mXD_T-xEX1wCRBiTfBOC_qIM_Sy-xAFTrS7UIyL4ohqN7BqYf0kjqCNtbOCfi1d7vY4my1bliP9A_GjvN3_BQdqeyFhReSAc800tm8gUIZmnuGBEcWsBhhDGy-c4SLocPJKTjXKCE-GL8Z1WwLmfZE5ZeO0b5aMzmBcBnr_IZjjezaRDkd4SG6vZL3Dk43Y28HOqYxd0lPfrp3QrE0Yu8956LLwV0wU2OBMgxLpGdfSWKodwNXi2f8wVfHRzqBdnWJGAVY0Bi2cvf86JAee1JLpf8wFVCL9HSsmEX1pTCyKdIaLl3qwMYmM6saECV-Z-66VCj-cMAjfhfnX6G9aw6hVruEEFAHqD8iyCKaLfoPGc_jH28p0NAeS3-G-NJXgXgfDjBwALERC3R44i1rCLsSM-QPp9XnckeYOuFB58Re6YlbuQ1GLdFmnI6NXkEWUy9yb3-a2StWbgGzWWtr8oAiZGbxy17xahQlLbFGThMtEXiexhkD9DJbXdgqfn6UOSy0ie5tBSbRTGxyImaof1BFKkWcIjaAGqjS8XWWshzkdRyPc6DKwLh_SGV01jSiYrxxpPmZjYutPfy_RuDWsXi4FFNhLRmuQetRlSjpgD2w72T3lD4Qjgq4tTVvLAgOSwpP4nO_hOqMnfnGskTTosLIEBq7XpFJ2IAwTtOo5oRbBBUvB1Ly2aRLxFMvBj4FXrqPpxjXqo2RGntJLP7qQMSSYV5ZNIVSmvd0fyJGE6Ajyk-8RZL6prnZ7nMY3JNGksXTtx7HqPCMgnU5dJA1rShuICqPBWws96-aGkWgYUKCdMePCyGLWsZgZuVOgJ9WwVe4mgthMNTXZ7kpiKeriSpHq0OAxZbg2UNHl2Yhw9Pr_m5qt_Imm4Qb0N9b_WANM2BDj0sUJ-NQSVb_mkICTxcFPGxLqGTUPFroJTKiXtZ23DANjJtYESQKOAw3ex7gWXcmEBGFtOr00NF25lmKQWeoSveDYQHq-O1-PdwimdeVKyEy5oKF4UPdJFjOkwodFcYODCOhMKI7B2CAslOrg3K4up1q0ivSLRvnwqd1sBr4awB5RcVQvwwAmJH_x3H1BFq_NtfK0vhLzF0S3OR0K5qZT_BwYhQjSiH7EF4UKWtW64CpEY4OB1j4R1t7DcgRLa6mEoNWcvzFCYj22HV0jUU5Cw4vct-F2tzs-s2EyNgDVioD3TNkavp9riAcCpq48nuOkapSRrasU5HekC15nzcboE0ILc1NiijnCFx3b3bQ53KO6IZzGbbO4VDkPa4IPvDrOB8qcF4bboeKeBBga7Lh0r0n4jufrns_OHg_HkReSzzkzr6ltedtP7ZKwoUaTNIOkPuf6a_cxoLHwRR_CB_dyrjDlfBkhiDHMxmbjhDTQetS3oxKOsylzY4RHIw5-yothVPr_0oKEyEW3vyhWeQzsVZRZNrUbtjVarZfjxF6MkBjoDax_M_Tti0_onVxhYZ9pLAnM0IcK6L9-DvIBTLukbWOovUF-IBP8GHEzEJdvyatRfqY6swA4JcjFBQ7Z9vRGUVM795I-bJDPlgdX_1KdbBuXRxyWltp4ZaHssUNh8BuN5hcTtepNNiU_eTijDaR_kdsnkV6Ckuq-dUjm8nu7_FHvYvrq_eAnedwU74cQ4wt-lsYF5-q4HNkWFCKN-KUBaRi0x-pHrVayDfMVFk_ULrZC-q6gdJvUjUygojsCpvvwnkNNbToxj_RGWhwZpAUrPzOOc77jsMLSVtOPdpsxZC-VMyR7pstopgjFVFBABwsfhmb__VlW8FFLKiawBpBMZFAuIHnjdFyMev2HVF0dEPEO5L_0xyVhYESSPWadPOJJCi9PzO4Ihaxo6dQg9FCK4-9FhiKeJl-zw74ngZzW4P94oKMjaIH4BcIr6Bh7gbuCdHL3voIf9LTRbII5v0hRjFHj_1V9_GVSErhT9JF71kgjZcA3z_WZzDn_0000 "Click for SVG image of SAMD Class Hierarchy") +[![**Catena SAMD Class Hierarchy (full detail):**](http://www.plantuml.com/plantuml/png/xLbhRzf85_xC_8gf-kfjakO2fBcekvLA2OdG0a50jX-g2etj0tXZptXdngHiD_zzZmSRNu8XLTLj8ksN9ZxFSoxdoPdZWRvNcaaT-XuvUaL8LpYX1syhJQQ1imzCmM7WCMvmSXboMxk2loMLVcIywNQeX0b8u3PG9KA9FoP2qa6hST5j7VeEZIYsnvIYZikcalc7f4AQ8bX8TphJ66W8G9bj2pzWVE7oAUsqcwtUi4KdhWV8ROHw9YGIHo3bWdQ5aB1FkyrccpQ538HaKKMLdfY3Ru6azMhjd92UqA2oPRe-cuAYBezgwrwOsfW4EWKE608SQYrem9IEIj0pLvdyoDU2LFGCkmCvn_1CqvdMmTkZexkxkvKqXrZ_KVAmJnbtAFPgMSjWs8O45NeczisWemuf7SsYI4nHBQW5r14yIe4Pc4UrwuFQftUkdg5g4wEl9fKvyq9i0HmNopMLHR7fd4cNMHuY5dZYxX130yLwV7IA6ax_6AHovteO7l2VXGZf7TRmIb4Eu81pICYh8q9U_0zu5Arhr5Jq7QsjR4Fj7zVHKaqjp7SCXN26DGVC1jgrRNSvFVGh8SnIMZ9RnqEGZXM2bBv6C4ImTTC-VJEsmgZNiVxb0O8Fg5qUkU7kdo6qBrPkdpwlWnFV10OU-lIwtneqHktUrVYoqxWQfa2_qnXTNW-w6VjNfPbsxViG5J-kZpN5cT8uvFwbnwPgV0KQpqmlZEJQsSrvM49ur1PSQVWIoBpVwt5ReHyA7plDXUlG8Pj07ylLazXgl6CHFiHzqZtCELmej2O94vNlb_ncOzJgDSP9CyPXbLt8ziK3FvCTMObgIVePa-YTsfTY9kZMP35n9Hr2rq5qtZ28aI7NV0cOzSvfkBuB2wOkBn5csKyyXJtcmyukDSYwG4CF87WOw58od-vDGKU_PEiFXETbdoKMeZJ8Q-iFi7MCCCTfujbat4dAxqinTvKhEBOzr0iFJ9z5Oqms8uLummgob3QVY0BZMZDMGZ7LzK0FsHo6e2B2PdIecSvLW32cAFWc8BRO4GFsaV6aqyAvo2o1lI1zY3WlKw5p6kOZ5LdJT316qLegPJM3iEsiezf3a2xp1i2SHSKVPvuCdDzF50dc-2rT-yBpKE0Mnxa3nBBFqpYwbi3yDaSxD146Mmk9rDNlIrhSvPADSEuveXmaPm71_5anQCc1zCT1qhEX6JKKcqDwJ5FxDBSgZ60HV4zUk1EwazlxkFXtro_u2A_NwDVyqQ5cFBBdCsDOTIRc8ANhG9UfsnNhjiWAcnum6N7sQMeSWaxTIdPQyMm_RkGEbeqDHasKVg1jemXmV3sJL9dq7LakZI4yIMMs2r7IzDPnk0IcPo2xLUmxUTCsUetEzTMut-vbNhyNxQlsgD59hGzqcNY2QHgTpDyjfhFh-sLnsHUtdtapFLo9MttDdZ3EPgqrUhUmYCLOt-v7T8fU3lNR7zdlw-ARA0s0fWz2wAO8kTxvlvNykcnrqv3RSTauuvVouSfP1Vs-wU_W71IR_OwECkUeNAqIKgXofE9ks2xM-NQn391h7_T7kaLAXkZDoScN7pe-PJBSbnLqMdjg1Hq_iOBEgp-beErRELVbcngUl_A2iZVbzHVbbu_UaOQzxV9raDmBoy9ERyTnrF5l67QDJxD_qxvOtNZ6tKQVpaswaKWIVlgyna-vVy5OKruaHv8MHAl_9zgtYtQ2eZrIdlAB_BUAKRm0x-pHfNsUkAfFdtStDPRmVf9gfz-lseyLvK75Pq-zuktNbSAxj_ROXlv5cKzhpsmmiEBQiwku_kmgFdjs5Py_jugFdzl9Ew_Mdbt5cqzUoKNOvK-WbwqNyCnNdh_-VN2G-vgi_DMqqTamjkTDynZduZSofOpqImnIS4bOoOU9pNWTyKB0FE5a6-5q6-6i-aW9bvQYXfqgoJqbXEHJ-0RqjBOHFTw4ueT5Gj8iXQmragOefAoMGnkywkNGMJbqJj9U2hrLITf8eR5QERIQsFlaZrNu_yPtjBfBPgu3r5-Q4eVt-2FqlNy0)](https://www.plantuml.com/plantuml/svg/xLbhRzf85_xC_8gf-kfjakO2fBcekvLA2OdG0a50jX-g2etj0tXZptXdngHiD_zzZmSRNu8XLTLj8ksN9ZxFSoxdoPdZWRvNcaaT-XuvUaL8LpYX1syhJQQ1imzCmM7WCMvmSXboMxk2loMLVcIywNQeX0b8u3PG9KA9FoP2qa6hST5j7VeEZIYsnvIYZikcalc7f4AQ8bX8TphJ66W8G9bj2pzWVE7oAUsqcwtUi4KdhWV8ROHw9YGIHo3bWdQ5aB1FkyrccpQ538HaKKMLdfY3Ru6azMhjd92UqA2oPRe-cuAYBezgwrwOsfW4EWKE608SQYrem9IEIj0pLvdyoDU2LFGCkmCvn_1CqvdMmTkZexkxkvKqXrZ_KVAmJnbtAFPgMSjWs8O45NeczisWemuf7SsYI4nHBQW5r14yIe4Pc4UrwuFQftUkdg5g4wEl9fKvyq9i0HmNopMLHR7fd4cNMHuY5dZYxX130yLwV7IA6ax_6AHovteO7l2VXGZf7TRmIb4Eu81pICYh8q9U_0zu5Arhr5Jq7QsjR4Fj7zVHKaqjp7SCXN26DGVC1jgrRNSvFVGh8SnIMZ9RnqEGZXM2bBv6C4ImTTC-VJEsmgZNiVxb0O8Fg5qUkU7kdo6qBrPkdpwlWnFV10OU-lIwtneqHktUrVYoqxWQfa2_qnXTNW-w6VjNfPbsxViG5J-kZpN5cT8uvFwbnwPgV0KQpqmlZEJQsSrvM49ur1PSQVWIoBpVwt5ReHyA7plDXUlG8Pj07ylLazXgl6CHFiHzqZtCELmej2O94vNlb_ncOzJgDSP9CyPXbLt8ziK3FvCTMObgIVePa-YTsfTY9kZMP35n9Hr2rq5qtZ28aI7NV0cOzSvfkBuB2wOkBn5csKyyXJtcmyukDSYwG4CF87WOw58od-vDGKU_PEiFXETbdoKMeZJ8Q-iFi7MCCCTfujbat4dAxqinTvKhEBOzr0iFJ9z5Oqms8uLummgob3QVY0BZMZDMGZ7LzK0FsHo6e2B2PdIecSvLW32cAFWc8BRO4GFsaV6aqyAvo2o1lI1zY3WlKw5p6kOZ5LdJT316qLegPJM3iEsiezf3a2xp1i2SHSKVPvuCdDzF50dc-2rT-yBpKE0Mnxa3nBBFqpYwbi3yDaSxD146Mmk9rDNlIrhSvPADSEuveXmaPm71_5anQCc1zCT1qhEX6JKKcqDwJ5FxDBSgZ60HV4zUk1EwazlxkFXtro_u2A_NwDVyqQ5cFBBdCsDOTIRc8ANhG9UfsnNhjiWAcnum6N7sQMeSWaxTIdPQyMm_RkGEbeqDHasKVg1jemXmV3sJL9dq7LakZI4yIMMs2r7IzDPnk0IcPo2xLUmxUTCsUetEzTMut-vbNhyNxQlsgD59hGzqcNY2QHgTpDyjfhFh-sLnsHUtdtapFLo9MttDdZ3EPgqrUhUmYCLOt-v7T8fU3lNR7zdlw-ARA0s0fWz2wAO8kTxvlvNykcnrqv3RSTauuvVouSfP1Vs-wU_W71IR_OwECkUeNAqIKgXofE9ks2xM-NQn391h7_T7kaLAXkZDoScN7pe-PJBSbnLqMdjg1Hq_iOBEgp-beErRELVbcngUl_A2iZVbzHVbbu_UaOQzxV9raDmBoy9ERyTnrF5l67QDJxD_qxvOtNZ6tKQVpaswaKWIVlgyna-vVy5OKruaHv8MHAl_9zgtYtQ2eZrIdlAB_BUAKRm0x-pHfNsUkAfFdtStDPRmVf9gfz-lseyLvK75Pq-zuktNbSAxj_ROXlv5cKzhpsmmiEBQiwku_kmgFdjs5Py_jugFdzl9Ew_Mdbt5cqzUoKNOvK-WbwqNyCnNdh_-VN2G-vgi_DMqqTamjkTDynZduZSofOpqImnIS4bOoOU9pNWTyKB0FE5a6-5q6-6i-aW9bvQYXfqgoJqbXEHJ-0RqjBOHFTw4ueT5Gj8iXQmragOefAoMGnkywkNGMJbqJj9U2hrLITf8eR5QERIQsFlaZrNu_yPtjBfBPgu3r5-Q4eVt-2FqlNy0 "Click for SVG image of SAMD Class Hierarchy") ### Platform Management diff --git a/assets/CatenaBase.plantuml b/assets/CatenaBase.plantuml index 6793bf7..ecb0c04 100644 --- a/assets/CatenaBase.plantuml +++ b/assets/CatenaBase.plantuml @@ -55,9 +55,9 @@ abstract class CatenaBase { +ProvisioningStyle GetProvisioningStyle(); +bool GetAbpProvisioningInfo(); +bool GetOtaaProvisioningInfo(); - +void NetSaveFCntUp(); - +void NetSaveFCntDown(); +void NetSaveSessionInfo(); + +void NetSaveSessionState(); + +bool NetGetSessionInfo(); +bool addLoRaWanCommands(); +{static}CatenaBase *pCatenaBase; #{abstract}void registerCommands(); diff --git a/keywords.txt b/keywords.txt index 4baa106..cc71eb0 100644 --- a/keywords.txt +++ b/keywords.txt @@ -85,9 +85,9 @@ MCCIADK_STRINGVAL KEYWORD2 MCCIADK_UNREFERENCED_PARAMETER KEYWORD1 MCCIADK_UNREFERENCED_VARIABLE KEYWORD1 MCCIHWINFO_KEY KEYWORD1 -NetSaveFCntDown KEYWORD2 -NetSaveFCntUp KEYWORD2 NetSaveSessionInfo KEYWORD2 +NetSaveSessionState KEYWORD2 +NetGetSessionState KEYWORD2 OPERATING_FLAGS KEYWORD1 PAGE_BASE KEYWORD2 PIN_ONE_WIRE KEYWORD2 diff --git a/src/CatenaBase.h b/src/CatenaBase.h index 3dd801f..4bc7fca 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -276,13 +276,17 @@ class CatenaBase bool GetAbpProvisioningInfo(Arduino_LoRaWAN::AbpProvisioningInfo *); bool GetOtaaProvisioningInfo(Arduino_LoRaWAN::OtaaProvisioningInfo *); - void NetSaveFCntUp(uint32_t uFCntUp); - void NetSaveFCntDown(uint32_t uFCntDown); void NetSaveSessionInfo( const Arduino_LoRaWAN::SessionInfo &Info, const uint8_t *pExtraInfo, size_t nExtraInfo ); + void NetSaveSessionState( + const Arduino_LoRaWAN::SessionState &State + ); + bool NetGetSessionState( + Arduino_LoRaWAN::SessionState &State + ); bool addLoRaWanCommands(void); diff --git a/src/CatenaStm32L0.h b/src/CatenaStm32L0.h index 81146b4..8891a6d 100644 --- a/src/CatenaStm32L0.h +++ b/src/CatenaStm32L0.h @@ -32,6 +32,14 @@ Copyright notice: #include +static_assert( + ! ARDUINO_LORAWAN_VERSION_COMPARE_LT( + ARDUINO_LORAWAN_VERSION, + ARDUINO_LORAWAN_VERSION_CALC(0, 9, 0, 1) + ), + "ARDUINO_LORAWAN_VERSION must be at least 0.9.0-1" + ); + namespace McciCatena { class CatenaStm32L0 : public CatenaStm32 @@ -146,13 +154,17 @@ class CatenaStm32L0::LoRaWAN : public Arduino_LoRaWAN_network, virtual bool GetOtaaProvisioningInfo( Arduino_LoRaWAN::OtaaProvisioningInfo * ) override; - virtual void NetSaveFCntUp(uint32_t uFCntUp) override; - virtual void NetSaveFCntDown(uint32_t uFCntDown) override; virtual void NetSaveSessionInfo( const SessionInfo &Info, const uint8_t *pExtraInfo, size_t nExtraInfo ) override; + virtual void NetSaveSessionState( + Arduino_LoRaWAN::SessionState const &State + ) override; + virtual bool NetGetSessionState( + Arduino_LoRaWAN::SessionState &State + ) override; // // TODO(tmm@mcci.com) -- the following are not used but are always diff --git a/src/CatenaWingFram2k.h b/src/CatenaWingFram2k.h index 90bea3c..c947de4 100644 --- a/src/CatenaWingFram2k.h +++ b/src/CatenaWingFram2k.h @@ -29,6 +29,14 @@ Copyright notice: #include +static_assert( + ! ARDUINO_LORAWAN_VERSION_COMPARE_LT( + ARDUINO_LORAWAN_VERSION, + ARDUINO_LORAWAN_VERSION_CALC(0, 9, 0, 1) + ), + "ARDUINO_LORAWAN_VERSION must be at least 0.9.0-1" + ); + // // TODO(tmm@mcci.com) // For some reason CatenaWingFram2k doesn't depend on CatenaFeatherM0. @@ -131,13 +139,20 @@ class CatenaWingFram2k::LoRaWAN : public Arduino_LoRaWAN_network, virtual bool GetOtaaProvisioningInfo( Arduino_LoRaWAN::OtaaProvisioningInfo * ) override; - virtual void NetSaveFCntUp(uint32_t uFCntUp) override; - virtual void NetSaveFCntDown(uint32_t uFCntDown) override; virtual void NetSaveSessionInfo( const SessionInfo &Info, const uint8_t *pExtraInfo, size_t nExtraInfo ) override; + virtual void NetSaveSessionState( + const SessionState &State + ); + virtual void NetSaveSessionState( + Arduino_LoRaWAN::SessionState const &State + ) override; + virtual bool NetGetSessionState( + Arduino_LoRaWAN::SessionState &State + ) override; private: CatenaWingFram2k *m_pCatena; diff --git a/src/Catena_FramStorage.h b/src/Catena_FramStorage.h index fa169a3..08e745e 100644 --- a/src/Catena_FramStorage.h +++ b/src/Catena_FramStorage.h @@ -48,6 +48,7 @@ class cFramStorage kOperatingFlags = 15, kBme680Cal = 16, kAppConf = 17, + kLmicSessionState = 18, // when you add something, also update McciCatena::cFramStorage::vItemDefs[]! kMAX }; diff --git a/src/Catena_Mx25v8035f.h b/src/Catena_Mx25v8035f.h index a7554cd..43cba5e 100644 --- a/src/Catena_Mx25v8035f.h +++ b/src/Catena_Mx25v8035f.h @@ -121,10 +121,10 @@ Revision history: #define CATENA_MX25V8035F_PL_BLOCK_0_7 0x84 /* 8 blocks */ #define CATENA_MX25V8035F_PL_BLOCK_ALL 0x85 /* 16 blocks */ -#define CATENA_MX25V8035F_PAGE_BASE(a) ((a) & ~MX25V8035F_PAGE_SIZE) -#define CATENA_MX25V8035F_SECTOR_BASE(a) ((a) & ~MX25V8035F_SECTOR_SIZE) -#define CATENA_MX25V8035F_BLOCK32_BASE(a) ((a) & ~MX25V8035F_BLOCK32_SIZE) -#define CATENA_MX25V8035F_BLOCK64_BASE(a) ((a) & ~MX25V8035F_BLOCK64_SIZE) +#define CATENA_MX25V8035F_PAGE_BASE(a) ((a) & ~(MX25V8035F_PAGE_SIZE - 1)) +#define CATENA_MX25V8035F_SECTOR_BASE(a) ((a) & ~(MX25V8035F_SECTOR_SIZE - 1)) +#define CATENA_MX25V8035F_BLOCK32_BASE(a) ((a) & ~(MX25V8035F_BLOCK32_SIZE - 1)) +#define CATENA_MX25V8035F_BLOCK64_BASE(a) ((a) & ~(MX25V8035F_BLOCK64_SIZE - 1)) namespace McciCatena { diff --git a/src/lib/CatenaBase_NetSave.cpp b/src/lib/CatenaBase_NetSave.cpp index 4478f21..23a6167 100644 --- a/src/lib/CatenaBase_NetSave.cpp +++ b/src/lib/CatenaBase_NetSave.cpp @@ -38,28 +38,6 @@ Revision history: using namespace McciCatena; -void -CatenaBase::NetSaveFCntUp( - uint32_t uFCntUp - ) - { - auto const pFram = this->getFram(); - - if (pFram != nullptr) - pFram->saveField(cFramStorage::kFCntUp, uFCntUp); - } - -void -CatenaBase::NetSaveFCntDown( - uint32_t uFCntDown - ) - { - auto const pFram = this->getFram(); - - if (pFram != nullptr) - pFram->saveField(cFramStorage::kFCntDown, uFCntDown); - } - void CatenaBase::NetSaveSessionInfo( const Arduino_LoRaWAN::SessionInfo &Info, @@ -68,15 +46,21 @@ CatenaBase::NetSaveSessionInfo( ) { auto const pFram = this->getFram(); - - if (pFram != nullptr) + + // note that the v1 header and the V2 header are identical in the + // bytes belwow. + if (pFram != nullptr && (Info.Header.Tag == Arduino_LoRaWAN::kSessionInfoTag_V1 || + Info.Header.Tag == Arduino_LoRaWAN::kSessionInfoTag_V2)) { pFram->saveField(cFramStorage::kNetID, Info.V1.NetID); pFram->saveField(cFramStorage::kDevAddr, Info.V1.DevAddr); pFram->saveField(cFramStorage::kNwkSKey, Info.V1.NwkSKey); pFram->saveField(cFramStorage::kAppSKey, Info.V1.AppSKey); - pFram->saveField(cFramStorage::kFCntUp, Info.V1.FCntUp); - pFram->saveField(cFramStorage::kFCntDown, Info.V1.FCntDown); + if (Info.Header.Tag == Arduino_LoRaWAN::kSessionInfoTag_V1) + { + pFram->saveField(cFramStorage::kFCntUp, Info.V1.FCntUp); + pFram->saveField(cFramStorage::kFCntDown, Info.V1.FCntDown); + } } gLog.printf( @@ -88,4 +72,32 @@ CatenaBase::NetSaveSessionInfo( ); } +void +CatenaBase::NetSaveSessionState( + const Arduino_LoRaWAN::SessionState &State + ) + { + auto const pFram = this->getFram(); + + // note that the v1 header and the V2 header are identical in the + // bytes belwow. + if (pFram != nullptr && (State.Header.Tag == Arduino_LoRaWAN::kSessionStateTag_V1)) + { + pFram->saveField(cFramStorage::kLmicSessionState, State); + } + } + +bool +CatenaBase::NetGetSessionState( + Arduino_LoRaWAN::SessionState &State + ) + { + auto const pFram = this->getFram(); + + if (pFram == nullptr) + return false; + + return pFram->getField(cFramStorage::kLmicSessionState, State); + } + /**** end of CatenaBase_NetSave.cpp ****/ diff --git a/src/lib/CatenaBase_registerCommands.cpp b/src/lib/CatenaBase_registerCommands.cpp index a0fa716..37c2a07 100644 --- a/src/lib/CatenaBase_registerCommands.cpp +++ b/src/lib/CatenaBase_registerCommands.cpp @@ -321,15 +321,18 @@ static void printVersion( cCommandStream *pThis, const char *pLabel, - uint32_t packedVersion + uint32_t packedVersion, + bool fSemantic = false ) { - pThis->printf("%s-Version: %d.%d.%d%s", + const char cSemantic = fSemantic ? '-' : '.'; + + pThis->printf("%s-Version: %d.%d.%d%c", pLabel, (packedVersion >> 24) & 0xFF, (packedVersion >> 16) & 0xFF, (packedVersion >> 8) & 0xFF, - (packedVersion & 0xFF) ? "." : "\n" + (packedVersion & 0xFF) ? cSemantic : '\n' ); if (packedVersion & 0xFF) @@ -360,7 +363,7 @@ doVersion( pThis->printf("Board: %s\n", pCatena->CatenaName()); printVersion(pThis, "Platform", CATENA_ARDUINO_PLATFORM_VERSION); - printVersion(pThis, "Arduino-LoRaWAN", ARDUINO_LORAWAN_VERSION); + printVersion(pThis, "Arduino-LoRaWAN", ARDUINO_LORAWAN_VERSION, true); printVersion(pThis, "Arduino-LMIC", ARDUINO_LMIC_VERSION); printVersion(pThis, "MCCIADK", mcciadk_version); diff --git a/src/lib/Catena_FramStorage.cpp b/src/lib/Catena_FramStorage.cpp index c9d937d..ca4fbbc 100644 --- a/src/lib/Catena_FramStorage.cpp +++ b/src/lib/Catena_FramStorage.cpp @@ -35,6 +35,7 @@ Revision history: #include "Catena_Guids_FramStorage.h" #include +#include using namespace McciCatena; @@ -68,9 +69,10 @@ McciCatena::cFramStorage::vItemDefs[cFramStorage::kMAX] = /* the size field should match BSEC_MAX_STATE_BLOB_SIZE, which is 139 */ cFramStorage::StandardItem(kBme680Cal, 139, /* number */ false), - cFramStorage::StandardItem(kAppConf, cFramStorage::MaxAppConfSize, false) - }; + cFramStorage::StandardItem(kAppConf, cFramStorage::MaxAppConfSize, false), + cFramStorage::StandardItem(kLmicSessionState, sizeof(Arduino_LoRaWAN::SessionState), /* number */ false), + }; /****************************************************************************\ | diff --git a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp index cc9c00d..bad3bf4 100644 --- a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp +++ b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp @@ -132,36 +132,36 @@ CatenaWingFram2k::LoRaWAN::GetProvisioningStyle( return pCatena->GetProvisioningStyle(); } -void -CatenaWingFram2k::LoRaWAN::NetSaveFCntUp( - uint32_t uFCntUp +void +CatenaWingFram2k::LoRaWAN::NetSaveSessionInfo( + const SessionInfo &Info, + const uint8_t *pExtraInfo, + size_t nExtraInfo ) { CatenaWingFram2k * const pCatena = this->m_pCatena; - pCatena->NetSaveFCntUp(uFCntUp); + pCatena->NetSaveSessionInfo(Info, pExtraInfo, nExtraInfo); } void -CatenaWingFram2k::LoRaWAN::NetSaveFCntDown( - uint32_t uFCntDown +CatenaWingFram2k::LoRaWAN::NetSaveSessionState( + const SessionState &State ) { CatenaWingFram2k * const pCatena = this->m_pCatena; - pCatena->NetSaveFCntDown(uFCntDown); - } + pCatena->NetSaveSessionState(State); + } -void -CatenaWingFram2k::LoRaWAN::NetSaveSessionInfo( - const SessionInfo &Info, - const uint8_t *pExtraInfo, - size_t nExtraInfo +bool +CatenaWingFram2k::LoRaWAN::NetGetSessionState( + SessionState &State ) { CatenaWingFram2k * const pCatena = this->m_pCatena; - pCatena->NetSaveSessionInfo(Info, pExtraInfo, nExtraInfo); + return pCatena->NetGetSessionState(State); } #endif // ARDUINO_ARCH_SAMD diff --git a/src/lib/stm32/stm32l0/CatenaStm32L0_LoRaWAN_storage.cpp b/src/lib/stm32/stm32l0/CatenaStm32L0_LoRaWAN_storage.cpp index 574045b..bc5a4a0 100644 --- a/src/lib/stm32/stm32l0/CatenaStm32L0_LoRaWAN_storage.cpp +++ b/src/lib/stm32/stm32l0/CatenaStm32L0_LoRaWAN_storage.cpp @@ -44,35 +44,35 @@ Revision history: using namespace McciCatena; void -CatenaStm32L0::LoRaWAN::NetSaveFCntUp( - uint32_t uFCntUp +CatenaStm32L0::LoRaWAN::NetSaveSessionInfo( + const SessionInfo &Info, + const uint8_t *pExtraInfo, + size_t nExtraInfo ) { CatenaStm32L0 * const pCatena = this->m_pCatena; - pCatena->NetSaveFCntUp(uFCntUp); + pCatena->NetSaveSessionInfo(Info, pExtraInfo, nExtraInfo); } void -CatenaStm32L0::LoRaWAN::NetSaveFCntDown( - uint32_t uFCntDown +CatenaStm32L0::LoRaWAN::NetSaveSessionState( + const SessionState &State ) { CatenaStm32L0 * const pCatena = this->m_pCatena; - pCatena->NetSaveFCntDown(uFCntDown); - } + pCatena->NetSaveSessionState(State); + } -void -CatenaStm32L0::LoRaWAN::NetSaveSessionInfo( - const SessionInfo &Info, - const uint8_t *pExtraInfo, - size_t nExtraInfo +bool +CatenaStm32L0::LoRaWAN::NetGetSessionState( + SessionState &State ) { CatenaStm32L0 * const pCatena = this->m_pCatena; - pCatena->NetSaveSessionInfo(Info, pExtraInfo, nExtraInfo); + return pCatena->NetGetSessionState(State); } #endif // ARDUINO_ARCH_STM32 From ab977da09fdad3a33bfeb9b21a7d9f7c276644e6 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 13:50:29 -0400 Subject: [PATCH 02/28] Fix #287: switch to semantic versioning for this library --- src/CatenaBase.h | 30 ++++++++++++++++++++++--- src/lib/CatenaBase_registerCommands.cpp | 2 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index 4bc7fca..dd511dd 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -47,15 +47,16 @@ Copyright notice: #include -#if ! (defined(ARDUINO_LORAWAN_VERSION) && ARDUINO_LORAWAN_VERSION >= ARDUINO_LORAWAN_VERSION_CALC(0,6,0,20)) +#if ! (defined(ARDUINO_LORAWAN_VERSION_COMPARE_LT) && \ + ! ARDUINO_LORAWAN_VERSION_COMPARE_LT(ARDUINO_LORAWAN_VERSION, ARDUINO_LORAWAN_VERSION_CALC(0,9,0,1))) # error Arduino_LoRaWAN library is out of date. Check ARDUINO_LORAWAN_VERSION. #endif -// Catena-Arduino-Platform Version +// Catena-Arduino-Platform Version: uses semantic version for local (so local == 0 is > non-zero) #define CATENA_ARDUINO_PLATFORM_VERSION_CALC(major, minor, patch, local) \ (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) -#define CATENA_ARDUINO_PLATFORM_VERSION CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 20, 1, 0) /* v0.20.1.0 */ +#define CATENA_ARDUINO_PLATFORM_VERSION CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 1) /* v0.21.0-1 */ #define CATENA_ARDUINO_PLATFORM_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) @@ -69,6 +70,29 @@ Copyright notice: #define CATENA_ARDUINO_PLATFORM_VERSION_GET_LOCAL(v) \ ((v) & 0xFFu) +/// \brief convert a semantic version to an integer. +#define CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(v) \ + (((v) & 0xFFFFFF00u) | (((v) - 1) & 0xFFu)) + +/// \brief compare two semantic versions +/// \return \c true if \b a is less than \b b (as a semantic version). +#define CATENA_ARDUINO_PLATFORM_VERSION_COMPARE_LT(a, b) \ + (CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(a) < CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(b)) + +/// \brief compare two semantic versions +/// \return \c true if \b a is greater than or equal to \b b (as a semantic version). +#define CATENA_ARDUINO_PLATFORM_VERSION_COMPARE_GE(a, b) \ + (CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(a) >= CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(b)) + +/// \brief compare two semantic versions +/// \return \c true if \b a is greater than \b b (as a semantic version). +#define CATENA_ARDUINO_PLATFORM_VERSION_COMPARE_GT(a, b) \ + (CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(a) > CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(b)) + +/// \brief compare two semantic versions +/// \return \c true if \b a is less than or equal to \b b (as a semantic version). +#define CATENA_ARDUINO_PLATFORM_VERSION_COMPARE_LE(a, b) \ + (CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(a) <= CATENA_ARDUINO_PLATFORM_VERSION_TO_INT(b)) namespace McciCatena { diff --git a/src/lib/CatenaBase_registerCommands.cpp b/src/lib/CatenaBase_registerCommands.cpp index 37c2a07..5f6e05e 100644 --- a/src/lib/CatenaBase_registerCommands.cpp +++ b/src/lib/CatenaBase_registerCommands.cpp @@ -362,7 +362,7 @@ doVersion( } pThis->printf("Board: %s\n", pCatena->CatenaName()); - printVersion(pThis, "Platform", CATENA_ARDUINO_PLATFORM_VERSION); + printVersion(pThis, "Platform", CATENA_ARDUINO_PLATFORM_VERSION, true); printVersion(pThis, "Arduino-LoRaWAN", ARDUINO_LORAWAN_VERSION, true); printVersion(pThis, "Arduino-LMIC", ARDUINO_LMIC_VERSION); printVersion(pThis, "MCCIADK", mcciadk_version); From 1ec51eae44148e8612658ed69b34ca5aa70da4d2 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 16:24:54 -0400 Subject: [PATCH 03/28] Bugfix: FCntUp and FCntDown were being reset becuase we had two copies --- src/lib/CatenaBase_GetAbpProvisioningInfo.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/CatenaBase_GetAbpProvisioningInfo.cpp b/src/lib/CatenaBase_GetAbpProvisioningInfo.cpp index ca74fbb..8beab84 100644 --- a/src/lib/CatenaBase_GetAbpProvisioningInfo.cpp +++ b/src/lib/CatenaBase_GetAbpProvisioningInfo.cpp @@ -109,6 +109,7 @@ CatenaBase::GetAbpProvisioningInfo( ) { auto const pFram = this->getFram(); + Arduino_LoRaWAN::SessionState State; if (pFram == nullptr) { @@ -127,8 +128,7 @@ CatenaBase::GetAbpProvisioningInfo( framAppSKey(pFram), framDevAddr(pFram), framNetID(pFram), - framFCntUp(pFram), - framFCntDown(pFram); + framSessionState(pFram); bool fResult; @@ -138,8 +138,7 @@ CatenaBase::GetAbpProvisioningInfo( framAppSKey.locate(cFramStorage::vItemDefs[cFramStorage::kAppSKey]) && framDevAddr.locate(cFramStorage::vItemDefs[cFramStorage::kDevAddr]) && framNetID.locate(cFramStorage::vItemDefs[cFramStorage::kNetID]) && - framFCntUp.locate(cFramStorage::vItemDefs[cFramStorage::kFCntUp]) && - framFCntDown.locate(cFramStorage::vItemDefs[cFramStorage::kFCntDown])) + framSessionState.locate(cFramStorage::vItemDefs[cFramStorage::kLmicSessionState])) fResult = true; if (! fResult) @@ -159,8 +158,9 @@ CatenaBase::GetAbpProvisioningInfo( framAppSKey.get(pInfo->AppSKey, sizeof(pInfo->AppSKey)); framDevAddr.getuint32(pInfo->DevAddr); framNetID.getuint32(pInfo->NetID); - framFCntUp.getuint32(pInfo->FCntUp); - framFCntDown.getuint32(pInfo->FCntDown); + framSessionState.get((uint8_t *)&State, sizeof(State)); + pInfo->FCntDown = State.V1.FCntDown; + pInfo->FCntUp = State.V1.FCntUp; return true; } From fcb6eda051af2741e55c5ad6ae759c19b7a9f41e Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 16:26:13 -0400 Subject: [PATCH 04/28] Change lorawan config to use the SessionState for FCntUp/FCntDown manipulation --- src/Catena_Fram.h | 22 ++++++ src/lib/CatenaBase_addLoRaWanCommands.cpp | 86 +++++++++++++++++------ src/lib/Catena_Fram.cpp | 32 ++++++++- 3 files changed, 118 insertions(+), 22 deletions(-) diff --git a/src/Catena_Fram.h b/src/Catena_Fram.h index 7554144..f3adb22 100644 --- a/src/Catena_Fram.h +++ b/src/Catena_Fram.h @@ -250,6 +250,14 @@ class cFram::Cursor size_t nData ) const; + // parse a field + static bool parsefield( + const char *pValue, + uint8_t *pData, + size_t nData, + bool isNumber + ); + size_t formatvalue( char *pBuffer, size_t nBuffer, @@ -257,6 +265,20 @@ class cFram::Cursor const uint8_t *pData, size_t nData ) const; + + static size_t formatfield( + char *pBuffer, + size_t nBuffer, + size_t iBuffer, + const uint8_t *pData, + size_t nData, + bool isNum + ); + + cFramStorage::StandardKeys getKey() const + { + return cFramStorage::StandardKeys(this->m_uKey); + } private: cFramStorage::StandardItem getItem() diff --git a/src/lib/CatenaBase_addLoRaWanCommands.cpp b/src/lib/CatenaBase_addLoRaWanCommands.cpp index 4c66c97..9757a0f 100644 --- a/src/lib/CatenaBase_addLoRaWanCommands.cpp +++ b/src/lib/CatenaBase_addLoRaWanCommands.cpp @@ -47,6 +47,8 @@ struct KeyMap { const char *pName; cFramStorage::StandardKeys uKey; + unsigned fieldOffset; + unsigned fieldSize; }; static KeyMap sKeyMap[] = @@ -58,8 +60,14 @@ static KeyMap sKeyMap[] = { "appskey", cFramStorage::StandardKeys::kAppSKey, }, { "devaddr", cFramStorage::StandardKeys::kDevAddr, }, { "netid", cFramStorage::StandardKeys::kNetID, }, - { "fcntup", cFramStorage::StandardKeys::kFCntUp, }, - { "fcntdown", cFramStorage::StandardKeys::kFCntDown, }, + { "fcntup", cFramStorage::StandardKeys::kLmicSessionState, + offsetof(Arduino_LoRaWAN::SessionStateV1, FCntUp), + sizeof(Arduino_LoRaWAN::SessionStateV1::FCntUp) + }, + { "fcntdown", cFramStorage::StandardKeys::kLmicSessionState, + offsetof(Arduino_LoRaWAN::SessionStateV1, FCntDown), + sizeof(Arduino_LoRaWAN::SessionStateV1::FCntDown) + }, { "join", cFramStorage::StandardKeys::kJoin, }, }; @@ -148,14 +156,14 @@ doConfigure( { CatenaBase * const pCatena = static_cast(pContext); cFram::Cursor cursor(pCatena->getFram()); - static constexpr unsigned databuf_size = 16; + static constexpr unsigned databuf_size = 256; - auto printValue = [](cCommandStream *pThis, cFram::Cursor &cursor, const char *pName) -> cCommandStream::CommandStatus + auto printValue = [](cCommandStream *pThis, cFram::Cursor &cursor, const KeyMap &p) -> cCommandStream::CommandStatus { uint8_t databuf[databuf_size]; if (! cursor.islocated()) { - pThis->printf("%s: not initialized\n", pName); + pThis->printf("%s: not initialized\n", p.pName); return cCommandStream::CommandStatus::kNotInitialized; } else @@ -170,14 +178,26 @@ doConfigure( if (! cursor.get(databuf, size)) { - pThis->printf("%s: read error\n", pName); + pThis->printf("%s: read error\n", p.pName); return cCommandStream::CommandStatus::kReadError; } - cursor.formatvalue( - strbuf, sizeof(strbuf), 0, - databuf, size - ); + if (cursor.getKey() == cFramStorage::StandardKeys::kLmicSessionState) + { + // it's a state variable + cursor.formatfield(strbuf, sizeof(strbuf), 0, + &databuf[p.fieldOffset], + p.fieldSize, + /* is number? */ true + ); + } + else + { + cursor.formatvalue( + strbuf, sizeof(strbuf), 0, + databuf, size + ); + } pThis->printf("%s\n", strbuf); return cCommandStream::CommandStatus::kSuccess; @@ -194,20 +214,22 @@ doConfigure( continue; pThis->printf("lorawan %s %s ", argv[0], p.pName); - (void) printValue(pThis, cursor, p.pName); + (void) printValue(pThis, cursor, p); } return cCommandStream::CommandStatus::kSuccess; } const char * const pName = argv[1]; + const KeyMap *p = nullptr; - for (auto const & p : sKeyMap) + for (auto const & Key : sKeyMap) { - if (strcasecmp(p.pName, pName) == 0) + if (strcasecmp(Key.pName, pName) == 0) { // matched! - cursor.locate(p.uKey); + cursor.locate(Key.uKey); + p = &Key; } } @@ -224,25 +246,49 @@ doConfigure( // display if (argc <= 2) { - return printValue(pThis, cursor, pName); + return printValue(pThis, cursor, *p); } else { const char * const pValue = argv[2]; uint8_t databuf[databuf_size]; size_t size; + bool fParseOk; + /* + || fcntup and fcntdown are in a bigger field, so things + || get sophisticated. + */ size = cursor.getitemsize(); if (size > sizeof(databuf)) size = sizeof(databuf); // parse the argument according to the cursor (which // specifies what will receive it - if (! cursor.parsevalue( - pValue, - databuf, - size - )) + if (cursor.getKey() == cFramStorage::StandardKeys::kLmicSessionState) + { + if (! cursor.get(databuf, size)) + { + pThis->printf("%s: could not create entry\n", + pName + ); + + return cCommandStream::CommandStatus::kCreateError; + } + fParseOk = cursor.parsefield( + pValue, + databuf + p->fieldOffset, + p->fieldSize, + true + ); + } + else + fParseOk = cursor.parsevalue( + pValue, + databuf, + size + ); + if (! fParseOk) { pThis->printf("%s: invalid parameter: %s\n", pName, pValue diff --git a/src/lib/Catena_Fram.cpp b/src/lib/Catena_Fram.cpp index 655537b..e879fb7 100644 --- a/src/lib/Catena_Fram.cpp +++ b/src/lib/Catena_Fram.cpp @@ -997,6 +997,17 @@ McciCatena::cFram::Cursor::parsevalue( if (nData != item.getSize()) return false; + return parsefield(pValue, pData, nData, item.isNumber()); + } + +bool +McciCatena::cFram::Cursor::parsefield( + const char *pValue, + uint8_t *pData, + size_t nData, + bool isNumber + ) + { // value is hex, and may have embedded '-' to separate // bytes. At the end, if it's a number, we have to reverse // it.... for sanity, start with zeros. As a further @@ -1050,7 +1061,7 @@ McciCatena::cFram::Cursor::parsevalue( } // if it's a number, we now have to byte-reverse - if (item.isNumber()) + if (isNumber) { size_t nData2 = nData/2; size_t i, j; @@ -1061,6 +1072,7 @@ McciCatena::cFram::Cursor::parsevalue( return true; } + size_t McciCatena::cFram::Cursor::formatvalue( char *pBuffer, @@ -1080,6 +1092,22 @@ McciCatena::cFram::Cursor::formatvalue( if (! this->getitem(item)) return iBuffer; + return formatfield(pBuffer, nBuffer, iBuffer, pData, nData, item.isNumber()); + } + +size_t +McciCatena::cFram::Cursor::formatfield( + char *pBuffer, + size_t nBuffer, + size_t iBuffer, + const uint8_t *pData, + size_t nData, + bool isNum + ) + { + if (iBuffer < nBuffer) + pBuffer[iBuffer] = '\0'; + // if it's a number, we need to reverse it. // TODO(tmm@mcci.com): better formatting for GUIDs for (size_t i = 0; i < nData; ++i) @@ -1087,7 +1115,7 @@ McciCatena::cFram::Cursor::formatvalue( size_t j; const char *pSep; pSep = "-"; - if (item.isNumber()) + if (isNum) { j = nData - i - 1; if (nData <= 4 || j == 0) From fa27ef53ef7d051c52433a12a415c81ab5d1cacf Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 16:26:39 -0400 Subject: [PATCH 05/28] Step version number to 0.21.0-2 --- src/CatenaBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index dd511dd..56b4564 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -56,7 +56,8 @@ Copyright notice: #define CATENA_ARDUINO_PLATFORM_VERSION_CALC(major, minor, patch, local) \ (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) -#define CATENA_ARDUINO_PLATFORM_VERSION CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 1) /* v0.21.0-1 */ +#define CATENA_ARDUINO_PLATFORM_VERSION \ + CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 2) /* v0.21.0-2 */ #define CATENA_ARDUINO_PLATFORM_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From 0f19c32a522838060a002e12077479e58666766b Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 2 Apr 2021 16:32:38 -0400 Subject: [PATCH 06/28] Trim whitespace --- examples/catena_fsm/catena_fsm.ino | 2 +- examples/catena_hello/catena_hello.ino | 2 +- .../catena_hello_lora/catena_hello_lora.ino | 2 +- src/Catena4410.h | 10 ++-- src/Catena4410_project_config.h | 4 +- src/Catena4420_project_config.h | 4 +- src/Catena4450.h | 4 +- src/Catena4460.h | 4 +- src/Catena4470.h | 4 +- src/CatenaBase_types.h | 4 +- src/CatenaFeatherM0.h | 4 +- src/CatenaRTC.h | 6 +- src/CatenaSamd21.h | 4 +- src/CatenaStm32L0.h | 2 +- src/CatenaWingFram2k.h | 2 +- src/Catena_Completion.h | 6 +- src/Catena_FSM.h | 8 +-- src/Catena_Fram.h | 18 +++--- src/Catena_Fram2k.h | 4 +- src/Catena_Fram8k.h | 4 +- src/Catena_Guids_FramStorage.h | 4 +- src/Catena_Led.h | 10 ++-- src/Catena_PersistentStorage.h | 4 +- src/Catena_PollableInterface.h | 4 +- src/Catena_Si1133.h | 16 ++--- src/Catena_functional.h | 4 +- src/McciHwInfo.h | 4 +- src/lib/CatenaBase.cpp | 6 +- src/lib/CatenaBase_GetUniqueIDstring.cpp | 8 +-- src/lib/CatenaBase_NetSave.cpp | 4 +- src/lib/CatenaBase_SafePrintf.cpp | 14 ++--- src/lib/Catena_Fram.cpp | 58 +++++++++---------- src/lib/Catena_Fram2k.cpp | 26 ++++----- src/lib/Catena_Fram8k.cpp | 26 ++++----- src/lib/Catena_Log.cpp | 8 +-- src/lib/Catena_Mb85rc64ta.cpp | 4 +- src/lib/samd/CatenaRTC.cpp | 10 ++-- src/lib/samd/CatenaSamd21.cpp | 6 +- src/lib/samd/CatenaSamd21_begin.cpp | 10 ++-- .../samd/CatenaSamd21_registerCommands.cpp | 6 +- src/lib/samd/catena4410/Catena4410.cpp | 10 ++-- .../Catena4410_getCpuIdPlatformTable.cpp | 30 +++++----- .../catena4410/Catena4410_gk_lorawan_keys.cpp | 2 +- src/lib/samd/catena4420/Catena4420.cpp | 4 +- .../Catena4420_getCpuIdPlatformTable.cpp | 24 ++++---- .../catena4420/Catena4420_gk_lorawan_keys.cpp | 2 +- .../Catena4450_getCpuIdPlatformTable.cpp | 24 ++++---- .../Catena4450_getPlatformTable.cpp | 6 +- .../Catena4460_getPlatformTable.cpp | 6 +- .../Catena4470_getPlatformTable.cpp | 6 +- src/lib/samd/catenasamd21_getuniqueid.cpp | 10 ++-- .../samd/catenasamd_gk_plaformhierarchy.cpp | 8 +-- .../CatenaWingFram2k_LoRaWAN_begin.cpp | 6 +- .../CatenaWingFram2k_LoRaWAN_storage.cpp | 10 ++-- .../CatenaWingFram2k_ReadVbat.cpp | 2 +- .../CatenaWingFram2k_begin.cpp | 12 ++-- .../samd/featherm0/catenafeatherm0_begin.cpp | 2 +- .../catenafeatherm0_getprovisioninginfo.cpp | 14 ++--- .../catenafeatherm0_lorawan_begin.cpp | 10 ++-- ...atherm0_lorawan_getabpprovisioninginfo.cpp | 10 ++-- ...therm0_lorawan_getotaaprovisioninginfo.cpp | 10 ++-- ...featherm0_lorawan_getprovisioningstyle.cpp | 4 +- .../featherm0/catenafeatherm0_readvbat.cpp | 6 +- src/lib/stm32/CatenaStm32_GetUniqueID.cpp | 10 ++-- .../stm32/CatenaStm32_registerCommands.cpp | 4 +- .../Catena4551_getPlatformTable.cpp | 2 +- .../Catena4610_getPlatformTable.cpp | 2 +- .../Catena4611_getPlatformTable.cpp | 2 +- .../Catena4612_getPlatformTable.cpp | 2 +- .../Catena4801_getPlatformTable.cpp | 2 +- .../Catena4802_getPlatformTable.cpp | 2 +- .../stm32l0/CatenaStm32L0_ReadAnalog.cpp | 2 +- 72 files changed, 288 insertions(+), 288 deletions(-) diff --git a/examples/catena_fsm/catena_fsm.ino b/examples/catena_fsm/catena_fsm.ino index 86ab77e..83fcdd7 100644 --- a/examples/catena_fsm/catena_fsm.ino +++ b/examples/catena_fsm/catena_fsm.ino @@ -57,7 +57,7 @@ public: }; // the begin method initializes the fsm - void begin() + void begin() { if (! this->m_fRunning) this->m_fsm.init(*this, &Turnstile::fsmDispatch); diff --git a/examples/catena_hello/catena_hello.ino b/examples/catena_hello/catena_hello.ino index 0a82b47..9399eff 100644 --- a/examples/catena_hello/catena_hello.ino +++ b/examples/catena_hello/catena_hello.ino @@ -7,7 +7,7 @@ Function: Copyright notice and License: See LICENSE file accompanying this project. - + Author: Terry Moore, MCCI Corporation April 2018 diff --git a/examples/catena_hello_lora/catena_hello_lora.ino b/examples/catena_hello_lora/catena_hello_lora.ino index 1f7efe9..a493863 100644 --- a/examples/catena_hello_lora/catena_hello_lora.ino +++ b/examples/catena_hello_lora/catena_hello_lora.ino @@ -7,7 +7,7 @@ Function: Copyright notice and License: See LICENSE file accompanying this project. - + Author: Terry Moore, MCCI Corporation April 2018 diff --git a/src/Catena4410.h b/src/Catena4410.h index 83b5f38..4cccdaa 100644 --- a/src/Catena4410.h +++ b/src/Catena4410.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -63,7 +63,7 @@ class Catena4410 : public CatenaFeatherM0 PIN_SHT10_CLK = 11, PIN_SHT10_DATA = 10 }; - + /* || Methods */ @@ -107,11 +107,11 @@ class Catena4410::LoRaWAN : public CatenaFeatherM0::LoRaWAN || the constructor. */ LoRaWAN() {}; - + /* || the begin function loads data from the local || platform's stable storage and initializes - || the connection. + || the connection. */ // bool begin(Catena4410 *pCatena4410); diff --git a/src/Catena4410_project_config.h b/src/Catena4410_project_config.h index 01fe88f..f7f3bc9 100644 --- a/src/Catena4410_project_config.h +++ b/src/Catena4410_project_config.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation November 2016 diff --git a/src/Catena4420_project_config.h b/src/Catena4420_project_config.h index 2a52baf..c101cbf 100644 --- a/src/Catena4420_project_config.h +++ b/src/Catena4420_project_config.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation November 2016 diff --git a/src/Catena4450.h b/src/Catena4450.h index b579acf..57ac7d9 100644 --- a/src/Catena4450.h +++ b/src/Catena4450.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/Catena4460.h b/src/Catena4460.h index 01ff977..482ad82 100644 --- a/src/Catena4460.h +++ b/src/Catena4460.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2018 diff --git a/src/Catena4470.h b/src/Catena4470.h index e68e308..9e159af 100644 --- a/src/Catena4470.h +++ b/src/Catena4470.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2018 diff --git a/src/CatenaBase_types.h b/src/CatenaBase_types.h index 97cec5c..6df88e9 100644 --- a/src/CatenaBase_types.h +++ b/src/CatenaBase_types.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/CatenaFeatherM0.h b/src/CatenaFeatherM0.h index 0088c71..977fb23 100644 --- a/src/CatenaFeatherM0.h +++ b/src/CatenaFeatherM0.h @@ -84,11 +84,11 @@ class CatenaFeatherM0::LoRaWAN : public Arduino_LoRaWAN_network, || the constructor. */ LoRaWAN() {}; - + /* || the begin function loads data from the local || platform's stable storage and initializes - || the connection. + || the connection. */ virtual bool begin(CatenaFeatherM0 *pCatena); diff --git a/src/CatenaRTC.h b/src/CatenaRTC.h index 6d3214d..b57f95f 100644 --- a/src/CatenaRTC.h +++ b/src/CatenaRTC.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation November 2016 @@ -87,7 +87,7 @@ class CatenaRTC void SetAlarm(const CalendarTime *pNow); - void SleepForAlarm(Alarm_Match how = MATCH_HHMMSS, + void SleepForAlarm(Alarm_Match how = MATCH_HHMMSS, SleepMode howSleep = SleepMode::IdleCpu ); diff --git a/src/CatenaSamd21.h b/src/CatenaSamd21.h index bfa8201..3279d94 100644 --- a/src/CatenaSamd21.h +++ b/src/CatenaSamd21.h @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. @@ -65,7 +65,7 @@ namespace McciCatena { /* the class for Samd21-based Catenas */ class CatenaSamd21 : public CatenaBase { -public: +public: using Super = CatenaBase; /* diff --git a/src/CatenaStm32L0.h b/src/CatenaStm32L0.h index 8891a6d..0dbd9ec 100644 --- a/src/CatenaStm32L0.h +++ b/src/CatenaStm32L0.h @@ -102,7 +102,7 @@ class CatenaStm32L0 : public CatenaStm32 // In future versions, this might change; some STM32L0 implementations // might not have a crystal so LSE won't work. But for now, we assume // that there's a crystal for LSE. -#if defined(_mcci_arduino_version) +#if defined(_mcci_arduino_version) # if _mcci_arduino_version >= _mcci_arduino_version_calc(2,4,0,90) static constexpr bool kUsesLSE = true; // _mcci_arduino_version indicates that LSE clock is used. # else diff --git a/src/CatenaWingFram2k.h b/src/CatenaWingFram2k.h index c947de4..eeac8c1 100644 --- a/src/CatenaWingFram2k.h +++ b/src/CatenaWingFram2k.h @@ -90,7 +90,7 @@ class CatenaWingFram2k : public CatenaSamd21 }; bool getBootCount(uint32_t &bootCount) - { + { bootCount = this->m_BootCount; return true; }; diff --git a/src/Catena_Completion.h b/src/Catena_Completion.h index 4950ce8..4e742af 100644 --- a/src/Catena_Completion.h +++ b/src/Catena_Completion.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -40,7 +40,7 @@ namespace McciCatena { // a completion is an abstract class; pass a pointer to this to // any of the event processors, and it will get dispatched. Note that -// in your derived version, +// in your derived version, class cCompletion { public: diff --git a/src/Catena_FSM.h b/src/Catena_FSM.h index 00d0359..cd01a2f 100644 --- a/src/Catena_FSM.h +++ b/src/Catena_FSM.h @@ -162,7 +162,7 @@ Name: McciCatena::cFSM::eval() the outer evaluator; its job is to keep applying the parent's fsmDispatch() until there's no more work to be done. - + While doing that, it watches for recursive calls to eval(), and schedules additional executions until everything settles down. @@ -179,7 +179,7 @@ Name: McciCatena::cFSM::eval() is the type of the parent object for this finite state machine; it's used so we can call the dispatch function: - + TState TParent::dispatch( TState currentState, bool fEntry // true if just entering @@ -219,9 +219,9 @@ void cFSM::eval(void) break; // call the state dispatcher. - auto const newState = + auto const newState = (this->m_parent->*this->m_dispatch)( - oldState, + oldState, fStateChanged ); diff --git a/src/Catena_Fram.h b/src/Catena_Fram.h index f3adb22..9e13ed7 100644 --- a/src/Catena_Fram.h +++ b/src/Catena_Fram.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -57,7 +57,7 @@ class cFram : public cPersistentStorage using Super = cPersistentStorage; public: - virtual bool begin() override + virtual bool begin() override { this->resetCache(); this->m_endOffset = 0; @@ -183,17 +183,17 @@ class cFram::Cursor { public: // the basic constructor just fills things in. - Cursor(cFram *pFram) - : m_pFram(pFram), - m_uKey(cFramStorage::StandardKeys::kMAX), - m_offset(cFramStorage::kInvalidOffset) + Cursor(cFram *pFram) + : m_pFram(pFram), + m_uKey(cFramStorage::StandardKeys::kMAX), + m_offset(cFramStorage::kInvalidOffset) {}; // construct and locate Cursor(cFram *pFram, cFramStorage::StandardItem item); // construct and locate using key - Cursor(cFram *pFram, cFramStorage::StandardKeys uKey) + Cursor(cFram *pFram, cFramStorage::StandardKeys uKey) : Cursor{pFram, cFramStorage::vItemDefs[uKey]} {}; // take a located cursor and create an object if needed @@ -279,7 +279,7 @@ class cFram::Cursor { return cFramStorage::StandardKeys(this->m_uKey); } - + private: cFramStorage::StandardItem getItem() { diff --git a/src/Catena_Fram2k.h b/src/Catena_Fram2k.h index 03e623c..e251730 100644 --- a/src/Catena_Fram2k.h +++ b/src/Catena_Fram2k.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/Catena_Fram8k.h b/src/Catena_Fram8k.h index de74b34..9f6158d 100644 --- a/src/Catena_Fram8k.h +++ b/src/Catena_Fram8k.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: ChaeHee Won, MCCI Corporation October 2017 diff --git a/src/Catena_Guids_FramStorage.h b/src/Catena_Guids_FramStorage.h index 2cd19a0..5bd1c3b 100644 --- a/src/Catena_Guids_FramStorage.h +++ b/src/Catena_Guids_FramStorage.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/Catena_Led.h b/src/Catena_Led.h index 14f4341..1118a41 100644 --- a/src/Catena_Led.h +++ b/src/Catena_Led.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation December 2016 @@ -82,10 +82,10 @@ class StatusLed : public cPollableObject m_StartTime = millis(); m_Pattern = LedPattern::Off; } - - virtual void poll(void) override + + virtual void poll(void) override { - this->loop(); + this->loop(); } void loop(void) diff --git a/src/Catena_PersistentStorage.h b/src/Catena_PersistentStorage.h index 21eaac2..ab53928 100644 --- a/src/Catena_PersistentStorage.h +++ b/src/Catena_PersistentStorage.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/Catena_PollableInterface.h b/src/Catena_PollableInterface.h index 31f36d5..0e6521c 100644 --- a/src/Catena_PollableInterface.h +++ b/src/Catena_PollableInterface.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/Catena_Si1133.h b/src/Catena_Si1133.h index b53e4a3..26eeb12 100644 --- a/src/Catena_Si1133.h +++ b/src/Catena_Si1133.h @@ -196,7 +196,7 @@ class Catena_Si1133 static constexpr bool isValid(InputLed_t v) { return (v <= InputLed_t::Disabled) && - ((UINT32_C(1) << uint8_t(v)) & + ((UINT32_C(1) << uint8_t(v)) & ((1u << uint8_t(InputLed_t::SmallIR)) | (1u << uint8_t(InputLed_t::MediumIR)) | (1u << uint8_t(InputLed_t::LargeIR)) | @@ -206,7 +206,7 @@ class Catena_Si1133 (1u << uint8_t(InputLed_t::UVdeep)) | (1u << uint8_t(InputLed_t::Disabled)))); } - + public: Catena_Si1133(void); @@ -269,25 +269,25 @@ class Catena_Si1133 ChannelConfiguration_t& setSwGainCode(uint8_t gc) { return this->setValue(adcsense_sw_gain, gc); } - uint8_t getSwGainCode() { return fieldget(adcsense_sw_gain, this->m_value); } + uint8_t getSwGainCode() { return fieldget(adcsense_sw_gain, this->m_value); } ChannelConfiguration_t& setHwGainCode(uint8_t gc) { return this->setValue(adcsense_hw_gain, gc); } - uint8_t getHwGainCode() { return fieldget(adcsense_hw_gain, this->m_value); } + uint8_t getHwGainCode() { return fieldget(adcsense_hw_gain, this->m_value); } ChannelConfiguration_t& setHsig(bool fHighRange) { return this->setValue(adcsense_hsig, fHighRange); } - bool getHsig() { return fieldget(adcsense_hsig, this->m_value); } + bool getHsig() { return fieldget(adcsense_hsig, this->m_value); } enum class Threshold_t : uint8_t { None = 0, Threshold0, - Threshold1, + Threshold1, Threshold2 }; - + ChannelConfiguration_t& setInterruptThreshold(Threshold_t nBits) { return this->setValue(adcpost_thresh_en, uint8_t(nBits)); } @@ -336,7 +336,7 @@ class Catena_Si1133 /// \param uChannel is the sequence of the measrurement /// in the Si1133 output buffer. /// - /// \param uMode is an index into + /// \param uMode is an index into boolean configure( uint8_t uChannel, uint8_t uMode, diff --git a/src/Catena_functional.h b/src/Catena_functional.h index a2de2c1..cdd42ff 100644 --- a/src/Catena_functional.h +++ b/src/Catena_functional.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 diff --git a/src/McciHwInfo.h b/src/McciHwInfo.h index 9ab2747..2f47e1e 100644 --- a/src/McciHwInfo.h +++ b/src/McciHwInfo.h @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 diff --git a/src/lib/CatenaBase.cpp b/src/lib/CatenaBase.cpp index 9ee065b..c6d201c 100644 --- a/src/lib/CatenaBase.cpp +++ b/src/lib/CatenaBase.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -89,7 +89,7 @@ CatenaBase::registerObject( /* poll all the registered objects */ void CatenaBase::poll() - { + { this->m_PollingEngine.poll(); } diff --git a/src/lib/CatenaBase_GetUniqueIDstring.cpp b/src/lib/CatenaBase_GetUniqueIDstring.cpp index 3ed5e13..fea974b 100644 --- a/src/lib/CatenaBase_GetUniqueIDstring.cpp +++ b/src/lib/CatenaBase_GetUniqueIDstring.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -47,11 +47,11 @@ char *CatenaBase::GetUniqueIDstring( unsigned i; int j; - + for (i = 0, j = 0; i < sizeof(CPUid.b); ++i) { const int nBuf = sizeof(*pStringBuf) - j; - const int jResult = + const int jResult = snprintf( &pStringBuf->c[j], nBuf, diff --git a/src/lib/CatenaBase_NetSave.cpp b/src/lib/CatenaBase_NetSave.cpp index 23a6167..75b6091 100644 --- a/src/lib/CatenaBase_NetSave.cpp +++ b/src/lib/CatenaBase_NetSave.cpp @@ -46,7 +46,7 @@ CatenaBase::NetSaveSessionInfo( ) { auto const pFram = this->getFram(); - + // note that the v1 header and the V2 header are identical in the // bytes belwow. if (pFram != nullptr && (Info.Header.Tag == Arduino_LoRaWAN::kSessionInfoTag_V1 || @@ -78,7 +78,7 @@ CatenaBase::NetSaveSessionState( ) { auto const pFram = this->getFram(); - + // note that the v1 header and the V2 header are identical in the // bytes belwow. if (pFram != nullptr && (State.Header.Tag == Arduino_LoRaWAN::kSessionStateTag_V1)) diff --git a/src/lib/CatenaBase_SafePrintf.cpp b/src/lib/CatenaBase_SafePrintf.cpp index c5ae389..279eae7 100644 --- a/src/lib/CatenaBase_SafePrintf.cpp +++ b/src/lib/CatenaBase_SafePrintf.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -45,7 +45,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -56,7 +56,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -69,7 +69,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. @@ -77,9 +77,9 @@ using namespace McciCatena; \****************************************************************************/ -void +void CatenaBase::SafePrintf( - const char *fmt, + const char *fmt, ... ) { diff --git a/src/lib/Catena_Fram.cpp b/src/lib/Catena_Fram.cpp index e879fb7..e8dcd7a 100644 --- a/src/lib/Catena_Fram.cpp +++ b/src/lib/Catena_Fram.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -90,8 +90,8 @@ McciCatena::cFram::loadCache( cFramStorage::Offset offset; - for (offset = 0; - offset < this->m_endOffset; + for (offset = 0; + offset < this->m_endOffset; offset += object.nextObjectOffset()) { if (! this->read(offset, (uint8_t *)&object, sizeof(object))) @@ -234,7 +234,7 @@ Name: McciCatena::cFram::setCacheEntry() Set the data for a given key. Definition: - protected: void + protected: void McciCatena::cFram::setCacheEntry( cFramStorage::StandardKeys uKey, cFramStorage::Offset offset, @@ -249,7 +249,7 @@ Name: McciCatena::cFram::setCacheEntry() */ -void +void McciCatena::cFram::setCacheEntry( cFramStorage::StandardKeys uKey, cFramStorage::Offset offset, @@ -293,7 +293,7 @@ McciCatena::cFram::isValid() return true; nRead = this->read(0, object.getBuffer(), object.getBufferSize()); - + if (nRead != object.getBufferSize()) { gLog.printf( @@ -302,7 +302,7 @@ McciCatena::cFram::isValid() object.getBufferSize(), nRead ); - + return false; } @@ -351,7 +351,7 @@ McciCatena::cFram::isValid() } // get the end-of-storage pointer - uint32_t offsetOfEndPointer = + uint32_t offsetOfEndPointer = object.offsetOfReplicant( object.getCurrent() ); @@ -377,7 +377,7 @@ McciCatena::cFram::isValid() ); return false; } - + // check that endpointer is valid if (endPointer % cFramStorage::kObjectQuantum != 0 || endPointer < object.getObjectSize()) @@ -458,7 +458,7 @@ McciCatena::cFram::reset() { cFramStorage::Object object; uint32_t endPointer[2]; - + // initialize the object header object.initialize( cFramStorage::skFramGuid, @@ -483,8 +483,8 @@ McciCatena::cFram::reset() // now update the replicant index object.setCurrent(1); this->write( - 0 + object.offsetOfDiscriminator(), - object.getDiscriminatorBuffer(), + 0 + object.offsetOfDiscriminator(), + object.getDiscriminatorBuffer(), object.getDiscriminatorBufferSize() ); @@ -509,7 +509,7 @@ McciCatena::cFram::allocate( return cFramStorage::kInvalidOffset; // round nBytes. - size_t const nAlloc = cFramStorage::getClicks(nBytes) * + size_t const nAlloc = cFramStorage::getClicks(nBytes) * cFramStorage::kObjectQuantum; if (nAlloc < nBytes) @@ -534,7 +534,7 @@ McciCatena::cFram::writeItemData( { const uint8_t uKey = item.getKey(); const cFramStorage::Offset offset = this->m_offsetCache[uKey]; - static const uint8_t uVers[2][3] = + static const uint8_t uVers[2][3] = { { 0, 0, 0 }, { 1, 1, 1 }, @@ -561,7 +561,7 @@ McciCatena::cFram::writeItemData( nBuffer, item.getSize() ); - + return false; } @@ -574,7 +574,7 @@ McciCatena::cFram::writeItemData( pBuffer, nBuffer ); - + bool fResult; const uint8_t newVer = ! this->m_uVerCache[uKey]; @@ -590,7 +590,7 @@ McciCatena::cFram::writeItemData( if (fResult) { gLog.printf( - gLog.kTrace, + gLog.kTrace, "key(0x%x) write new version(%u): base(%u) offset(%u) size(%u)\n", uKey, newVer, @@ -761,7 +761,7 @@ McciCatena::cFram::Cursor::create( // write object and the default value cFramStorage::Offset const objOffset = offset; pFram->write(offset, (uint8_t *) &object, sizeof(object)); - + offset += sizeof(object); for (auto nWrite = object.getObjectSize() - sizeof(object); nWrite > 0; @@ -783,7 +783,7 @@ McciCatena::cFram::Cursor::create( pFram->m_endOffset = offset; pFram->m_offsetCache[this->m_uKey] = objOffset; this->m_offset = objOffset; - return true; + return true; } return false; @@ -797,7 +797,7 @@ Name: McciCatena::cFram::Cursor::locate() Set up a cursor for accessing an item. Definition: - public: bool + public: bool McciCatena::cFram::Cursor::locate( const cFramStorage::StandardItem item ); @@ -812,7 +812,7 @@ Name: McciCatena::cFram::Cursor::locate() */ -bool +bool McciCatena::cFram::Cursor::locate( const cFramStorage::StandardItem item ) @@ -853,9 +853,9 @@ McciCatena::cFram::Cursor::locate( return true; } -bool +bool McciCatena::cFram::Cursor::get( - uint8_t *pBuffer, + uint8_t *pBuffer, size_t nBuffer ) { @@ -981,7 +981,7 @@ static int getbyte(const char * &pValue, const char * &pTerm) return v; } -bool +bool McciCatena::cFram::Cursor::parsevalue( const char *pValue, uint8_t *pData, @@ -1009,7 +1009,7 @@ McciCatena::cFram::Cursor::parsefield( ) { // value is hex, and may have embedded '-' to separate - // bytes. At the end, if it's a number, we have to reverse + // bytes. At the end, if it's a number, we have to reverse // it.... for sanity, start with zeros. As a further // headache, if we have an odd-number of consecutive numeric // nibbles, we need to right justify, not left. @@ -1073,7 +1073,7 @@ McciCatena::cFram::Cursor::parsefield( } -size_t +size_t McciCatena::cFram::Cursor::formatvalue( char *pBuffer, size_t nBuffer, @@ -1082,7 +1082,7 @@ McciCatena::cFram::Cursor::formatvalue( size_t nData ) const { - // data has been fetched, but we need to use the + // data has been fetched, but we need to use the // cursor info to format it. cFramStorage::StandardItem item; @@ -1095,7 +1095,7 @@ McciCatena::cFram::Cursor::formatvalue( return formatfield(pBuffer, nBuffer, iBuffer, pData, nData, item.isNumber()); } -size_t +size_t McciCatena::cFram::Cursor::formatfield( char *pBuffer, size_t nBuffer, diff --git a/src/lib/Catena_Fram2k.cpp b/src/lib/Catena_Fram2k.cpp index 609f2c4..ce1f486 100644 --- a/src/lib/Catena_Fram2k.cpp +++ b/src/lib/Catena_Fram2k.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. @@ -62,7 +62,7 @@ Name: McciCatena::cFram2k::begin() Definition: public: virtual bool McciCatena::cFram2k::begin() - + Description: Initialize an cFram2K object prior to operation. @@ -90,10 +90,10 @@ Name: McciCatena::cFram2K::read() Read a string of bytes from the FRAM Definition: - public: virtual size_t + public: virtual size_t McciCatena::cFram2k::read( - cFramStorage::Offset uOffset, - uint8_t *pBuffer, + cFramStorage::Offset uOffset, + uint8_t *pBuffer, size_t nBuffer ) override; @@ -105,10 +105,10 @@ Name: McciCatena::cFram2K::read() */ -size_t +size_t McciCatena::cFram2k::read( - cFramStorage::Offset uOffset, - uint8_t *pBuffer, + cFramStorage::Offset uOffset, + uint8_t *pBuffer, size_t nBuffer ) { @@ -125,8 +125,8 @@ Name: McciCatena::cFram2K::write() Definition: public: virtual bool McciCatena::cFram2k::write( - cFramStorage::Offset uOffset, - const uint8_t *pBuffer, + cFramStorage::Offset uOffset, + const uint8_t *pBuffer, size_t nBuffer ) override; @@ -138,15 +138,15 @@ Name: McciCatena::cFram2K::write() true for success. Notes: - At the moment, the lower level write can't return failure status, + At the moment, the lower level write can't return failure status, so this routine always returns true. */ bool McciCatena::cFram2k::write( - cFramStorage::Offset uOffset, - const uint8_t *pBuffer, + cFramStorage::Offset uOffset, + const uint8_t *pBuffer, size_t nBuffer ) { diff --git a/src/lib/Catena_Fram8k.cpp b/src/lib/Catena_Fram8k.cpp index 504c45b..93e4811 100644 --- a/src/lib/Catena_Fram8k.cpp +++ b/src/lib/Catena_Fram8k.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. @@ -62,7 +62,7 @@ Name: McciCatena::cFram8k::begin() Definition: public: virtual bool McciCatena::cFram8k::begin() - + Description: Initialize an cFram2K object prior to operation. @@ -90,10 +90,10 @@ Name: McciCatena::cFram2K::read() Read a string of bytes from the FRAM Definition: - public: virtual size_t + public: virtual size_t McciCatena::cFram8k::read( - cFramStorage::Offset uOffset, - uint8_t *pBuffer, + cFramStorage::Offset uOffset, + uint8_t *pBuffer, size_t nBuffer ) override; @@ -105,10 +105,10 @@ Name: McciCatena::cFram2K::read() */ -size_t +size_t McciCatena::cFram8k::read( - cFramStorage::Offset uOffset, - uint8_t *pBuffer, + cFramStorage::Offset uOffset, + uint8_t *pBuffer, size_t nBuffer ) { @@ -125,8 +125,8 @@ Name: McciCatena::cFram2K::write() Definition: public: virtual bool McciCatena::cFram8k::write( - cFramStorage::Offset uOffset, - const uint8_t *pBuffer, + cFramStorage::Offset uOffset, + const uint8_t *pBuffer, size_t nBuffer ) override; @@ -138,15 +138,15 @@ Name: McciCatena::cFram2K::write() true for success. Notes: - At the moment, the lower level write can't return failure status, + At the moment, the lower level write can't return failure status, so this routine always returns true. */ bool McciCatena::cFram8k::write( - cFramStorage::Offset uOffset, - const uint8_t *pBuffer, + cFramStorage::Offset uOffset, + const uint8_t *pBuffer, size_t nBuffer ) { diff --git a/src/lib/Catena_Log.cpp b/src/lib/Catena_Log.cpp index 92263df..c13e6e3 100644 --- a/src/lib/Catena_Log.cpp +++ b/src/lib/Catena_Log.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -42,10 +42,10 @@ using namespace McciCatena; // the global instance cLog McciCatena::gLog; -void +void cLog::printf( DebugFlags uDebugFlags, - const char *fmt, + const char *fmt, ... ) { diff --git a/src/lib/Catena_Mb85rc64ta.cpp b/src/lib/Catena_Mb85rc64ta.cpp index ebaa6e5..c170309 100644 --- a/src/lib/Catena_Mb85rc64ta.cpp +++ b/src/lib/Catena_Mb85rc64ta.cpp @@ -147,7 +147,7 @@ bool Catena_Mb85rc64ta::begin( { break; } - + } if (i == 8) @@ -502,7 +502,7 @@ void Catena_Mb85rc64ta::powerUp( this->m_pWire->beginTransmission(this->m_DeviceAddress); this->m_pWire->endTransmission(false); - + /* tREC == Max 400us */ uSec = micros(); this->m_PowerDown = false; diff --git a/src/lib/samd/CatenaRTC.cpp b/src/lib/samd/CatenaRTC.cpp index 91c40ea..763a087 100644 --- a/src/lib/samd/CatenaRTC.cpp +++ b/src/lib/samd/CatenaRTC.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. @@ -156,7 +156,7 @@ bool CatenaRTC::begin(bool fResetTime) tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2 tmp_reg &= ~RTC_MODE2_CTRL_MATCHCLR; // disable clear on match - + //According to the datasheet RTC_MODE2_CTRL_CLKREP = 0 for 24h tmp_reg &= ~RTC_MODE2_CTRL_CLKREP; // 24h time representation @@ -165,7 +165,7 @@ bool CatenaRTC::begin(bool fResetTime) RTC->MODE2.CTRL.reg = tmp_reg; RtcWaitSynchronize(); - NVIC_EnableIRQ(RTC_IRQn); // enable RTC interrupt + NVIC_EnableIRQ(RTC_IRQn); // enable RTC interrupt NVIC_SetPriority(RTC_IRQn, 0x00); RTC->MODE2.INTENSET.reg |= RTC_MODE2_INTENSET_ALARM0; // enable alarm interrupt @@ -389,7 +389,7 @@ CatenaRTC::CalendarTime::Advance( delta = 86400; result = false; } - + d = delta % 60; delta /= 60; @@ -400,7 +400,7 @@ CatenaRTC::CalendarTime::Advance( Second %= 60; } if (delta == 0) - return result; + return result; d = delta % 60; delta /= 60; diff --git a/src/lib/samd/CatenaSamd21.cpp b/src/lib/samd/CatenaSamd21.cpp index 2a320fd..7738427 100644 --- a/src/lib/samd/CatenaSamd21.cpp +++ b/src/lib/samd/CatenaSamd21.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -41,7 +41,7 @@ using namespace McciCatena; bool CatenaSamd21::cSerialReady::isReady() const { - // unfortunately, we can't use !! Serial (or bool(Serial) -- + // unfortunately, we can't use !! Serial (or bool(Serial) -- // it doesn't really check what we want, and then it inserts // a 10ms delay unconditionally. // so we just check DTR instead. diff --git a/src/lib/samd/CatenaSamd21_begin.cpp b/src/lib/samd/CatenaSamd21_begin.cpp index 63bbcca..8f7175b 100644 --- a/src/lib/samd/CatenaSamd21_begin.cpp +++ b/src/lib/samd/CatenaSamd21_begin.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -51,7 +51,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -62,7 +62,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -75,7 +75,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/samd/CatenaSamd21_registerCommands.cpp b/src/lib/samd/CatenaSamd21_registerCommands.cpp index f2e88f5..4ba0524 100644 --- a/src/lib/samd/CatenaSamd21_registerCommands.cpp +++ b/src/lib/samd/CatenaSamd21_registerCommands.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -58,7 +58,7 @@ static const cCommandStream::cEntry sDefaultEntries[] = { "cpuid", doCpuid }, }; -static cCommandStream::cDispatch +static cCommandStream::cDispatch sDispatch(sDefaultEntries, sizeof(sDefaultEntries)); /****************************************************************************\ diff --git a/src/lib/samd/catena4410/Catena4410.cpp b/src/lib/samd/catena4410/Catena4410.cpp index b588b96..d667abe 100644 --- a/src/lib/samd/catena4410/Catena4410.cpp +++ b/src/lib/samd/catena4410/Catena4410.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -42,7 +42,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -53,7 +53,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -66,7 +66,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/samd/catena4410/Catena4410_getCpuIdPlatformTable.cpp b/src/lib/samd/catena4410/Catena4410_getCpuIdPlatformTable.cpp index 5846588..ec8ca71 100644 --- a/src/lib/samd/catena4410/Catena4410_getCpuIdPlatformTable.cpp +++ b/src/lib/samd/catena4410/Catena4410_getCpuIdPlatformTable.cpp @@ -44,7 +44,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -55,26 +55,26 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ /* -function _cpuid { - echo "$1" | - sed -e 's/^/0x/' -e 's/-/, 0x/g' | - awk '{ - $1 = " { CpuID: { " $1; - $8 = $8 "\n\t\t "; - $16 = $16 " },"; - print }' ; +function _cpuid { + echo "$1" | + sed -e 's/^/0x/' -e 's/-/, 0x/g' | + awk '{ + $1 = " { CpuID: { " $1; + $8 = $8 "\n\t\t "; + $16 = $16 " },"; + print }' ; } */ const CatenaBase::CPUID_PLATFORM_MAP Catena4410::vCpuIdToPlatform[] = { - { CpuID: { 0x08, 0x3b, 0xaf, 0x31, 0x35, 0x50, 0x4d, 0x51, + { CpuID: { 0x08, 0x3b, 0xaf, 0x31, 0x35, 0x50, 0x4d, 0x51, 0x20, 0x20, 0x20, 0x33, 0x1b, 0x1f, 0x11, 0xff }, pPlatform: &gkPlatformCatena4410_pond, SysEUI: { 0x00, 0x02, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x00 }, @@ -82,7 +82,7 @@ const CatenaBase::CPUID_PLATFORM_MAP Catena4410::vCpuIdToPlatform[] = OperatingFlagsSet: fUnattended, }, - { CpuID: { 0xea, 0xa3, 0x7e, 0x87, 0x35, 0x50, 0x4d, 0x51, + { CpuID: { 0xea, 0xa3, 0x7e, 0x87, 0x35, 0x50, 0x4d, 0x51, 0x20, 0x20, 0x20, 0x33, 0x3d, 0x21, 0x13, 0xff }, pPlatform: &gkPlatformCatena4410_anatolian, SysEUI: { 0x00, 0x02, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x01 }, @@ -90,7 +90,7 @@ const CatenaBase::CPUID_PLATFORM_MAP Catena4410::vCpuIdToPlatform[] = OperatingFlagsSet: fUnattended, }, - { CpuID: { 0xb0, 0xa9, 0x2f, 0x58, 0x35, 0x50, 0x4d, 0x51, + { CpuID: { 0xb0, 0xa9, 0x2f, 0x58, 0x35, 0x50, 0x4d, 0x51, 0x20, 0x20, 0x20, 0x33, 0x41, 0x23, 0x12, 0xff }, pPlatform: &gkPlatformCatena4410_gh, SysEUI: { 0x00, 0x02, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x02 }, @@ -223,7 +223,7 @@ const size_t Catena4410::nvCpuIdToPlatform = | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. @@ -239,7 +239,7 @@ Name: Catena4410::getCpuIdPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4410::getCpuIdPlatformTable( const CPUID_PLATFORM_MAP * &vCpuIdToPlatform, size_t &nvCpuIdToPlatform diff --git a/src/lib/samd/catena4410/Catena4410_gk_lorawan_keys.cpp b/src/lib/samd/catena4410/Catena4410_gk_lorawan_keys.cpp index c027a42..0ac9643 100644 --- a/src/lib/samd/catena4410/Catena4410_gk_lorawan_keys.cpp +++ b/src/lib/samd/catena4410/Catena4410_gk_lorawan_keys.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + Author: Terry Moore, MCCI Corporation November 2016 diff --git a/src/lib/samd/catena4420/Catena4420.cpp b/src/lib/samd/catena4420/Catena4420.cpp index 48c9b51..ca5d0eb 100644 --- a/src/lib/samd/catena4420/Catena4420.cpp +++ b/src/lib/samd/catena4420/Catena4420.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation December 2016 diff --git a/src/lib/samd/catena4420/Catena4420_getCpuIdPlatformTable.cpp b/src/lib/samd/catena4420/Catena4420_getCpuIdPlatformTable.cpp index 3439cbc..e425f3f 100644 --- a/src/lib/samd/catena4420/Catena4420_getCpuIdPlatformTable.cpp +++ b/src/lib/samd/catena4420/Catena4420_getCpuIdPlatformTable.cpp @@ -44,7 +44,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -55,20 +55,20 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ /* -function _cpuid { - echo "$1" | - sed -e 's/^/0x/' -e 's/-/, 0x/g' | - awk '{ - $1 = " { CpuID: { " $1; - $8 = $8 "\n\t\t "; - $16 = $16 " },"; - print }' ; +function _cpuid { + echo "$1" | + sed -e 's/^/0x/' -e 's/-/, 0x/g' | + awk '{ + $1 = " { CpuID: { " $1; + $8 = $8 "\n\t\t "; + $16 = $16 " },"; + print }' ; } */ @@ -134,7 +134,7 @@ const size_t Catena4420::nvCpuIdToPlatform = | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. @@ -150,7 +150,7 @@ Name: Catena4420::getCpuIdPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4420::getCpuIdPlatformTable( const CPUID_PLATFORM_MAP * &vCpuIdToPlatform, size_t &nvCpuIdToPlatform diff --git a/src/lib/samd/catena4420/Catena4420_gk_lorawan_keys.cpp b/src/lib/samd/catena4420/Catena4420_gk_lorawan_keys.cpp index 199efa5..bf14f07 100644 --- a/src/lib/samd/catena4420/Catena4420_gk_lorawan_keys.cpp +++ b/src/lib/samd/catena4420/Catena4420_gk_lorawan_keys.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + Author: Terry Moore, MCCI Corporation December 2016 diff --git a/src/lib/samd/catena4450/Catena4450_getCpuIdPlatformTable.cpp b/src/lib/samd/catena4450/Catena4450_getCpuIdPlatformTable.cpp index 6c3639a..bd0ae1c 100644 --- a/src/lib/samd/catena4450/Catena4450_getCpuIdPlatformTable.cpp +++ b/src/lib/samd/catena4450/Catena4450_getCpuIdPlatformTable.cpp @@ -44,7 +44,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -55,20 +55,20 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ /* -function _cpuid { - echo "$1" | - sed -e 's/^/0x/' -e 's/-/, 0x/g' | - awk '{ - $1 = " { CpuID: { " $1; - $8 = $8 "\n\t\t "; - $16 = $16 " },"; - print }' ; +function _cpuid { + echo "$1" | + sed -e 's/^/0x/' -e 's/-/, 0x/g' | + awk '{ + $1 = " { CpuID: { " $1; + $8 = $8 "\n\t\t "; + $16 = $16 " },"; + print }' ; } */ @@ -183,7 +183,7 @@ const size_t Catena4450::nvCpuIdToPlatform = | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. @@ -199,7 +199,7 @@ Name: Catena4450::getCpuIdPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4450::getCpuIdPlatformTable( const CPUID_PLATFORM_MAP * &vCpuIdToPlatform, size_t &nvCpuIdToPlatform diff --git a/src/lib/samd/catena4450/Catena4450_getPlatformTable.cpp b/src/lib/samd/catena4450/Catena4450_getPlatformTable.cpp index 1f584ec..0ffbe83 100644 --- a/src/lib/samd/catena4450/Catena4450_getPlatformTable.cpp +++ b/src/lib/samd/catena4450/Catena4450_getPlatformTable.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation April 2017 @@ -60,7 +60,7 @@ Name: Catena4450::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4450::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/samd/catena4460/Catena4460_getPlatformTable.cpp b/src/lib/samd/catena4460/Catena4460_getPlatformTable.cpp index 3d76304..732744f 100644 --- a/src/lib/samd/catena4460/Catena4460_getPlatformTable.cpp +++ b/src/lib/samd/catena4460/Catena4460_getPlatformTable.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation April 2017 @@ -60,7 +60,7 @@ Name: Catena4460::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4460::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/samd/catena4470/Catena4470_getPlatformTable.cpp b/src/lib/samd/catena4470/Catena4470_getPlatformTable.cpp index b686b80..fd718be 100644 --- a/src/lib/samd/catena4470/Catena4470_getPlatformTable.cpp +++ b/src/lib/samd/catena4470/Catena4470_getPlatformTable.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation April 2017 @@ -57,7 +57,7 @@ Name: Catena4470::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4470::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/samd/catenasamd21_getuniqueid.cpp b/src/lib/samd/catenasamd21_getuniqueid.cpp index ea65e62..38811b4 100644 --- a/src/lib/samd/catenasamd21_getuniqueid.cpp +++ b/src/lib/samd/catenasamd21_getuniqueid.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -40,7 +40,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -51,7 +51,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -64,7 +64,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/samd/catenasamd_gk_plaformhierarchy.cpp b/src/lib/samd/catenasamd_gk_plaformhierarchy.cpp index e3a723f..1f252d5 100644 --- a/src/lib/samd/catenasamd_gk_plaformhierarchy.cpp +++ b/src/lib/samd/catenasamd_gk_plaformhierarchy.cpp @@ -21,7 +21,7 @@ Copyright notice: This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -53,7 +53,7 @@ namespace McciCatena { | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -64,7 +64,7 @@ namespace McciCatena { | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -373,7 +373,7 @@ const CATENA_PLATFORM gkPlatformCatena4470_m101 = | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_begin.cpp b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_begin.cpp index 49650e6..f1cbe48 100644 --- a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_begin.cpp +++ b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_begin.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -66,7 +66,7 @@ Name: CatenaWingFram2k::LoRaWAN::begin() */ -bool +bool CatenaWingFram2k::LoRaWAN::begin( CatenaWingFram2k *pParent ) diff --git a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp index bad3bf4..c6e35b1 100644 --- a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp +++ b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_LoRaWAN_storage.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -132,10 +132,10 @@ CatenaWingFram2k::LoRaWAN::GetProvisioningStyle( return pCatena->GetProvisioningStyle(); } -void +void CatenaWingFram2k::LoRaWAN::NetSaveSessionInfo( - const SessionInfo &Info, - const uint8_t *pExtraInfo, + const SessionInfo &Info, + const uint8_t *pExtraInfo, size_t nExtraInfo ) { diff --git a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_ReadVbat.cpp b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_ReadVbat.cpp index 38583ee..8ef0be9 100644 --- a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_ReadVbat.cpp +++ b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_ReadVbat.cpp @@ -39,7 +39,7 @@ Revision history: using namespace McciCatena; -float +float CatenaWingFram2k::ReadVbat(void) const { float rawVoltage = analogRead(CatenaWingFram2k::APIN_VBAT_SENSE); diff --git a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_begin.cpp b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_begin.cpp index 1e1ab8e..68525b2 100644 --- a/src/lib/samd/catenawingfram2k/CatenaWingFram2k_begin.cpp +++ b/src/lib/samd/catenawingfram2k/CatenaWingFram2k_begin.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation March 2017 @@ -66,7 +66,7 @@ bool CatenaWingFram2k::begin() delay(2000); gLog.printf(gLog.kTrace, "+CatenaWingFram2k::begin()\n"); - // we must initialize the FRAM before we call our parent, + // we must initialize the FRAM before we call our parent, // because FRAM is used for stable storage of platform info. // start the FRAM @@ -77,7 +77,7 @@ bool CatenaWingFram2k::begin() if (! this->m_Fram.isValid()) { gLog.printf( - gLog.kError, + gLog.kError, "FRAM contents are not valid, resetting\n" ); this->m_Fram.initialize(); @@ -87,7 +87,7 @@ bool CatenaWingFram2k::begin() if (! this->Super::begin()) { gLog.printf( - gLog.kError, + gLog.kError, "?CatenaWingFram2k::begin:" " Super::begin() failed\n" ); @@ -101,7 +101,7 @@ bool CatenaWingFram2k::begin() if (!this->m_Fram.addCommands()) { gLog.printf( - gLog.kError, + gLog.kError, "?CatenaWingFram2k::begin:" " m_Fram.addCommands() failed\n" ); diff --git a/src/lib/samd/featherm0/catenafeatherm0_begin.cpp b/src/lib/samd/featherm0/catenafeatherm0_begin.cpp index 8201d16..224a4f3 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_begin.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_begin.cpp @@ -66,7 +66,7 @@ bool CatenaFeatherM0::begin() if (! this->Super::begin()) { gLog.printf( - gLog.kError, + gLog.kError, "?CatenaFeatherM0::begin:" " Super::begin() failed\n" ); diff --git a/src/lib/samd/featherm0/catenafeatherm0_getprovisioninginfo.cpp b/src/lib/samd/featherm0/catenafeatherm0_getprovisioninginfo.cpp index ef059c3..5466d9f 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_getprovisioninginfo.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_getprovisioninginfo.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation November 2016 @@ -74,8 +74,8 @@ CatenaFeatherM0::GetProvisioningInfo( for (i = pTable->nInfo, pInfo = pTable->pInfo; i > 0; ++pInfo, --i) { - /* - || even for ABP, we use the DevEUI to match up -- but it's + /* + || even for ABP, we use the DevEUI to match up -- but it's || reversed. All Catenas have DevEUIs, so this is really not || a sacrifice. */ @@ -83,9 +83,9 @@ CatenaFeatherM0::GetProvisioningInfo( const uint8_t *q; unsigned j; - for (j = sizeof(*pSysEUI), - p = &pSysEUI->b[0], q = &pInfo->OtaaInfo.DevEUI[j - 1]; - j > 0; + for (j = sizeof(*pSysEUI), + p = &pSysEUI->b[0], q = &pInfo->OtaaInfo.DevEUI[j - 1]; + j > 0; --j, ++p, --q ) { diff --git a/src/lib/samd/featherm0/catenafeatherm0_lorawan_begin.cpp b/src/lib/samd/featherm0/catenafeatherm0_lorawan_begin.cpp index 58acc5a..34a4500 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_lorawan_begin.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_lorawan_begin.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -49,7 +49,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -60,7 +60,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -72,7 +72,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getabpprovisioninginfo.cpp b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getabpprovisioninginfo.cpp index 47637c8..b7345e6 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getabpprovisioninginfo.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getabpprovisioninginfo.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -75,7 +75,7 @@ CatenaFeatherM0::LoRaWAN::GetAbpProvisioningInfo( __func__ ); - if (! pInstance || + if (! pInstance || pInstance->Style != ProvisioningStyle::kABP) { if (pInfo) @@ -83,10 +83,10 @@ CatenaFeatherM0::LoRaWAN::GetAbpProvisioningInfo( // ensure consistent behavior memset(pInfo, 0, sizeof(*pInfo)); } - + return false; } - + // got instance data if (pInfo) { diff --git a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getotaaprovisioninginfo.cpp b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getotaaprovisioninginfo.cpp index c51019f..9080705 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getotaaprovisioninginfo.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getotaaprovisioninginfo.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -68,7 +68,7 @@ CatenaFeatherM0::LoRaWAN::GetOtaaProvisioningInfo( CatenaFeatherM0 * const pCatena = this->m_pCatena; const ProvisioningInfo * const pInstance = pCatena->GetProvisioningInfo(); - if (! pInstance || + if (! pInstance || pInstance->Style != ProvisioningStyle::kOTAA) { if (pInfo) @@ -76,10 +76,10 @@ CatenaFeatherM0::LoRaWAN::GetOtaaProvisioningInfo( // ensure consistent behavior memset(pInfo, 0, sizeof(*pInfo)); } - + return false; } - + // got instance data if (pInfo) { diff --git a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getprovisioningstyle.cpp b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getprovisioningstyle.cpp index be53891..1ed616c 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_lorawan_getprovisioningstyle.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_lorawan_getprovisioningstyle.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 diff --git a/src/lib/samd/featherm0/catenafeatherm0_readvbat.cpp b/src/lib/samd/featherm0/catenafeatherm0_readvbat.cpp index 815a283..3ceea90 100644 --- a/src/lib/samd/featherm0/catenafeatherm0_readvbat.cpp +++ b/src/lib/samd/featherm0/catenafeatherm0_readvbat.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -42,7 +42,7 @@ Revision history: using namespace McciCatena; -float +float CatenaFeatherM0::ReadVbat(void) const { float rawVoltage = analogRead(CatenaFeatherM0::APIN_VBAT_SENSE); diff --git a/src/lib/stm32/CatenaStm32_GetUniqueID.cpp b/src/lib/stm32/CatenaStm32_GetUniqueID.cpp index f9f7f1d..c7c78e8 100644 --- a/src/lib/stm32/CatenaStm32_GetUniqueID.cpp +++ b/src/lib/stm32/CatenaStm32_GetUniqueID.cpp @@ -18,10 +18,10 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. - + Author: Terry Moore, MCCI Corporation October 2016 @@ -41,7 +41,7 @@ using namespace McciCatena; | | Manifest constants & typedefs. | -| This is strictly for private types and constants which will not +| This is strictly for private types and constants which will not | be exported. | \****************************************************************************/ @@ -52,7 +52,7 @@ using namespace McciCatena; | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only +| If program is to be ROM-able, these must all be tagged read-only | using the ROM storage class; they may be global. | \****************************************************************************/ @@ -65,7 +65,7 @@ using namespace McciCatena; | | If program is to be ROM-able, these must be initialized | using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those +| every variable to have an initializer.) Note that only those | variables owned by this module should be declared here, using the BSS | keyword; this allows for linkers that dislike multiple declarations | of objects. diff --git a/src/lib/stm32/CatenaStm32_registerCommands.cpp b/src/lib/stm32/CatenaStm32_registerCommands.cpp index b205d7f..22084e0 100644 --- a/src/lib/stm32/CatenaStm32_registerCommands.cpp +++ b/src/lib/stm32/CatenaStm32_registerCommands.cpp @@ -18,7 +18,7 @@ Copyright notice: Ithaca, NY 14850 An unpublished work. All rights reserved. - + This file is proprietary information, and may not be disclosed or copied without the prior permission of MCCI Corporation. @@ -58,7 +58,7 @@ static const cCommandStream::cEntry sDefaultEntries[] = { "cpuid", doCpuid }, }; -static cCommandStream::cDispatch +static cCommandStream::cDispatch sDispatch(sDefaultEntries, sizeof(sDefaultEntries)); /****************************************************************************\ diff --git a/src/lib/stm32/catena455x/Catena4551_getPlatformTable.cpp b/src/lib/stm32/catena455x/Catena4551_getPlatformTable.cpp index 5414342..8de57cb 100644 --- a/src/lib/stm32/catena455x/Catena4551_getPlatformTable.cpp +++ b/src/lib/stm32/catena455x/Catena4551_getPlatformTable.cpp @@ -134,7 +134,7 @@ Name: Catena4551::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4551::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/catena461x/Catena4610_getPlatformTable.cpp b/src/lib/stm32/catena461x/Catena4610_getPlatformTable.cpp index 2a4038e..dbaf7ba 100644 --- a/src/lib/stm32/catena461x/Catena4610_getPlatformTable.cpp +++ b/src/lib/stm32/catena461x/Catena4610_getPlatformTable.cpp @@ -134,7 +134,7 @@ Name: Catena4610::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4610::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/catena461x/Catena4611_getPlatformTable.cpp b/src/lib/stm32/catena461x/Catena4611_getPlatformTable.cpp index 810009f..63e2723 100644 --- a/src/lib/stm32/catena461x/Catena4611_getPlatformTable.cpp +++ b/src/lib/stm32/catena461x/Catena4611_getPlatformTable.cpp @@ -134,7 +134,7 @@ Name: Catena4611::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4611::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/catena461x/Catena4612_getPlatformTable.cpp b/src/lib/stm32/catena461x/Catena4612_getPlatformTable.cpp index 7431e99..230a0bd 100644 --- a/src/lib/stm32/catena461x/Catena4612_getPlatformTable.cpp +++ b/src/lib/stm32/catena461x/Catena4612_getPlatformTable.cpp @@ -134,7 +134,7 @@ Name: Catena4612::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4612::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/catena480x/Catena4801_getPlatformTable.cpp b/src/lib/stm32/catena480x/Catena4801_getPlatformTable.cpp index 868e6e6..cc19973 100644 --- a/src/lib/stm32/catena480x/Catena4801_getPlatformTable.cpp +++ b/src/lib/stm32/catena480x/Catena4801_getPlatformTable.cpp @@ -69,7 +69,7 @@ Name: Catena4801::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4801::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/catena480x/Catena4802_getPlatformTable.cpp b/src/lib/stm32/catena480x/Catena4802_getPlatformTable.cpp index f41a18b..2508739 100644 --- a/src/lib/stm32/catena480x/Catena4802_getPlatformTable.cpp +++ b/src/lib/stm32/catena480x/Catena4802_getPlatformTable.cpp @@ -53,7 +53,7 @@ Name: Catena4802::getPlatformTable() Get the known platform table. Definition: - public: virtual + public: virtual void Catena4802::getPlatformTable( const CATENA_PLATFORM * const * &vPlatforms, size_t &nvPlatforms diff --git a/src/lib/stm32/stm32l0/CatenaStm32L0_ReadAnalog.cpp b/src/lib/stm32/stm32l0/CatenaStm32L0_ReadAnalog.cpp index 337b509..9ac0ea3 100644 --- a/src/lib/stm32/stm32l0/CatenaStm32L0_ReadAnalog.cpp +++ b/src/lib/stm32/stm32l0/CatenaStm32L0_ReadAnalog.cpp @@ -221,7 +221,7 @@ bool McciCatena::CatenaStm32L0_ReadAnalog( vRefInt_cal = (*pVrefintCal * 3000 + 1) / (4096 / 4); vResult = vChannel * Multiplier; - + vResult = vResult * vRefInt_cal / vRef; // remove the factor of 4, and round *pValue = (vResult + 2) >> 2; From 63057715727d82eaee3ab3e38c7cef4cdc6be4d5 Mon Sep 17 00:00:00 2001 From: dhineshkumarmcci Date: Sat, 3 Apr 2021 23:11:36 +0530 Subject: [PATCH 07/28] Fix #288: disable 24-bit mode in Si1133 driver --- src/lib/Catena_Si1133.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Catena_Si1133.cpp b/src/lib/Catena_Si1133.cpp index 88e0bf1..1c94d35 100644 --- a/src/lib/Catena_Si1133.cpp +++ b/src/lib/Catena_Si1133.cpp @@ -87,7 +87,7 @@ static const Catena_Si1133::ChannelConfiguration_t sk_Config[] = .setSwGainCode(7) .setHwGainCode(4) .setPostShift(1) - .set24bit(1) + .set24bit(0) .setCounter(Catena_Si1133::ChannelConfiguration_t::CounterSelect_t::MeasCount2), Catena_Si1133::ChannelConfiguration_t() .setAdcMux(Catena_Si1133::InputLed_t::UV) From 8f872214a4a946cebc454910c65886a5b63a9a1b Mon Sep 17 00:00:00 2001 From: dhineshkumarmcci Date: Sat, 3 Apr 2021 23:39:45 +0530 Subject: [PATCH 08/28] Fix #288: set swgain and hwgain to 0 by default --- src/lib/Catena_Si1133.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Catena_Si1133.cpp b/src/lib/Catena_Si1133.cpp index 1c94d35..4745a17 100644 --- a/src/lib/Catena_Si1133.cpp +++ b/src/lib/Catena_Si1133.cpp @@ -84,8 +84,8 @@ static const Catena_Si1133::ChannelConfiguration_t sk_Config[] = .setCounter(Catena_Si1133::ChannelConfiguration_t::CounterSelect_t::MeasCount2), Catena_Si1133::ChannelConfiguration_t() .setAdcMux(Catena_Si1133::InputLed_t::LargeWhite) - .setSwGainCode(7) - .setHwGainCode(4) + .setSwGainCode(0) + .setHwGainCode(0) .setPostShift(1) .set24bit(0) .setCounter(Catena_Si1133::ChannelConfiguration_t::CounterSelect_t::MeasCount2), From 379ff93adf882a536816e78138392b279ac4de4d Mon Sep 17 00:00:00 2001 From: dhineshkumarmcci Date: Mon, 5 Apr 2021 16:40:59 +0530 Subject: [PATCH 09/28] Fix #288: set decimation rate to 1 --- src/lib/Catena_Si1133.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/Catena_Si1133.cpp b/src/lib/Catena_Si1133.cpp index 4745a17..9120b45 100644 --- a/src/lib/Catena_Si1133.cpp +++ b/src/lib/Catena_Si1133.cpp @@ -84,6 +84,8 @@ static const Catena_Si1133::ChannelConfiguration_t sk_Config[] = .setCounter(Catena_Si1133::ChannelConfiguration_t::CounterSelect_t::MeasCount2), Catena_Si1133::ChannelConfiguration_t() .setAdcMux(Catena_Si1133::InputLed_t::LargeWhite) + .setDecimationRateCode(1) + .setHsig(false) .setSwGainCode(0) .setHwGainCode(0) .setPostShift(1) From 388c12c48ce13fc917deeff792a3297a7b50836a Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 5 Apr 2021 22:41:39 +0200 Subject: [PATCH 10/28] Step pre-release 0.21.0-3: light sensor changes --- src/CatenaBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index 56b4564..8a16b53 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -57,7 +57,7 @@ Copyright notice: (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) #define CATENA_ARDUINO_PLATFORM_VERSION \ - CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 2) /* v0.21.0-2 */ + CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 3) /* v0.21.0-3 */ #define CATENA_ARDUINO_PLATFORM_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From 09b4d50a62f32a3ca30fb403a2c799ceab43fc04 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sat, 10 Apr 2021 01:28:54 -0400 Subject: [PATCH 11/28] Step version to 0.9.0-2 --- src/CatenaBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index 56b4564..cffa4bc 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -48,7 +48,7 @@ Copyright notice: #include #if ! (defined(ARDUINO_LORAWAN_VERSION_COMPARE_LT) && \ - ! ARDUINO_LORAWAN_VERSION_COMPARE_LT(ARDUINO_LORAWAN_VERSION, ARDUINO_LORAWAN_VERSION_CALC(0,9,0,1))) + ! ARDUINO_LORAWAN_VERSION_COMPARE_LT(ARDUINO_LORAWAN_VERSION, ARDUINO_LORAWAN_VERSION_CALC(0,9,0,2))) # error Arduino_LoRaWAN library is out of date. Check ARDUINO_LORAWAN_VERSION. #endif From 6e53672a176d32ae7bf1e8464132bf5f7696020f Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sat, 10 Apr 2021 01:27:12 -0400 Subject: [PATCH 12/28] Support semantic versions in Arduino BSP. --- src/CatenaBase.h | 5 +++++ src/lib/CatenaBase_registerCommands.cpp | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index cffa4bc..ad14b8f 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -115,6 +115,11 @@ class CatenaBase static constexpr uint32_t kMcciArduinoVersion = _mcci_arduino_version; #else static constexpr uint32_t kMcciArduinoVersion = 0; +#endif +#if defined(_mcci_arduino_version_is_semantic) + static constexpr bool kMcciArduinoVersionIsSemantic = true; +#else + static constexpr bool kMcciArduinoVersionIsSemantic = false; #endif static constexpr uint32_t versionCalc(uint8_t major, uint8_t minor, uint8_t patch, uint8_t local) { diff --git a/src/lib/CatenaBase_registerCommands.cpp b/src/lib/CatenaBase_registerCommands.cpp index 5f6e05e..227d6a7 100644 --- a/src/lib/CatenaBase_registerCommands.cpp +++ b/src/lib/CatenaBase_registerCommands.cpp @@ -369,7 +369,9 @@ doVersion( /* include the MCCI Arduino version, if known */ if (pCatena->kMcciArduinoVersion != 0) - printVersion(pThis, "MCCI-Arduino-BSP", pCatena->kMcciArduinoVersion); + printVersion(pThis, "MCCI-Arduino-BSP", pCatena->kMcciArduinoVersion, + pCatena->kMcciArduinoVersionIsSemantic + ); return cCommandStream::CommandStatus::kSuccess; } From a68787b5689e6b36328ff3a553b91ada6756d5b3 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sat, 10 Apr 2021 01:36:19 -0400 Subject: [PATCH 13/28] Fix #294: Make flash driver more poll() friendly --- src/Catena_Mx25v8035f.h | 14 +- src/lib/stm32/Catena_Mx25v8035f.cpp | 195 ++++++++++++++++++---------- 2 files changed, 137 insertions(+), 72 deletions(-) diff --git a/src/Catena_Mx25v8035f.h b/src/Catena_Mx25v8035f.h index 43cba5e..a77c0a3 100644 --- a/src/Catena_Mx25v8035f.h +++ b/src/Catena_Mx25v8035f.h @@ -131,7 +131,16 @@ namespace McciCatena { class Catena_Mx25v8035f { public: - Catena_Mx25v8035f(void); + Catena_Mx25v8035f(void) + : m_Initialized(false) + , m_registered(false) + {}; + + // neither copyable nor movable + Catena_Mx25v8035f(const Catena_Mx25v8035f&) = delete; + Catena_Mx25v8035f& operator=(const Catena_Mx25v8035f&) = delete; + Catena_Mx25v8035f(const Catena_Mx25v8035f&&) = delete; + Catena_Mx25v8035f& operator=(const Catena_Mx25v8035f&&) = delete; // set up and probe device boolean begin(SPIClass *pSpi, uint8_t ChipSelectPin = D19); @@ -168,10 +177,13 @@ class Catena_Mx25v8035f private: boolean m_Initialized; boolean m_PowerDown; + boolean m_registered; uint8_t m_CS; SPIClass * m_pSpi; void erase(uint32_t Address, uint8_t Command, uint32_t Delay); + void setWel(void); + void pollWip(uint32_t pollMs); }; } // namespace McciCatena diff --git a/src/lib/stm32/Catena_Mx25v8035f.cpp b/src/lib/stm32/Catena_Mx25v8035f.cpp index 6eabc68..7bd5265 100644 --- a/src/lib/stm32/Catena_Mx25v8035f.cpp +++ b/src/lib/stm32/Catena_Mx25v8035f.cpp @@ -43,56 +43,31 @@ Revision history: #include #include "Catena_Mx25v8035f.h" +#include "CatenaBase.h" using namespace McciCatena; /****************************************************************************\ | -| Manifest constants & typedefs. -| -| This is strictly for private types and constants which will not -| be exported. +| Manifest constants & typedefs. | \****************************************************************************/ - +static void flashDelay(uint32_t howLong); /****************************************************************************\ | | Read-only data. | -| If program is to be ROM-able, these must all be tagged read-only -| using the ROM storage class; they may be global. -| \****************************************************************************/ - /****************************************************************************\ | -| VARIABLES: -| -| If program is to be ROM-able, these must be initialized -| using the BSS keyword. (This allows for compilers that require -| every variable to have an initializer.) Note that only those -| variables owned by this module should be declared here, using the BSS -| keyword; this allows for linkers that dislike multiple declarations -| of objects. +| Variables. | \****************************************************************************/ -/* -|| Constructors -*/ - -Catena_Mx25v8035f::Catena_Mx25v8035f(void) - { - this->m_Initialized = false; - } - -/* -|| Public functions -*/ - + /* Name: Catena_Mx25v8035f::begin @@ -155,6 +130,7 @@ boolean Catena_Mx25v8035f::begin( /* Everything seems to be properly initialised and connected */ this->m_Initialized = true; + /* we're not registering as a pollable object yet, so don't set m_Registered */ return true; } @@ -187,7 +163,76 @@ void Catena_Mx25v8035f::end( pinMode(this->m_CS, INPUT); digitalWrite(this->m_CS, 0); } + +/* + +Name: flashDelay() + +Function: + Delay, driving the poll loop. + +Definition: + void flashDelay( + uint32_t howLong + ); + +Description: + The current thread is delayed for `howLong` milliseconds. + After each time the clock is checked, gpCatenaBase->poll() is + called to ensure that other activities have a chance to + run. +Returns: + No explicit result. + +*/ + +static void flashDelay(uint32_t howLong) + { + auto const tNow = millis(); + + while (millis() - tNow < howLong) + { + gpCatenaBase->poll(); + } + } + +/* + +Name: Catena_Mx25v8035f::setWel + +Function: + Set WEL in flash chip. + +Definition: + void Catena_Mx25v8035f::setWel( + void + ); + +Description: + This function sets the WEL latch in the MX25V8035F chip. + +Returns: + No explicit result. + +*/ + +void Catena_Mx25v8035f::setWel(void) + { + uint8_t status[2]; + auto const pSpi = this->m_pSpi; + + while (true) + { + pSpi->transfer(this->m_CS, MX25V8035F_CMD_WREN); + status[0] = MX25V8035F_CMD_RDSR; + pSpi->transfer(this->m_CS, status, sizeof(status)); + if ((status[1] & MX25V8035F_STS_WEL) != 0) + break; + gpCatenaBase->poll(); + } + } + /* Name: Catena_Mx25v8035f::reset @@ -216,7 +261,9 @@ void Catena_Mx25v8035f::reset( pSpi->transfer(this->m_CS, MX25V8035F_CMD_RSTEN, SPI_LAST); pSpi->transfer(this->m_CS, MX25V8035F_CMD_RST, SPI_LAST); - delay(100); /* Reset recovery time: Chip Erase operation = 100ms */ + + /* Reset recovery time: Chip Erase operation = 100ms */ + flashDelay(100); } /* @@ -284,16 +331,46 @@ void Catena_Mx25v8035f::eraseChip( SPIClass * const pSpi = this->m_pSpi; uint8_t status[2]; - do { - pSpi->transfer(this->m_CS, MX25V8035F_CMD_WREN); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while ((status[1] & MX25V8035F_STS_WEL) == 0); - + this->setWel(); pSpi->transfer(this->m_CS, MX25V8035F_CMD_CE); + this->pollWip(100); + } + +/* + +Name: Catena_Mx25v8035f::pollWip() + +Function: + Loop waiting for the WIP bit to go clear, with controlled poll interval + +Definition: + void Catena_Mx25v8035f::pollWip( + uint32_t tPollMs + ); + +Description: + Periodically read the status register and check the WIP bit. + Return as soon as it is observed to be clear. tPollMs sets the + interval between polls, in milliseconds. + +Returns: + No explicit result. + +Notes: + There's no timeout; if WIP never clears, this will hang forever. + +*/ + +void Catena_Mx25v8035f::pollWip( + uint32_t tPollMs + ) + { + uint8_t status[2]; + auto const pSpi = this->m_pSpi; + do { - delay(500); + flashDelay(tPollMs); status[0] = MX25V8035F_CMD_RDSR; pSpi->transfer(this->m_CS, status, sizeof(status)); } while (status[1] & MX25V8035F_STS_WIP); @@ -336,19 +413,11 @@ void Catena_Mx25v8035f::erase( data[2] = (Address >> 8) & 0xFF; data[3] = Address & 0xFF; - do { - pSpi->transfer(this->m_CS, MX25V8035F_CMD_WREN); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while ((status[1] & MX25V8035F_STS_WEL) == 0); + this->setWel(); pSpi->transfer(this->m_CS, data, sizeof(data)); - do { - delay(Delay); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while (status[1] & MX25V8035F_STS_WIP); + this->pollWip(Delay); } /* @@ -375,7 +444,7 @@ void Catena_Mx25v8035f::eraseSector( uint32_t SectorAddress ) { - this->erase(SectorAddress, MX25V8035F_CMD_SE, 20); + this->erase(SectorAddress, MX25V8035F_CMD_SE, 20 /*ms*/); } /* @@ -402,7 +471,7 @@ void Catena_Mx25v8035f::eraseBlock32( uint32_t Block32Address ) { - this->erase(Block32Address, MX25V8035F_CMD_BE_32K, 100); + this->erase(Block32Address, MX25V8035F_CMD_BE_32K, 100 /*ms*/); } /* @@ -429,7 +498,7 @@ void Catena_Mx25v8035f::eraseBlock64( uint32_t Block64Address ) { - this->erase(Block64Address, MX25V8035F_CMD_BE, 200); + this->erase(Block64Address, MX25V8035F_CMD_BE, 200 /*ms*/); } /* @@ -467,19 +536,11 @@ void Catena_Mx25v8035f::setProtection( else data[2] = 0; - do { - pSpi->transfer(this->m_CS, MX25V8035F_CMD_WREN); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while ((status[1] & MX25V8035F_STS_WEL) == 0); + this->setWel(); pSpi->transfer(this->m_CS, data, sizeof(data)); - do { - delay(1); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while (status[1] & MX25V8035F_STS_WIP); + this->pollWip(1 /*ms*/); } /* @@ -564,20 +625,12 @@ size_t Catena_Mx25v8035f::programPage( if (programSize > nBuffer) programSize = nBuffer; - do { - pSpi->transfer(this->m_CS, MX25V8035F_CMD_WREN); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while ((status[1] & MX25V8035F_STS_WEL) == 0); + this->setWel(); pSpi->transfer(this->m_CS, data, sizeof(data), SPI_CONTINUE); pSpi->transfer(this->m_CS, pBuffer, programSize, SPI_LAST); - do { - delay(1); - status[0] = MX25V8035F_CMD_RDSR; - pSpi->transfer(this->m_CS, status, sizeof(status)); - } while (status[1] & MX25V8035F_STS_WIP); + this->pollWip(1 /* ms */); return programSize; } From 87ad3eceb5a85b1107cb32cd8db27060212bc050 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sat, 10 Apr 2021 01:38:57 -0400 Subject: [PATCH 14/28] Fix #293: don't clobber user's write buffer in catena_Mx25v8035f::programPage() --- src/Catena_Mx25v8035f.h | 4 ++-- src/lib/stm32/Catena_Mx25v8035f.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Catena_Mx25v8035f.h b/src/Catena_Mx25v8035f.h index a77c0a3..45f5654 100644 --- a/src/Catena_Mx25v8035f.h +++ b/src/Catena_Mx25v8035f.h @@ -167,8 +167,8 @@ class Catena_Mx25v8035f void read(uint32_t Address, uint8_t *pBuffer, size_t nBuffer); // program a buffer - void program(uint32_t Address, uint8_t *pBuffer, size_t nBuffer); - size_t programPage(uint32_t Address, uint8_t *pBuffer, size_t nBuffer); + void program(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer); + size_t programPage(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer); // power management void powerDown(void); diff --git a/src/lib/stm32/Catena_Mx25v8035f.cpp b/src/lib/stm32/Catena_Mx25v8035f.cpp index 7bd5265..f5a7cf6 100644 --- a/src/lib/stm32/Catena_Mx25v8035f.cpp +++ b/src/lib/stm32/Catena_Mx25v8035f.cpp @@ -607,13 +607,13 @@ Name: Catena_Mx25v8035f::programPage size_t Catena_Mx25v8035f::programPage( uint32_t Address, - uint8_t *pBuffer, + const uint8_t *pBuffer, size_t nBuffer ) { SPIClass * const pSpi = this->m_pSpi; uint8_t status[2]; - uint8_t data[4]; + uint8_t data[MX25V8035F_PAGE_SIZE]; size_t programSize; data[0] = MX25V8035F_CMD_PP; @@ -628,7 +628,8 @@ size_t Catena_Mx25v8035f::programPage( this->setWel(); pSpi->transfer(this->m_CS, data, sizeof(data), SPI_CONTINUE); - pSpi->transfer(this->m_CS, pBuffer, programSize, SPI_LAST); + memcpy(data, pBuffer, programSize); + pSpi->transfer(this->m_CS, data, programSize, SPI_LAST); this->pollWip(1 /* ms */); @@ -645,7 +646,7 @@ Name: Catena_Mx25v8035f::program Definition: void Catena_Mx25v8035f::program( uint32_t Address, - uint8_t *pBuffer, + const uint8_t *pBuffer, size_t nBuffer ); @@ -659,7 +660,7 @@ Name: Catena_Mx25v8035f::program void Catena_Mx25v8035f::program( uint32_t Address, - uint8_t *pBuffer, + const uint8_t *pBuffer, size_t nBuffer ) { From 35de33cbb57fde5e3d939a811e2f26fc6d82606e Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 12 Apr 2021 02:54:29 -0400 Subject: [PATCH 15/28] Remove gpCatenaBase in favor of CatenaBase::pCatenaBase --- src/CatenaBase.h | 3 --- src/lib/stm32/Catena_Mx25v8035f.cpp | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index e2cda81..e0f6b84 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -599,9 +599,6 @@ Index: Function: CatenaBase::PlatformFlags_IsModded(); */ // actual function is above. -// global for finding the base from anywhere. -extern CatenaBase *gpCatenaBase; - }; // end namespace McciCatena diff --git a/src/lib/stm32/Catena_Mx25v8035f.cpp b/src/lib/stm32/Catena_Mx25v8035f.cpp index f5a7cf6..9c6adf8 100644 --- a/src/lib/stm32/Catena_Mx25v8035f.cpp +++ b/src/lib/stm32/Catena_Mx25v8035f.cpp @@ -178,7 +178,7 @@ Name: flashDelay() Description: The current thread is delayed for `howLong` milliseconds. - After each time the clock is checked, gpCatenaBase->poll() is + After each time the clock is checked, CatenaBase::pCatenaBase->poll() is called to ensure that other activities have a chance to run. @@ -193,7 +193,7 @@ static void flashDelay(uint32_t howLong) while (millis() - tNow < howLong) { - gpCatenaBase->poll(); + CatenaBase::pCatenaBase->poll(); } } @@ -229,7 +229,7 @@ void Catena_Mx25v8035f::setWel(void) pSpi->transfer(this->m_CS, status, sizeof(status)); if ((status[1] & MX25V8035F_STS_WEL) != 0) break; - gpCatenaBase->poll(); + CatenaBase::pCatenaBase->poll(); } } From ab2704b4c29bb7fabad333d0892fcc29aec757bd Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 12 Apr 2021 02:55:18 -0400 Subject: [PATCH 16/28] Fix the adaptation of Catena_Mx25v8035f --- src/Catena_Mx25v8035f.h | 35 +++++++++++++++-------------- src/lib/stm32/Catena_Mx25v8035f.cpp | 9 +++++--- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/Catena_Mx25v8035f.h b/src/Catena_Mx25v8035f.h index 45f5654..012c299 100644 --- a/src/Catena_Mx25v8035f.h +++ b/src/Catena_Mx25v8035f.h @@ -37,6 +37,7 @@ Revision history: #pragma once #include +#include #include /* TODO: change these to enums and constepxrs in the McciCatena namespace */ @@ -128,7 +129,7 @@ Revision history: namespace McciCatena { -class Catena_Mx25v8035f +class Catena_Mx25v8035f : public cFlash { public: Catena_Mx25v8035f(void) @@ -143,36 +144,36 @@ class Catena_Mx25v8035f Catena_Mx25v8035f& operator=(const Catena_Mx25v8035f&&) = delete; // set up and probe device - boolean begin(SPIClass *pSpi, uint8_t ChipSelectPin = D19); - void end(void); + virtual bool begin(SPIClass *pSpi, uint8_t ChipSelectPin = D19) override; + virtual void end(void) override; // reset chip - void reset(void); + virtual void reset(void) override; // read id - void readId(uint8_t *pManufacturerId, uint16_t *pDeviceId); + virtual void readId(uint8_t *pManufacturerId, uint16_t *pDeviceId) override; - // chip earse - void eraseChip(void); + /// \brief chip erase + virtual void eraseChip(void) override; - // earse sector, block32 and block64 - void eraseSector(uint32_t SectorAddress); - void eraseBlock32(uint32_t Block32Address); - void eraseBlock64(uint32_t Block64Address); + // erase sector, block32 and block64 + virtual void eraseSector(uint32_t SectorAddress) override; + virtual void eraseBlock32(uint32_t Block32Address) override; + virtual void eraseBlock64(uint32_t Block64Address) override; // set protection -- CATENA_MX25V8035F_PL_xxx - void setProtection(uint8_t protectionLevel); + virtual void setProtection(uint8_t protectionLevel) override; // read a buffer - void read(uint32_t Address, uint8_t *pBuffer, size_t nBuffer); + virtual void read(uint32_t Address, uint8_t *pBuffer, size_t nBuffer) override; // program a buffer - void program(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer); - size_t programPage(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer); + virtual void program(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer) override; + virtual size_t programPage(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer) override; // power management - void powerDown(void); - void powerUp(void); + virtual void powerDown(void) override; + virtual void powerUp(void) override; private: boolean m_Initialized; diff --git a/src/lib/stm32/Catena_Mx25v8035f.cpp b/src/lib/stm32/Catena_Mx25v8035f.cpp index 9c6adf8..d90c07c 100644 --- a/src/lib/stm32/Catena_Mx25v8035f.cpp +++ b/src/lib/stm32/Catena_Mx25v8035f.cpp @@ -39,10 +39,13 @@ Revision history: #ifdef ARDUINO_ARCH_STM32 +#include + #include #include -#include "Catena_Mx25v8035f.h" +#include + #include "CatenaBase.h" using namespace McciCatena; @@ -89,7 +92,7 @@ Name: Catena_Mx25v8035f::begin */ -boolean Catena_Mx25v8035f::begin( +bool Catena_Mx25v8035f::begin( SPIClass *pSpi, uint8_t ChipSelectPin ) @@ -627,7 +630,7 @@ size_t Catena_Mx25v8035f::programPage( this->setWel(); - pSpi->transfer(this->m_CS, data, sizeof(data), SPI_CONTINUE); + pSpi->transfer(this->m_CS, data, 4, SPI_CONTINUE); memcpy(data, pBuffer, programSize); pSpi->transfer(this->m_CS, data, programSize, SPI_LAST); From 31156ade51d3b033d2bfe1a065f69a490f2ffa19 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 12 Apr 2021 02:55:54 -0400 Subject: [PATCH 17/28] Add API to fetch the line collector --- src/CatenaBase.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index e0f6b84..8957b85 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -333,6 +333,11 @@ class CatenaBase return &this->m_CommandStream; } + /// \brief return the command line collector + cStreamLineCollector *getCommandCollector() + { + return &this->m_Collector; + } /****************************************************************************\ | From 512bdfa7a1c45bedc37203743c26c7fc80e8ba96 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 12 Apr 2021 02:57:21 -0400 Subject: [PATCH 18/28] Add firmware download support --- src/Catena_BootloaderApi.h | 99 ++++++ src/Catena_Download.h | 197 ++++++++++++ src/Catena_Flash.h | 85 +++++ src/Catena_Serial.h | 159 ++++++++++ src/lib/Catena_BootloaderApi.cpp | 291 +++++++++++++++++ src/lib/Catena_Download.cpp | 525 +++++++++++++++++++++++++++++++ 6 files changed, 1356 insertions(+) create mode 100644 src/Catena_BootloaderApi.h create mode 100644 src/Catena_Download.h create mode 100644 src/Catena_Flash.h create mode 100644 src/Catena_Serial.h create mode 100644 src/lib/Catena_BootloaderApi.cpp create mode 100644 src/lib/Catena_Download.cpp diff --git a/src/Catena_BootloaderApi.h b/src/Catena_BootloaderApi.h new file mode 100644 index 0000000..b4de6ca --- /dev/null +++ b/src/Catena_BootloaderApi.h @@ -0,0 +1,99 @@ +/* + +Module: Catena_BootloaderApi.h + +Function: + McciCatena::cBootloaderApi + +Copyright and License: + This file copyright (C) 2021 by + + MCCI Corporation + 3520 Krums Corners Road + Ithaca, NY 14850 + + See accompanying LICENSE file for copyright and license information. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#pragma once + +#ifndef _catena_bootloaderapi_h_ +#define _catena_bootloaderapi_h_ + +#include +#include + +namespace McciCatena { + +class cBootloaderApi + { +private: + enum : uint32_t { + kNotInitialized = 0, + kNotFound = 1, + }; + + static constexpr uint32_t kBootloaderAddress = 0x08000000; + static constexpr uint32_t kSvcIndex = 11; + +public: + cBootloaderApi() + : m_svcaddr(kNotInitialized) + {}; + + // neither copyable nor movable + cBootloaderApi(const cBootloaderApi&) = delete; + cBootloaderApi& operator=(const cBootloaderApi&) = delete; + cBootloaderApi(const cBootloaderApi&&) = delete; + cBootloaderApi& operator=(const cBootloaderApi&&) = delete; + + // bootloader things + + /// \brief get the EEPROM flag pointer + uint32_t *getUpdateFlagAddress(void); + + /// \brief init a SHA512 hash buffer + void hash_init(uint8_t (&hash)[512/8]); + /// \brief add some bytes to a hash calculation + size_t hash_blocks(uint8_t (&hash)[512/8], const uint8_t *p, size_t n); + /// \brief finalize a hash calculation + void hash_finish(uint8_t (&hash)[512/8], const uint8_t *p, size_t n, size_t msgSize); + /// \brief constant-time hash compare + bool hash_verify(const uint8_t (&hash1)[512/8], const uint8_t (&hash2)[512/8]); + + /// \brief the app info block + struct AppInfo_t + { + /// \brief the identifying value + static constexpr uint32_t kMagic = (('M' << 0) | ('A' << 8) | ('P' << 16) | ('0' << 24)); + /// \brief the index of the appinfo block in the image + static constexpr uint32_t kFileIndex = 48 * 4; + static constexpr uint32_t kMaxAuthSize = 0x400; + + uint32_t magic = kMagic; ///< the format identifier. + uint32_t size = sizeof(*this); ///< size of this stucture, in bytes + uint32_t targetAddress { 0 }; ///< the target load address + uint32_t imagesize { 0 }; ///< size of the app, in bytes. + /// Must be multiple of 4. + uint32_t authsize { 0 }; ///< size of authentication data. + /// Overall image size is imagesize + /// + authsize + uint32_t version { 0 }; ///< version of the image (semantic version) + uint64_t posixTimestamp { 0 }; ///< Posix timestamp of image + uint8_t comment[16]; ///< the comment + uint8_t reserved56[16] { 0 }; ///< reserved, zero. + }; + +private: + uint32_t m_svcaddr; ///< memoized SVC entry point. + /// \brief return effective SVC entry point + uint32_t getSvc(void); + }; + +} // namespace McciCatena + +#endif /* _catena_bootloaderapi_h_ */ diff --git a/src/Catena_Download.h b/src/Catena_Download.h new file mode 100644 index 0000000..edb00db --- /dev/null +++ b/src/Catena_Download.h @@ -0,0 +1,197 @@ +/* + +Module: Catena_Download.h + +Function: + McciCatena::cDownload + +Copyright and License: + This file copyright (C) 2021 by + + MCCI Corporation + 3520 Krums Corners Road + Ithaca, NY 14850 + + See accompanying LICENSE file for copyright and license information. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#pragma once + +#ifndef _catena_download_h_ +#define _catena_download_h_ + +#include +#include +#include +#include +#include +#include +#include + +namespace McciCatena { + +/// +/// \brief Download from a Serial-like object +/// +class cDownload : public cPollableObject + { +protected: + static constexpr uint32_t kMaxFileSize = (192 - 24) * 1024; + static constexpr uint32_t kUploadFileAddress = 256 * 1024; + static constexpr uint32_t kFallbackFileAddress = 64 * 1024; + static constexpr uint32_t kTransferChunkBytes = 128; + static constexpr uint32_t kTransferTimeoutMs = 2 * 1000; + + enum class DownloadRq_t : uint8_t + { + Idle = 0, + GetUpdate = 1, + GetFallback = 2, + }; + +public: + // constructor + cDownload() {} + + // neither copyable nor movable + cDownload(const cDownload&) = delete; + cDownload& operator=(const cDownload&) = delete; + cDownload(const cDownload&&) = delete; + cDownload& operator=(const cDownload&&) = delete; + + /// set up to begin operation + void begin(cSerialAbstract &rSerial, cFlash &rFlash, cBootloaderApi &rBoot); + + /// poll function (from framework); drives FSM + virtual void poll() override; + + /// results of downloading + enum class Status_t : uint32_t + { + kSuccessful = 0, ///< successful + kInvalidRequest, ///< invalid request code + kDownloadSizeTooBig, ///< invalid download size + kDownloadReadTimeout, ///< timeout reading image + kDownloadReadError, ///< error reading image + kDownloadAppInfoBadMagic, ///< bad magic value in download + kDownloadAppInfoBadAuthsize,///< bad authsize value in download + kDownloadSizeTooSmall, ///< download must be >= 256+96 bytes + kHashCheckFailure, ///< hashcode check failure + kUpdateFlagLocateFailure, ///< could not locate update flag + kUpdateFlagSetFailure, ///< could not set update flag + }; + + /// states of the finite state machine. + enum class State_t : int + { + stNoChange = -1, ///< no change + stInitial = 0, ///< initial + stIdle, ///< idle + stErase, ///< erase the flash + stGetData, ///< download + stProgram, ///< program + stFinal, ///< finish up + }; + + /// dispatch FSM + /// \param [in] curState is the current state + /// \param [in] fEntry is true if the state is beign entered. + State_t fsmDispatch(State_t curState, bool fEntry); + + /// evaluate FSM + void fsmEval(void) + { + this->m_Fsm.eval(); + } + + /// completion function + typedef void CompletionFn(void *pUserData, Status_t status); + + /// request a download + bool evStart(bool fUpdateNotFallback, CompletionFn *pDoneFn, void *pUserData) + { + if (this->m_fBusy) + return false; + + this->m_fBusy = true; + this->m_pCompletionFn = pDoneFn; + this->m_pUserData = pUserData; + + this->m_events.f.downloadRequest = + fUpdateNotFallback ? DownloadRq_t::GetUpdate : + DownloadRq_t::GetFallback ; + + this->fsmEval(); + return true; + } + +protected: + /// complete a download + State_t completeRequest(Status_t status); + + /// \brief arm the request logic. + void armRequest(void) + { + this->m_events.f.downloadRequest = DownloadRq_t::Idle; + } + + /// \brief check whether download has been requested; reset flag. + /// \return \c true if download requested, \c false otherwise. + DownloadRq_t checkRequest(void) + { + auto const result = this->m_events.f.downloadRequest; + + if (result != DownloadRq_t::Idle) + { + this->m_events.f.downloadRequest = DownloadRq_t::Idle; + } + return result; + } + +private: + /// \brief the finite state machine object. + cFSM m_Fsm; + + cSerialAbstract *m_pSerial; ///< reference to the serial object for the downloader. + cFlash *m_pFlash; ///< reference to the flash object. + cBootloaderApi *m_pBootloaderApi; ///< reference to the bootloader API object. + uint32_t m_fileSize; ///< size of file. + uint32_t m_fileIndex; ///< current byte location in file. + uint32_t m_readTimer; ///< timeout timer for getData + CompletionFn *m_pCompletionFn; ///< completion function for request + void *m_pUserData; ///< context for request. + + /// \brief event flags for cDownload FSM implementation + union + { + /// view of all flags for quick reset. + uint32_t v; + + /// flags as individual bits + struct + { + DownloadRq_t downloadRequest: 8; ///< set non-zero when it's time to download + } f; + } m_events; + + cBootloaderApi::AppInfo_t m_appInfo; + + uint8_t m_pagebuffer[256]; ///< one page worth of data for SPI flash + uint32_t m_nPageBuffer; ///< number of bytes in page buffer. + uint32_t m_pageAddr; ///< SPI flash destination for pagebuffer. + + void pushBytesToFlash(const uint8_t *pBuffer, size_t nBufffer); + void flushBytesToFlash(); + void initPageBuffer(uint32_t byteIndex); + bool checkHash(uint32_t fileIndex, uint32_t fileSize); + + uint8_t m_fBusy; ///< if true, processing a request. + }; + +} // McciCatena + +#endif // _catena_download_h_ diff --git a/src/Catena_Flash.h b/src/Catena_Flash.h new file mode 100644 index 0000000..e8431ed --- /dev/null +++ b/src/Catena_Flash.h @@ -0,0 +1,85 @@ +/* + +Name: Catena_Flash.h + +Function: + Abstract flash base class for McciCatena. + +Copyright: + See accompanying LICENSE file. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#pragma once + +#ifndef _catena_flash_h_ +#define _catena_flash_h_ + +#include +#include + +namespace McciCatena { + +class cFlash + { +public: + // default constructor + cFlash() {} + // neither copyable nor movable + cFlash(const cFlash&) = delete; + cFlash& operator=(const cFlash&) = delete; + cFlash(const cFlash&&) = delete; + cFlash& operator=(const cFlash&&) = delete; + + // public methods + + /// \brief initialize flash system + virtual bool begin(SPIClass *pSpi, uint8_t ChipSelectPin) = 0; + + /// \brief stop the flash system + virtual void end() = 0; + + /// \brief reset chip + virtual void reset(void) = 0; + + /// \brief read JEDEC id + virtual void readId(uint8_t *pManufacturerId, uint16_t *pDeviceId) = 0; + + /// \brief chip erase + virtual void eraseChip(void) = 0; + + /// \brief erase a 4k page + virtual void eraseSector(uint32_t SectorAddress) = 0; + + /// \brief erase a 32k page + virtual void eraseBlock32(uint32_t Block32Address) = 0; + + /// \brief erase a 64k page + virtual void eraseBlock64(uint32_t Block64Address) = 0; + + // set protection -- CATENA_MX25V8035F_PL_xxx + virtual void setProtection(uint8_t protectionLevel) = 0; + + /// \brief read buffer + virtual void read(uint32_t Address, uint8_t *pBuffer, size_t nBuffer) = 0; + + /// \brief program buffer + virtual void program(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer) = 0; + + /// \brief program at most one page. + /// \returns number of bytes not consumed from buffer. + virtual size_t programPage(uint32_t Address, const uint8_t *pBuffer, size_t nBuffer) = 0; + + /// \brief power flash down + virtual void powerDown(void) = 0; + + /// \brief power flash ups + virtual void powerUp(void) = 0; + }; + +} // namespace McciCatena + +#endif /* _catena_flash_h_ */ diff --git a/src/Catena_Serial.h b/src/Catena_Serial.h new file mode 100644 index 0000000..b397258 --- /dev/null +++ b/src/Catena_Serial.h @@ -0,0 +1,159 @@ +/* + +Module: Catena_Serial.h + +Function: + McciCatena::cSerial + +Copyright and License: + This file copyright (C) 2021 by + + MCCI Corporation + 3520 Krums Corners Road + Ithaca, NY 14850 + + See accompanying LICENSE file for copyright and license information. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#pragma once + +#ifndef _catena_serial_h_ +#define _catena_serial_h_ + +#include + +namespace McciCatena { + +/// \brief Simple architecture that lets us use serial-like ports interchangably. +/// +/// \details +/// The Arduino system omittted a virutal base class that all Serial ports +/// can be derived from. This means you can't have a pointer to a "serial-like" +/// thing, which is very inconvenient. Even if we put one in our Arduino +/// variant, it would not help with third-party libraries. +/// +/// We need one, however, so we synthesize one, consisting of a base virtual +/// class \c cSerialAbstract accompanied by concrete derived template classes that +/// wrap the actual object and give it virtual methods. +/// +/// \note +/// This implementation doesn't provide all stream methods. +/// +class cSerialAbstract + { +public: + // constructor + cSerialAbstract() {}; + + // neither copyable nor movable. + cSerialAbstract(const cSerialAbstract&) = delete; + cSerialAbstract& operator=(const cSerialAbstract&) = delete; + cSerialAbstract(const cSerialAbstract&&) = delete; + cSerialAbstract& operator=(const cSerialAbstract&&) = delete; + + virtual void begin(unsigned long baudrate) const = 0; + virtual void begin(unsigned long baudrate, uint16_t config) const = 0; + virtual int available() const = 0; + virtual int read() const = 0; + virtual size_t write(const uint8_t *buffer, size_t size) const = 0; + size_t write(const char *buffer, size_t size) const + { + return this->write((const uint8_t *)buffer, size); + } + virtual void end() const = 0; + + virtual void drainRead() const + { + while (this->read() >= 0) + /* discard */; + } + virtual void drainWrite() const = 0; + + // provide this as a synonym for drainWrite, so that we + // have the complete Arduino::Uart interface. + virtual void flush() const + { + this->drainWrite(); + } + + // get the underlying stream + virtual Stream & stream(void) = 0; + }; + +/// +/// \brief Instantiate a \c cSerial variant for a given Serial-like type +/// +/// \param T is class like \ref UART that has UART semantics. +/// +/// \details +/// A typical use might be `cSerial gSerial(Serial); +/// this would declare a \ref cSerial object that is a wrapper for +/// \ref Serial without requiring that you know the type of `Serial`. +/// This is convenient on platforms where Serial changes type based on +/// whether it's hardware, software, USB, etc. +/// +template +class cSerial : public cSerialAbstract + { +public: + // constructor + cSerial(T *pPort) : m_pPort(pPort) {} + cSerial(T &Port) : m_pPort(&Port) {} + + // neither copyable nor movable. + cSerial(const cSerial&) = delete; + cSerial& operator=(const cSerial&) = delete; + cSerial(const cSerial&&) = delete; + cSerial& operator=(const cSerial&&) = delete; + + virtual int available() const override + { + return this->m_pPort->available(); + } + + virtual void begin(unsigned long ulBaudRate) const override + { + this->m_pPort->begin(ulBaudRate); + } + + virtual void begin(unsigned long ulBaudRate, uint16_t config) const override + { + this->m_pPort->begin(ulBaudRate, config); + } + + virtual void drainWrite() const override + { + this->m_pPort->flush(); + } + + virtual int read() const override + { + return this->m_pPort->read(); + } + + virtual size_t write(const uint8_t *buffer, size_t size) const override + { + return this->m_pPort->write(buffer, size); + } + + virtual void end() const override + { + this->m_pPort->end(); + } + + virtual Stream & stream() override + { + return *m_pPort; + } + +private: + T *m_pPort; + }; + +} // namespace McciCatena + +#endif /* _catena_serial_h_ */ diff --git a/src/lib/Catena_BootloaderApi.cpp b/src/lib/Catena_BootloaderApi.cpp new file mode 100644 index 0000000..4cea06e --- /dev/null +++ b/src/lib/Catena_BootloaderApi.cpp @@ -0,0 +1,291 @@ +/* + +Module: Catena_BootloaderApi.cpp + +Function: + cBootloaderApi. + +Copyright and License: + This file copyright (C) 2021 by + + MCCI Corporation + 3520 Krums Corners Road + Ithaca, NY 14850 + + See accompanying LICENSE file for copyright and license information. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#include "Catena_BootloaderApi.h" + +#include +using namespace McciCatena; + +/****************************************************************************\ +| +| Manifest constants & typedefs. +| +\****************************************************************************/ + +extern "C" { + +/// \brief error codes from SVC handler on ARMv6-M systems & such like +typedef enum McciBootloaderPlatform_ARMv6M_SvcError_e + { + /// successful processing + McciBootloaderPlatform_SvcError_OK = 0, + + /// error: verify failure + McciBootloaderPlatform_SvcError_VerifyFailure = UINT32_C(-3), + /// error: invalid parameter to SVC + McciBootloaderPlatform_SvcError_InvalidParameter = UINT32_C(-2), + /// error: SVC isn't just unimplemented, it's unkown to the bootloader + McciBootloaderPlatform_SvcError_Unclaimed = UINT32_C(-1), + } McciBootloaderPlatform_ARMv6M_SvcError_t; + +/// \brief SVC request codes for boot loader on ARMv6-M systems & such like +typedef enum McciBootloaderPlatform_ARMv6M_SvcRq_e + { + /// Fetch pointer to \c uint32_t "update" flag in EEPROM. \c arg1 is pointer to cell to + /// receive pointer. + McciBootloaderPlatform_ARMv6M_SvcRq_GetUpdatePointer = UINT32_C(0x01000000), + + /// Call \ref mcci_tweetnacl_hashblocks_sha512_init. \c arg1 is pointer to hash block. + McciBootloaderPlatform_ARMv6M_SvcRq_HashInit /* = UINT32_C(0x01000001) */, + + /// Call \ref mcci_tweetnacl_hashblocks_sha512. \c arg1 points to argument. + /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_t + McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks /* = UINT32_C(0x01000002) */, + + /// Call \ref mcci_tweetnacl_hashblocks_finish. \c arg1 points to + /// argument. + /// \see McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_t + McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish /* = UINT32_C(0x01000003) */, + + /// Call \ref mcci_tweetnacl_verify64. \c arg1 and \c arg2 are the pointers + /// result is set to verifyFailure for failure. + McciBootloaderPlatform_ARMv6M_SvcRq_Verify64 /* = UINT32_C(0x01000004) */, + } McciBootloaderPlatform_ARMv6M_SvcRq_t; + +/// \brief argument to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks +typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_s + { + void *pHash; + const uint8_t *pMessage; + size_t nMessage; + } McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_t; + +/// \brief argumennt to \ref McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish +typedef struct McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_s + { + void *pHash; + const uint8_t *pMessage; + size_t nMessage; + size_t nOverall; + } McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_t; + +/// +/// \brief SVC function interface +/// +/// \param [in] svcRequest is the request code. +/// \param [in] pErrorCode points to a cell to be filled with the error code +/// (According to the value of \p svcRequest, there may additional +/// OUT parameters) +/// \param [in] arg1 is an extra argument, interpreted according to \p svcRequest +/// \param [in] arg2 is an extra argument, interpreted according to \p svcRequest +/// +/// \details +/// This definition lets us take advantage of the ARMv6-M and related +/// implementations; exception handlers are just like regular subroutines +/// (except that results have to be passed back by modifying the saved +/// registers on the stack). We work around this by passing results back +/// in memory. +/// +typedef void +(McciBootloaderPlatform_ARMv6M_SvcHandlerFn_t)( + McciBootloaderPlatform_ARMv6M_SvcRq_t svcRequest, + McciBootloaderPlatform_ARMv6M_SvcError_t *pErrorCode, + uint32_t arg1, + uint32_t arg2 + ); + +/// +/// \brief convert number to systcal function pointer +/// +static inline +McciBootloaderPlatform_ARMv6M_SvcHandlerFn_t *toSvc(uint32_t v) + { + return (McciBootloaderPlatform_ARMv6M_SvcHandlerFn_t *)v; + } +} // extern "C" + + +/****************************************************************************\ +| +| Read-only data. +| +\****************************************************************************/ + + +/****************************************************************************\ +| +| Variables. +| +\****************************************************************************/ + +uint32_t *cBootloaderApi::getUpdateFlagAddress() + { + auto const pSvc = toSvc(this->getSvc()); + McciBootloaderPlatform_ARMv6M_SvcError_t err; + uint32_t *result; + + err = McciBootloaderPlatform_SvcError_Unclaimed; + result = nullptr; + + if (pSvc != nullptr) + { + (*pSvc)( + McciBootloaderPlatform_ARMv6M_SvcRq_GetUpdatePointer, + &err, + (uint32_t)&result, + 0); + } + + if (err != McciBootloaderPlatform_SvcError_OK) + result = nullptr; + + return result; + } + +void cBootloaderApi::hash_init(uint8_t (&hash)[512/8]) + { + auto const pSvc = toSvc(this->getSvc()); + McciBootloaderPlatform_ARMv6M_SvcError_t err; + err = McciBootloaderPlatform_SvcError_Unclaimed; + + if (pSvc != nullptr) + { + (*pSvc)( + McciBootloaderPlatform_ARMv6M_SvcRq_HashInit, + &err, + (uint32_t)&hash[0], + 0); + } + + if (err != McciBootloaderPlatform_SvcError_OK) + { + memset(hash, 0, sizeof(hash)); + } + } + +size_t cBootloaderApi::hash_blocks( + uint8_t (&hash)[512/8], + const uint8_t *p, + size_t n + ) + { + auto const pSvc = toSvc(this->getSvc()); + McciBootloaderPlatform_ARMv6M_SvcError_t err; + size_t result; + + err = McciBootloaderPlatform_SvcError_Unclaimed; + result = 0; + + if (pSvc != nullptr) + { + McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks_Arg_t arg; + + arg.pHash = hash; + arg.pMessage = p; + arg.nMessage = n; + (*pSvc)( + McciBootloaderPlatform_ARMv6M_SvcRq_HashBlocks, + &err, + (uint32_t) &arg, + 0 + ); + if (err == McciBootloaderPlatform_SvcError_OK) + result = arg.nMessage; + } + + return result; + } + +void cBootloaderApi::hash_finish( + uint8_t (&hash)[512/8], + const uint8_t *p, + size_t n, + size_t msgSize + ) + { + auto const pSvc = toSvc(this->getSvc()); + McciBootloaderPlatform_ARMv6M_SvcError_t err; + + err = McciBootloaderPlatform_SvcError_Unclaimed; + + if (pSvc != nullptr) + { + McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish_Arg_t arg; + + arg.pHash = hash; + arg.pMessage = p; + arg.nMessage = n; + arg.nOverall = msgSize; + (*pSvc)( + McciBootloaderPlatform_ARMv6M_SvcRq_HashFinish, + &err, + (uint32_t) &arg, + 0 + ); + } + } + +bool cBootloaderApi::hash_verify( + const uint8_t (&hash1)[512/8], + const uint8_t (&hash2)[512/8] + ) + { + auto const pSvc = toSvc(this->getSvc()); + McciBootloaderPlatform_ARMv6M_SvcError_t err; + + err = McciBootloaderPlatform_SvcError_Unclaimed; + + if (pSvc != nullptr) + { + (*pSvc)( + McciBootloaderPlatform_ARMv6M_SvcRq_Verify64, + &err, + (uint32_t) hash1, + (uint32_t) hash2 + ); + } + + return err == McciBootloaderPlatform_SvcError_OK; + } + +uint32_t cBootloaderApi::getSvc(void) + { + if (this->m_svcaddr == kNotFound) + return 0; + else if (this->m_svcaddr != kNotInitialized) + return this->m_svcaddr; + + // look for the SVC pointer. + uint32_t const vects = SCB->VTOR; + uint32_t result; + + this->m_svcaddr = kNotFound; + if (vects == kBootloaderAddress) + /* not using bootloader */ + return 0; + + const auto svcAddr = ((uint32_t *)kBootloaderAddress)[kSvcIndex]; + if ((svcAddr & 1) == 0) + return 0; + + this->m_svcaddr = svcAddr; + return svcAddr; + } diff --git a/src/lib/Catena_Download.cpp b/src/lib/Catena_Download.cpp new file mode 100644 index 0000000..5dc5957 --- /dev/null +++ b/src/lib/Catena_Download.cpp @@ -0,0 +1,525 @@ +/* + +Module: Model4811_Download.h + +Function: + cDownload + +Copyright and License: + This file copyright (C) 2021 by + + MCCI Corporation + 3520 Krums Corners Road + Ithaca, NY 14850 + + See accompanying LICENSE file for copyright and license information. + +Author: + Terry Moore, MCCI Corporation April 2021 + +*/ + +#include "Catena_Download.h" + +#include +#include +#include +#include + +using namespace McciCatena; + +/****************************************************************************\ +| +| Manifest constants & typedefs. +| +\****************************************************************************/ + + +/****************************************************************************\ +| +| Read-only data. +| +\****************************************************************************/ + + +/****************************************************************************\ +| +| Variables. +| +\****************************************************************************/ + + +/* + +Name: cDownload::begin() + +Function: + Initiate operation of the Download module. + +Definition: + void cDownload::begin( + ); + +Description: + Start the download module. For convenience, we ask the user to pass in a + cFlash object and cBootloaderApi object. + +Returns: + No result is returned. + +*/ + +void cDownload::begin(cSerialAbstract &rSerial, cFlash &rFlash, cBootloaderApi &rBootloaderApi) + { + // save the pointers. + this->m_pSerial = &rSerial; + this->m_pFlash = &rFlash; + this->m_pBootloaderApi = &rBootloaderApi; + + // initialize the FSM + this->m_Fsm.init(*this, &cDownload::fsmDispatch); + + // set up for polling. + CatenaBase::pCatenaBase->registerObject(this); + } + +/* + +Name: cDownload::poll() + +Function: + Initiate operation of the Download module. + +Definition: + virtual void cDownload::poll( + void + ) override; + +Description: + We evaluate the firmware Download FSM + +Returns: + No result is returned. + +*/ + +void cDownload::poll(void) + { + this->fsmEval(); + } + +/* + +Name: cDownload::fsmDispatch() + +Function: + Handle the FSM updates for the Download + +Definition: + cDownload::State_t + cDownload::fsmDispatch( + cDownload::State_t curState, + bool fEntry + ); + +Description: + The download control engine walks through its states to + make things happen. + +Returns: + No result is returned. + +*/ + +cDownload::State_t +cDownload::fsmDispatch( + cDownload::State_t curState, + bool fEntry + ) + { + State_t newState; + + newState = State_t::stNoChange; + + switch (curState) + { + case State_t::stInitial: + { + // for debugging + //gLog.setFlags(cLog::DebugFlags(gLog.getFlags() | gLog.kTrace)); + + newState = State_t::stIdle; + } + break; + + case State_t::stIdle: + { + if (fEntry) + { + this->armRequest(); + } + + auto const requestType = this->checkRequest(); + + if (requestType != DownloadRq_t::Idle) + { + auto const regionAddress = + (requestType == DownloadRq_t::GetUpdate) + ? kUploadFileAddress + : kFallbackFileAddress + ; + this->initPageBuffer(regionAddress); + + newState = State_t::stErase; + } + } + break; + + case State_t::stErase: + { + const uint32_t regionAddress = this->m_pageAddr; + + if (fEntry) + { + const uint32_t regionEnd = regionAddress + kMaxFileSize; + + // erase pages containing the region + for (auto blockAddress = regionAddress; blockAddress < regionEnd; blockAddress += 64 * 1024) + { + gLog.printf(gLog.kTrace, "erase block at 0x%x...", blockAddress); + this->m_pFlash->eraseBlock64(blockAddress); + gLog.printf(gLog.kTrace, "\n"); + } + } + + // start download + newState = State_t::stGetData; + this->m_fileIndex = 0; + // set size large at first; we'll reduce it once we've read the header + this->m_fileSize = kMaxFileSize; + } + break; + + case State_t::stGetData: + { + auto const nAvail = this->m_pSerial->available(); + auto const tNow = millis(); + + // for USB downloads, we don't have to handshake. For others, + // we do, so print a '.' when we are looking for data. + if (fEntry) + { + // record starting time. + this->m_readTimer = tNow; + + if (nAvail == 0) + this->m_pSerial->write("<", 1); + } + + if (nAvail >= kTransferChunkBytes) + { + newState = State_t::stProgram; + } + else if (tNow - this->m_readTimer > kTransferTimeoutMs) + { + newState = this->completeRequest(Status_t::kDownloadReadTimeout); + } + } + break; + + case State_t::stProgram: + { + if (fEntry) + { + // completion; copy data bytes to buffer and program + // as there are overflows. + uint8_t data[kTransferChunkBytes]; + + auto const nRead = this->m_pSerial->stream().readBytes(data, sizeof(data)); + + if (nRead != kTransferChunkBytes) + { + newState = this->completeRequest(Status_t::kDownloadReadError); + break; + } + + auto const thisIndex = this->m_fileIndex; + if (thisIndex < this->m_appInfo.kFileIndex + sizeof(this->m_appInfo)) + { + // copy bytes to the app info header image + uint8_t *pOut = (uint8_t *)&this->m_appInfo; + uint8_t *pData = data; + size_t nCopy; + + nCopy = 0; + if (thisIndex < this->m_appInfo.kFileIndex) + { + // bytes at tail might qualify + if (thisIndex + nRead > this->m_appInfo.kFileIndex) + { + size_t nSkip = this->m_appInfo.kFileIndex - thisIndex; + pData += nSkip; + nCopy = nRead - nSkip; + if (nCopy > sizeof(this->m_appInfo)) + nCopy = sizeof(this->m_appInfo); + } + } + else /* start at front of data, but index into app info */ + { + size_t nSkip = thisIndex - this->m_appInfo.kFileIndex; + pOut += nSkip; + nCopy = this->m_appInfo.kFileIndex - nSkip; + if (nCopy < nRead) + nCopy = nRead; + } + + // copy this fragment to the AppInfo image + if (nCopy > 0) + { + memcpy(pOut, pData, nCopy); + + // is it the last fragment? + if (pOut + nCopy == (uint8_t *) &this->m_appInfo + sizeof(this->m_appInfo)) + { + // we just filled it. check signature. + if (this->m_appInfo.magic != this->m_appInfo.kMagic) + { + newState = this->completeRequest(Status_t::kDownloadAppInfoBadMagic); + break; + } + // check the file size. + if (this->m_appInfo.imagesize < 0x100) + { + newState = this->completeRequest(Status_t::kDownloadSizeTooSmall); + break; + } + else if (this->m_appInfo.authsize > this->m_appInfo.kMaxAuthSize) + { + newState = this->completeRequest(Status_t::kDownloadAppInfoBadAuthsize); + break; + } + else if (this->m_appInfo.imagesize > this->kMaxFileSize - this->m_appInfo.authsize) + { + newState = this->completeRequest(Status_t::kDownloadSizeTooBig); + break; + } + else + { + this->m_fileSize = this->m_appInfo.imagesize + this->m_appInfo.authsize; + gLog.printf(gLog.kTrace, "file size: 0x%x\n", this->m_fileSize); + } + } + } + } + + // advance pointer + auto thisSize = this->m_fileSize - this->m_fileIndex; + if (thisSize > nRead) + thisSize = nRead; + + this->m_fileIndex += thisSize; + + // copy bytes to program buffer, programming as it fills + this->pushBytesToFlash(data, thisSize); + } + + if (this->m_fileIndex < this->m_fileSize) + newState = State_t::stGetData; + else + newState = State_t::stFinal; + } + break; + + case State_t::stFinal: + { + if (fEntry) + { + // write out the left-overs + this->flushBytesToFlash(); + } + + bool fOk; + + gLog.printf(gLog.kTrace, "checking hash:"); + + // check the hash + auto status = this->checkHash(this->m_pageAddr - this->m_fileSize, this->m_fileSize) + ? Status_t::kSuccessful + : Status_t::kHashCheckFailure + ; + + // if successful, set the EEPROM flag + if (status == Status_t::kSuccessful) + { + gLog.printf(gLog.kTrace, " OK\nSet boot flag:"); + uint32_t *pUpdateFlag = this->m_pBootloaderApi->getUpdateFlagAddress(); + + if (pUpdateFlag == nullptr) + status = Status_t::kUpdateFlagLocateFailure; + else + { + /* Unlocking FLASH_PECR register access*/ + if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK)) + { + WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1); + WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2); + } + + FLASH->PECR &= ~FLASH_PECR_ERASE_Msk; + + __HAL_FLASH_CLEAR_FLAG( + FLASH_FLAG_EOP|FLASH_FLAG_WRPERR|FLASH_FLAG_PGAERR|\ + FLASH_FLAG_SIZERR|FLASH_FLAG_OPTVERR|FLASH_FLAG_RDERR|\ + FLASH_FLAG_FWWERR|FLASH_FLAG_NOTZEROERR + ); + + *pUpdateFlag = 0xFFFFFFFFu; + HAL_FLASH_Lock(); + + while (FLASH->SR & FLASH_SR_BSY) + /* loop */; + + if (*pUpdateFlag != 0xFFFFFFFFu) + { + status = Status_t::kUpdateFlagSetFailure; + gLog.printf(gLog.kTrace, " fail: 0x%x\n", *pUpdateFlag); + } + else + { + gLog.printf(gLog.kTrace, " OK\n"); + } + } + } + else + { + gLog.printf(gLog.kTrace, " fail\n"); + } + + newState = this->completeRequest(status); + } + break; + + default: + newState = State_t::stIdle; + break; + } + + return newState; + } + +void +cDownload::pushBytesToFlash( + const uint8_t *pBuffer, + size_t nBuffer + ) + { + while (nBuffer > 0) + { + auto const nPageBuffer = this->m_nPageBuffer; + auto nCopy = sizeof(this->m_pagebuffer) - nPageBuffer; + if (nCopy > nBuffer) + nCopy = nBuffer; + + memcpy(this->m_pagebuffer + nPageBuffer, pBuffer, nCopy); + pBuffer += nCopy; + nBuffer -= nCopy; + this->m_nPageBuffer += nCopy; + if (this->m_nPageBuffer == sizeof(this->m_pagebuffer)) + { + this->flushBytesToFlash(); + // above resets this->m_nPageBuffer to zero and advances m_pageAddr. + } + } + } + +void +cDownload::flushBytesToFlash( + void + ) + { + if (this->m_nPageBuffer != 0) + { + this->m_pFlash->program(this->m_pageAddr, this->m_pagebuffer, this->m_nPageBuffer); + this->m_pageAddr += this->m_nPageBuffer; + this->m_nPageBuffer = 0; + } + } + +void +cDownload::initPageBuffer( + uint32_t bytePosition + ) + { + this->m_pageAddr = bytePosition; + this->m_nPageBuffer = 0; + } + +bool +cDownload::checkHash( + uint32_t flashBaseAddr, + uint32_t fileSize + ) + { + uint8_t hash[512/8]; + uint32_t trailerSize = this->m_appInfo.authsize - 32; + size_t nRemaining; + const uint8_t *pRemaining; + + if (fileSize <= trailerSize) + return false; + + this->m_pBootloaderApi->hash_init(hash); + + auto const flashEndAddr = flashBaseAddr + fileSize - trailerSize; + + nRemaining = 0; + pRemaining = this->m_pagebuffer; + + for (auto i = flashBaseAddr; i < flashEndAddr; ) + { + uint32_t n = flashEndAddr - i; + if (n > sizeof(this->m_pagebuffer)) + n = sizeof(this->m_pagebuffer); + + this->m_pFlash->read(i, this->m_pagebuffer, n); + nRemaining = this->m_pBootloaderApi->hash_blocks(hash, this->m_pagebuffer, n); + + // advance + i += n; + + // in case it's the last time, set pRemaining. + auto const nConsumed = n - nRemaining; + pRemaining = this->m_pagebuffer + nConsumed; + } + + // finish up the hash. + this->m_pBootloaderApi->hash_finish(hash, pRemaining, nRemaining, flashEndAddr - flashBaseAddr); + + // now grab the security info (including the public key) + this->m_pFlash->read(flashEndAddr - 32, this->m_pagebuffer, trailerSize + 32); + + // this awkward couple of lines lets us work around the problem + // of casting the pointer into pagebuffer to a pointer to a hash. + // Hard to do it directly. + struct hash_t { uint8_t bytes[512 / 8]; }; + const hash_t *const pProgHash = (hash_t *)&this->m_pagebuffer[32]; + + if (this->m_pBootloaderApi->hash_verify(hash, pProgHash->bytes)) + return true; + else + return false; + } + +cDownload::State_t +cDownload::completeRequest( + Status_t status + ) + { + if (this->m_fBusy) + { + this->m_fBusy = false; + (*this->m_pCompletionFn)(this->m_pUserData, status); + } + + return State_t::stIdle; + } From cf38b87e9f4ee38851e5101c7eaa266e561b2027 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 12 Apr 2021 02:57:50 -0400 Subject: [PATCH 19/28] This is v0.21.0-4 (pre-release 4) --- src/CatenaBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index 8957b85..b2dfbc0 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -57,7 +57,7 @@ Copyright notice: (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) #define CATENA_ARDUINO_PLATFORM_VERSION \ - CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 3) /* v0.21.0-3 */ + CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 4) /* v0.21.0-4 */ #define CATENA_ARDUINO_PLATFORM_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From f5fa72c8517ec9c725fd442bd9b72d5538eb56a1 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 3 May 2021 18:09:46 -0400 Subject: [PATCH 20/28] Refactor download to allow non-serial-port sources --- src/Catena_Download.h | 146 +++++++++++++++++++++++++++--------- src/lib/Catena_Download.cpp | 83 ++++++++++++++++---- 2 files changed, 180 insertions(+), 49 deletions(-) diff --git a/src/Catena_Download.h b/src/Catena_Download.h index edb00db..55c2f3c 100644 --- a/src/Catena_Download.h +++ b/src/Catena_Download.h @@ -39,18 +39,22 @@ namespace McciCatena { /// class cDownload : public cPollableObject { -protected: - static constexpr uint32_t kMaxFileSize = (192 - 24) * 1024; - static constexpr uint32_t kUploadFileAddress = 256 * 1024; - static constexpr uint32_t kFallbackFileAddress = 64 * 1024; - static constexpr uint32_t kTransferChunkBytes = 128; - static constexpr uint32_t kTransferTimeoutMs = 2 * 1000; - +public: + /// \brief parameters + /// \{ + static constexpr uint32_t kMaxFileSize = (192 - 24) * 1024; ///< maximum download file size + static constexpr uint32_t kUploadFileAddress = 256 * 1024; ///< where the update file lives in SPI flash + static constexpr uint32_t kFallbackFileAddress = 64 * 1024; ///< where the fallback file lives in SPI flash + static constexpr uint32_t kTransferChunkBytes = 128; ///< how many bytes in a "chunk" -- matches half-page size + static constexpr uint32_t kTransferTimeoutMs = 2 * 1000; ///< how long to wait before timing out a download, in seconds. + /// \} + + /// \brief the request codes for doing an upload enum class DownloadRq_t : uint8_t { - Idle = 0, - GetUpdate = 1, - GetFallback = 2, + Idle = 0, ///< no request pending + GetUpdate = 1, ///< set the update image and do an update + GetFallback = 2, ///< set the fallback image }; public: @@ -64,7 +68,7 @@ class cDownload : public cPollableObject cDownload& operator=(const cDownload&&) = delete; /// set up to begin operation - void begin(cSerialAbstract &rSerial, cFlash &rFlash, cBootloaderApi &rBoot); + void begin(cFlash &rFlash, cBootloaderApi &rBoot); /// poll function (from framework); drives FSM virtual void poll() override; @@ -108,27 +112,100 @@ class cDownload : public cPollableObject this->m_Fsm.eval(); } - /// completion function - typedef void CompletionFn(void *pUserData, Status_t status); + // the request object + struct Request_t + { + template + struct Closure_t + { + Tfn *pFunction; + void *pUserData; + void init(Tfn *pFn, void *pData) + { + this->pFunction = pFn; + this->pUserData = pData; + } + }; + + /// completion function + typedef void CompletionFn_t(void *pUserData, Status_t status); + /// query available data + typedef int QueryAvailableDataFn_t(void *pUserData); + /// pull data if possible + typedef void PromptForDataFn_t(void *pUserData); + /// read bytes + typedef size_t ReadBytesFn_t(void *pUserData, std::uint8_t *pBuffer, size_t nBuffer); + + /// The methods + Closure_t Completion; + Closure_t QueryAvailableData; + Closure_t PromptForData; + Closure_t ReadBytes; + + /// the request code. + DownloadRq_t rq; + + int available(void) + { + return this->QueryAvailableData.pFunction(this->QueryAvailableData.pUserData); + } + void promptForData(void) + { + if (this->PromptForData.pFunction != nullptr) + this->PromptForData.pFunction(this->PromptForData.pUserData); + } + size_t readBytes(std::uint8_t *pBuffer, size_t nBuffer) + { + return this->ReadBytes.pFunction(this->ReadBytes.pUserData, pBuffer, nBuffer); + } + }; + - /// request a download - bool evStart(bool fUpdateNotFallback, CompletionFn *pDoneFn, void *pUserData) + /// + /// request an abstract download + /// + /// \returns \c true if the request was launched and the callback routine + /// will be called. \c false if the request was rejected; the + /// callback routine will not be called. + /// + bool evStart(Request_t &request) { - if (this->m_fBusy) + if (this->m_pRequest != nullptr) return false; - this->m_fBusy = true; - this->m_pCompletionFn = pDoneFn; - this->m_pUserData = pUserData; + this->m_pRequest = &request; - this->m_events.f.downloadRequest = - fUpdateNotFallback ? DownloadRq_t::GetUpdate : - DownloadRq_t::GetFallback ; + this->m_events.f.downloadRequest = true; this->fsmEval(); return true; } + /// + /// request a simple serial download over the specified serial port. + /// + /// \param [in] rq is the request (typically \c DownloadRq_t::GetUpdate oir + /// \c DownloadRq_t::GetFallback. + /// \param [in] serial is the serial port to be used. + /// \param [in] request is the request block to use. It is owned by the + /// library until the completion callback (if the request + /// gets launched). + /// \param [in] pCallback function to be called on completion of request + /// processing, if the request is accepted. + /// \param [in] pUserData user context to be passed to the callback function. + /// + /// \returns \c true if the request was launched and the callback routine + /// will be called. \c false if the request was rejected; the + /// callback routine will not be called. + /// + bool evStartSerialDownload( + DownloadRq_t rq, + cSerialAbstract &serial, + Request_t &request, + Request_t::CompletionFn_t *pCallback, + void *pUserData + ); + protected: /// complete a download State_t completeRequest(Status_t status); @@ -136,18 +213,18 @@ class cDownload : public cPollableObject /// \brief arm the request logic. void armRequest(void) { - this->m_events.f.downloadRequest = DownloadRq_t::Idle; + this->m_events.f.downloadRequest = false; } /// \brief check whether download has been requested; reset flag. /// \return \c true if download requested, \c false otherwise. - DownloadRq_t checkRequest(void) + bool checkRequest(void) { auto const result = this->m_events.f.downloadRequest; - if (result != DownloadRq_t::Idle) + if (result) { - this->m_events.f.downloadRequest = DownloadRq_t::Idle; + this->m_events.f.downloadRequest = false; } return result; } @@ -156,14 +233,12 @@ class cDownload : public cPollableObject /// \brief the finite state machine object. cFSM m_Fsm; - cSerialAbstract *m_pSerial; ///< reference to the serial object for the downloader. - cFlash *m_pFlash; ///< reference to the flash object. + cFlash *m_pFlash; ///< reference to the flash object. cBootloaderApi *m_pBootloaderApi; ///< reference to the bootloader API object. - uint32_t m_fileSize; ///< size of file. - uint32_t m_fileIndex; ///< current byte location in file. - uint32_t m_readTimer; ///< timeout timer for getData - CompletionFn *m_pCompletionFn; ///< completion function for request - void *m_pUserData; ///< context for request. + uint32_t m_fileSize; ///< size of file. + uint32_t m_fileIndex; ///< current byte location in file. + uint32_t m_readTimer; ///< timeout timer for getData + Request_t *m_pRequest; ///< current request or nullptr /// \brief event flags for cDownload FSM implementation union @@ -174,7 +249,7 @@ class cDownload : public cPollableObject /// flags as individual bits struct { - DownloadRq_t downloadRequest: 8; ///< set non-zero when it's time to download + bool downloadRequest: 1; ///< set non-zero when a request arrives } f; } m_events; @@ -188,10 +263,9 @@ class cDownload : public cPollableObject void flushBytesToFlash(); void initPageBuffer(uint32_t byteIndex); bool checkHash(uint32_t fileIndex, uint32_t fileSize); - - uint8_t m_fBusy; ///< if true, processing a request. }; + } // McciCatena #endif // _catena_download_h_ diff --git a/src/lib/Catena_Download.cpp b/src/lib/Catena_Download.cpp index 5dc5957..e9d7ff4 100644 --- a/src/lib/Catena_Download.cpp +++ b/src/lib/Catena_Download.cpp @@ -24,6 +24,7 @@ Copyright and License: #include #include #include +#include #include using namespace McciCatena; @@ -58,21 +59,23 @@ Name: cDownload::begin() Definition: void cDownload::begin( + cSerialAbstract &rSerial, + cFlash &rFlash, + cBootloaderApi &rBootloaderApi ); Description: Start the download module. For convenience, we ask the user to pass in a - cFlash object and cBootloaderApi object. + a cFlash object and cBootloaderApi object. Returns: No result is returned. */ -void cDownload::begin(cSerialAbstract &rSerial, cFlash &rFlash, cBootloaderApi &rBootloaderApi) +void cDownload::begin(cFlash &rFlash, cBootloaderApi &rBootloaderApi) { // save the pointers. - this->m_pSerial = &rSerial; this->m_pFlash = &rFlash; this->m_pBootloaderApi = &rBootloaderApi; @@ -159,12 +162,12 @@ cDownload::fsmDispatch( this->armRequest(); } - auto const requestType = this->checkRequest(); + auto const newRequest = this->checkRequest(); - if (requestType != DownloadRq_t::Idle) + if (newRequest) { auto const regionAddress = - (requestType == DownloadRq_t::GetUpdate) + (this->m_pRequest->rq == DownloadRq_t::GetUpdate) ? kUploadFileAddress : kFallbackFileAddress ; @@ -202,18 +205,19 @@ cDownload::fsmDispatch( case State_t::stGetData: { - auto const nAvail = this->m_pSerial->available(); + auto const nAvail = this->m_pRequest->available(); auto const tNow = millis(); // for USB downloads, we don't have to handshake. For others, - // we do, so print a '.' when we are looking for data. + // we do, so we want print a '<' when we are looking for data. + // Call back to the client to take care of it if (fEntry) { // record starting time. this->m_readTimer = tNow; if (nAvail == 0) - this->m_pSerial->write("<", 1); + this->m_pRequest->promptForData(); } if (nAvail >= kTransferChunkBytes) @@ -235,7 +239,7 @@ cDownload::fsmDispatch( // as there are overflows. uint8_t data[kTransferChunkBytes]; - auto const nRead = this->m_pSerial->stream().readBytes(data, sizeof(data)); + auto const nRead = this->m_pRequest->readBytes(data, sizeof(data)); if (nRead != kTransferChunkBytes) { @@ -515,11 +519,64 @@ cDownload::completeRequest( Status_t status ) { - if (this->m_fBusy) + Request_t * const pRequest = this->m_pRequest; + if (pRequest != nullptr) { - this->m_fBusy = false; - (*this->m_pCompletionFn)(this->m_pUserData, status); + this->m_pRequest = nullptr; + (*pRequest->Completion.pFunction)(pRequest->Completion.pUserData, status); } return State_t::stIdle; } + +bool +cDownload::evStartSerialDownload( + DownloadRq_t rq, + cSerialAbstract &serial, + Request_t &request, + Request_t::CompletionFn_t *pCallback, + void *pUserData + ) + { + // set up the callback. + request.Completion.init(pCallback, pUserData); + + // set up the query for available data + request.QueryAvailableData.init( + [] (void *pUserData) -> int + { + cSerialAbstract * const pSerial = (cSerialAbstract *)pUserData; + + return pSerial->available(); + }, + (void *)&serial + ); + + // set up the "prompt" + request.PromptForData.init( + [] (void *pUserData) -> void + { + cSerialAbstract * const pSerial = (cSerialAbstract *)pUserData; + + pSerial->write("<", 1); + }, + (void *)&serial + ); + + // set up the transfer from source to our buffer. + request.ReadBytes.init( + [] (void *pUserData, std::uint8_t *pData, size_t nData) -> size_t + { + cSerialAbstract * const pSerial = (cSerialAbstract *)pUserData; + + return pSerial->stream().readBytes(pData, nData); + }, + (void *)&serial + ); + + // set up the request code. + request.rq = rq; + + // launch the request. + return evStart(request); + } From cf9a5ad6145574758eda64a09b867b671d7bcad5 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 3 May 2021 18:10:12 -0400 Subject: [PATCH 21/28] This is v0.21.0-5 --- src/CatenaBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CatenaBase.h b/src/CatenaBase.h index b2dfbc0..e9f8090 100644 --- a/src/CatenaBase.h +++ b/src/CatenaBase.h @@ -57,7 +57,7 @@ Copyright notice: (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) #define CATENA_ARDUINO_PLATFORM_VERSION \ - CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 4) /* v0.21.0-4 */ + CATENA_ARDUINO_PLATFORM_VERSION_CALC(0, 21, 0, 5) /* v0.21.0-5 */ #define CATENA_ARDUINO_PLATFORM_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From 42e3f40db595ae774248499f39a9f9a11689c392 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 3 May 2021 20:48:10 -0400 Subject: [PATCH 22/28] Add more download logging --- src/Catena_Download.h | 16 ++++++++++++++++ src/lib/Catena_Download.cpp | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/src/Catena_Download.h b/src/Catena_Download.h index 55c2f3c..b7d49d5 100644 --- a/src/Catena_Download.h +++ b/src/Catena_Download.h @@ -101,6 +101,22 @@ class cDownload : public cPollableObject stFinal, ///< finish up }; + /// names of the states. + static constexpr const char *getStateName(State_t s) + { + switch (s) + { + case State_t::stNoChange: return "stNoChange"; + case State_t::stInitial: return "stInitial"; + case State_t::stIdle: return "stIdle"; + case State_t::stErase: return "stErase"; + case State_t::stGetData: return "stGetData"; + case State_t::stProgram: return "stProgram"; + case State_t::stFinal: return "stFinal"; + default: return "<>"; + } + } + /// dispatch FSM /// \param [in] curState is the current state /// \param [in] fEntry is true if the state is beign entered. diff --git a/src/lib/Catena_Download.cpp b/src/lib/Catena_Download.cpp index e9d7ff4..3c5b8ad 100644 --- a/src/lib/Catena_Download.cpp +++ b/src/lib/Catena_Download.cpp @@ -144,6 +144,11 @@ cDownload::fsmDispatch( newState = State_t::stNoChange; + if (gLog.isEnabled(gLog.kTrace) && fEntry) + { + gLog.printf(gLog.kAlways, "cDownload: enter state %s(%d)\n", getStateName(curState), int(curState)); + } + switch (curState) { case State_t::stInitial: From 9553e128431303bc8897e7d96e72316aeb5f24c5 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 22:22:09 +0200 Subject: [PATCH 23/28] Fix #295: enhance cLog::DebugFlags --- src/Catena_Log.h | 55 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/Catena_Log.h b/src/Catena_Log.h index c0d7578..56d2357 100644 --- a/src/Catena_Log.h +++ b/src/Catena_Log.h @@ -27,14 +27,42 @@ class cLog public: enum DebugFlags : uint32_t { - kAlways = 0u, - kFatal = 0xFFFFFFFFu, - - kBug = 0x00000001u, - kError = 0x00000002u, - kWarning = 0x00000004u, - kTrace = 0x00000008u, - kInfo = 0x00000010u, + kAlways = 0u, ///< this mask is always enabled + kFatal = 0xFFFFFFFFu, ///< this mask indicates a fatal error, always enabled + + kBug = 0x00000001u, ///< use this for errors that indicate software bugs + kError = 0x00000002u, ///< use this for errors that indicate operational probs + kWarning = 0x00000004u, ///< use this for warnings; not an error but might need attention + kInfo = 0x00000008u, ///< use this for normal informational messages. + kVerbose = 0x00000010u, ///< use this for verbose (chatty) messages + kRfu5 = 0x00000020u, ///< reserved for future definition in library + kRfu6 = 0x00000040u, ///< reserved for future definition in library + kRfu7 = 0x00000080u, ///< reserved for future definition in library + kUser8 = 0x00000100u, ///< Reserved for use by programs and applications + kUser9 = 0x00000200u, ///< Reserved for use by programs and applications + kUser10 = 0x00000400u, ///< Reserved for use by programs and applications + kUser11 = 0x00000800u, ///< Reserved for use by programs and applications + kUser12 = 0x00001000u, ///< Reserved for use by programs and applications + kUser13 = 0x00002000u, ///< Reserved for use by programs and applications + kUser14 = 0x00004000u, ///< Reserved for use by programs and applications + kUser15 = 0x00008000u, ///< Reserved for use by programs and applications + kTrace0 = 0x00010000u, ///< "Trace": debugging bit 0 + kTrace = kTrace0, ///< Legacy name for kTrace0 + kTrace1 = 0x00020000u, ///< Library debugging trace bit 1 + kTrace2 = 0x00040000u, ///< Library debugging trace bit 2 + kTrace3 = 0x00080000u, ///< Library debugging trace bit 3 + kTrace4 = 0x00100000u, ///< Library debugging trace bit 4 + kTrace5 = 0x00200000u, ///< Library debugging trace bit 5 + kTrace6 = 0x00400000u, ///< Library debugging trace bit 6 + kTrace7 = 0x00800000u, ///< Library debugging trace bit 7 + kUserTrace8 = 0x01000000u, ///< User debugging trace bit 8 + kUserTrace9 = 0x02000000u, ///< User debugging trace bit 9 + kUserTrace10 = 0x04000000u, ///< User debugging trace bit 10 + kUserTrace11 = 0x08000000u, ///< User debugging trace bit 11 + kUserTrace12 = 0x10000000u, ///< User debugging trace bit 12 + kUserTrace13 = 0x20000000u, ///< User debugging trace bit 13 + kUserTrace14 = 0x40000000u, ///< User debugging trace bit 14 + kUserTrace15 = 0x80000000u, ///< User debugging trace bit 15 }; cLog(DebugFlags flags = DebugFlags(0)) @@ -113,6 +141,17 @@ class cLog DebugFlags m_uDebugFlags; }; +inline cLog::DebugFlags operator| (cLog::DebugFlags a, cLog::DebugFlags b) + { + return cLog::DebugFlags(std::uint32_t(a) | std::uint32_t(b)); + } + +inline cLog::DebugFlags& operator| (cLog::DebugFlags& a, cLog::DebugFlags b) + { + a = cLog::DebugFlags(std::uint32_t(a) | std::uint32_t(b)); + return a; + } + extern cLog gLog; }; // namespace McciCatena From 1ca987a7539baf5c1921bccd1bbe72eda8e31b77 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 22:22:42 +0200 Subject: [PATCH 24/28] Change to use of new debug flags in download --- src/lib/Catena_Download.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lib/Catena_Download.cpp b/src/lib/Catena_Download.cpp index 3c5b8ad..dbdfaf3 100644 --- a/src/lib/Catena_Download.cpp +++ b/src/lib/Catena_Download.cpp @@ -194,9 +194,9 @@ cDownload::fsmDispatch( // erase pages containing the region for (auto blockAddress = regionAddress; blockAddress < regionEnd; blockAddress += 64 * 1024) { - gLog.printf(gLog.kTrace, "erase block at 0x%x...", blockAddress); + gLog.printf(gLog.kVerbose, "erase block at 0x%x...", blockAddress); this->m_pFlash->eraseBlock64(blockAddress); - gLog.printf(gLog.kTrace, "\n"); + gLog.printf(gLog.kVerbose, "\n"); } } @@ -315,7 +315,7 @@ cDownload::fsmDispatch( else { this->m_fileSize = this->m_appInfo.imagesize + this->m_appInfo.authsize; - gLog.printf(gLog.kTrace, "file size: 0x%x\n", this->m_fileSize); + gLog.printf(gLog.kVerbose, "file size: 0x%x\n", this->m_fileSize); } } } @@ -349,7 +349,7 @@ cDownload::fsmDispatch( bool fOk; - gLog.printf(gLog.kTrace, "checking hash:"); + gLog.printf(gLog.kVerbose, "checking hash:"); // check the hash auto status = this->checkHash(this->m_pageAddr - this->m_fileSize, this->m_fileSize) @@ -360,7 +360,7 @@ cDownload::fsmDispatch( // if successful, set the EEPROM flag if (status == Status_t::kSuccessful) { - gLog.printf(gLog.kTrace, " OK\nSet boot flag:"); + gLog.printf(gLog.kVerbose, " OK\nSet boot flag:"); uint32_t *pUpdateFlag = this->m_pBootloaderApi->getUpdateFlagAddress(); if (pUpdateFlag == nullptr) @@ -391,17 +391,21 @@ cDownload::fsmDispatch( if (*pUpdateFlag != 0xFFFFFFFFu) { status = Status_t::kUpdateFlagSetFailure; - gLog.printf(gLog.kTrace, " fail: 0x%x\n", *pUpdateFlag); + if (! gLog.isEnabled(gLog.kVerbose)) + gLog.printf(gLog.kError, "Set boot flag:"); + gLog.printf(gLog.kVerbose | gLog.kError, " failed: 0x%x\n", *pUpdateFlag); } else { - gLog.printf(gLog.kTrace, " OK\n"); + gLog.printf(gLog.kVerbose, " OK\n"); } } } else { - gLog.printf(gLog.kTrace, " fail\n"); + if (! gLog.isEnabled(gLog.kVerbose)) + gLog.printf(gLog.kError, "check hash:"); + gLog.printf(gLog.kError, " failed\n"); } newState = this->completeRequest(status); @@ -490,6 +494,10 @@ cDownload::checkHash( if (n > sizeof(this->m_pagebuffer)) n = sizeof(this->m_pagebuffer); + // this can take awhile, so let the rest of the system have a + // peek in. + CatenaBase::pCatenaBase->poll(); + this->m_pFlash->read(i, this->m_pagebuffer, n); nRemaining = this->m_pBootloaderApi->hash_blocks(hash, this->m_pagebuffer, n); From 7df5b844bc75e95c12f305acecd9b1e65586d416 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 22:28:19 +0200 Subject: [PATCH 25/28] Adjust default log flags to be info/error/bug --- src/Catena_Log.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Catena_Log.h b/src/Catena_Log.h index 56d2357..1452955 100644 --- a/src/Catena_Log.h +++ b/src/Catena_Log.h @@ -65,7 +65,7 @@ class cLog kUserTrace15 = 0x80000000u, ///< User debugging trace bit 15 }; - cLog(DebugFlags flags = DebugFlags(0)) + cLog(DebugFlags flags = DebugFlags(kInfo | kWarning | kError | kBug)) : m_uDebugFlags(flags) {}; @@ -76,7 +76,7 @@ class cLog cLog& operator=(const cLog&&) = delete; // initialize - bool begin(DebugFlags uDebugFlags = DebugFlags(kError | kBug)) + bool begin(DebugFlags uDebugFlags = DebugFlags(kInfo | kWarning | kError | kBug)) { this->m_uDebugFlags = uDebugFlags; } From 8b5759a6d16b69c92954e0dbccc32995870750cb Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 22:36:56 +0200 Subject: [PATCH 26/28] Adjust debug logging --- src/lib/CatenaBase_GetPlatformForID.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/CatenaBase_GetPlatformForID.cpp b/src/lib/CatenaBase_GetPlatformForID.cpp index 1382b2f..14cc600 100644 --- a/src/lib/CatenaBase_GetPlatformForID.cpp +++ b/src/lib/CatenaBase_GetPlatformForID.cpp @@ -99,7 +99,7 @@ CatenaBase::GetPlatformForID( )) { gLog.printf( - cLog::DebugFlags(gLog.kInfo | gLog.kError), + gLog.kError, "Didn't find SysEUI entry; zero local copy\n" ); memset(pSysEui->b, 0, sizeof(pSysEui->b)); @@ -114,7 +114,7 @@ CatenaBase::GetPlatformForID( uint32_t OperatingFlags; gLog.printf( - cLog::DebugFlags(gLog.kInfo | gLog.kError), + gLog.kError, "Didn't find FRAM entry; search well-known\n" ); From 4d2553384e90a76d7166f9e7411913e5827f8495 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 22:39:12 +0200 Subject: [PATCH 27/28] Further adjust logging --- src/lib/CatenaBase_NetSave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/CatenaBase_NetSave.cpp b/src/lib/CatenaBase_NetSave.cpp index 75b6091..76ec178 100644 --- a/src/lib/CatenaBase_NetSave.cpp +++ b/src/lib/CatenaBase_NetSave.cpp @@ -64,7 +64,7 @@ CatenaBase::NetSaveSessionInfo( } gLog.printf( - gLog.kAlways, + gLog.kInfo, "NwkID: %08x " "DevAddr: %08x\n", Info.V1.NetID, From aabf80a956c8679159156bcba4c41b2876e9261f Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 4 May 2021 23:12:39 +0200 Subject: [PATCH 28/28] Touch up debug flags; don't override lib defaults --- src/lib/CatenaBase.cpp | 3 ++- src/lib/Catena_Download.cpp | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/CatenaBase.cpp b/src/lib/CatenaBase.cpp index c6d201c..424b155 100644 --- a/src/lib/CatenaBase.cpp +++ b/src/lib/CatenaBase.cpp @@ -55,7 +55,8 @@ CatenaBase::begin(void) { UniqueID_buffer_t CpuID; - gLog.begin(cLog::DebugFlags(gLog.kError | gLog.kBug)); + // use default debug flags + gLog.begin(); this->m_PollingEngine.begin(); diff --git a/src/lib/Catena_Download.cpp b/src/lib/Catena_Download.cpp index dbdfaf3..347719a 100644 --- a/src/lib/Catena_Download.cpp +++ b/src/lib/Catena_Download.cpp @@ -153,9 +153,6 @@ cDownload::fsmDispatch( { case State_t::stInitial: { - // for debugging - //gLog.setFlags(cLog::DebugFlags(gLog.getFlags() | gLog.kTrace)); - newState = State_t::stIdle; } break;