diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8f71f43..0000000 --- a/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/LICENSE-NORDIC b/LICENSE-NORDIC deleted file mode 100644 index 0314fd5..0000000 --- a/LICENSE-NORDIC +++ /dev/null @@ -1,40 +0,0 @@ -LicenseID: LicenseRef-Nordic-5-Clause - -ExtractedText: -Copyright (c) 2018, Nordic Semiconductor ASA - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form, except as embedded into a Nordic - Semiconductor ASA integrated circuit in a product or a software update for - such product, must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -3. Neither the name of Nordic Semiconductor ASA nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -4. This software, with or without modification, must only be used with a - Nordic Semiconductor ASA integrated circuit. - -5. Any software provided in binary form under this license must not be reverse - engineered, decompiled, modified and/or disassembled. - -THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/README.md b/README.md index 3bf29b8..268b0cb 100644 --- a/README.md +++ b/README.md @@ -1,129 +1,10 @@ -# nRF9151 Connect Kit -> Versatile Prototyping Kit based on the nRF9151 SiP supporting LTE-M/NB-IoT Worldwide, DECT NR+ and GNSS +## Setup +follow the getting started guide: +`https://wiki.makerdiary.com/nrf9151-connectkit/guides/ncs/getting-started/` -[![Current Version](https://img.shields.io/github/tag/makerdiary/nrf9151-connectkit.svg)](https://github.com/makerdiary/nrf9151-connectkit/tags) -[![Documentation](https://github.com/makerdiary/nrf9151-connectkit/actions/workflows/documentation.yml/badge.svg?branch=main)](https://wiki.makerdiary.com/nrf9151-connectkit) -[![Twister Apps & Samples](https://github.com/makerdiary/nrf9151-connectkit/actions/workflows/twister-apps-samples.yml/badge.svg?branch=main)](https://wiki.makerdiary.com/nrf9151-connectkit/guides/ncs/) -[![PRs Welcome](https://img.shields.io/badge/Contributing-appreciated-brightgreen.svg?color=informational)](https://wiki.makerdiary.com/nrf9151-connectkit/contributing/) +## Building the app +west build -b nrf9151_connectkit/nrf9151/ns nrf9151-connectkit/app/ -## Introduction - -[nRF9151 Connect Kit][nrf9151-connectkit] is a versatile prototyping kit built around the [nRF9151][nrf9151] System-in-Package (SiP) which supports LTE-M, NB-IoT, GNSS, and DECT NR+, making it suitable for global use. It has LTE bands B1-B5, B8, B12, B13, B17-B20, B25, B26, B28, B65, B66 and B85 support, Arm TrustZone CryptoCell 310, unique modem features for further power saving and ease of use. - -The design comes with an Interface MCU built using the [nRF52820][nrf52820], which enables debug, programming as well as modem firmware update, no need for any external tools. The Interface MCU also includes a USB-UART bridge for log, trace and terminal emulation, and an Interface Shell bundled with helpful commands to access the board-specific functionality. - -The board contains a [BQ25180][bq25180] I2C programmable battery charger with power path management and ultra low quiescent current, and a [TPS63901][tps63901] buck-boost converter with 75-nA quiescent current and 1.8V/3.3V configurable power supply for I/Os. - -It also has USB-C, LEDs, Buttons, nano-SIM card slot, Battery connector, U.FL receptacles for U.FL cabled LTE-M/NB-IoT/NR+ and GNSS antennas, Arm Serial Wire Debug (SWD) port and dual-row 40 pins with loose or pre-soldered headers available. - -[nRF Connect SDK][ncs] is supported, including the [Zephyr RTOS][zephyr], various samples, networking protocols, libraries, and hardware drivers, all essential for cellular IoT development. It is open source, and can be leveraged and modified to suit your specific needs. - -[![](./docs/assets/images/nrf9151_connectkit_prod_hero_reva.png)][nrf9151-connectkit] - -## Key Features - -* Nordic Semiconductor nRF9151 SiP - - - Fully integrated SiP with 64 MHz Arm Cortex-M33 and multimode LTE-M/NB-IoT modem with - DECT NR+ support and GNSS - - 700-2200 MHz LTE bands: B1-B5, B8, B12, B13, B17-B20, B25, B26, B28, B65, B66, B85 - - Power Class 5 20 dBm - - Power Class 3 23 dBm - - 1.9GHz NR+ band support - - Certified for global operation - - Dedicated programmable application processor and memory - - 1 MB Flash + 256 KB RAM - - Arm TrustZone + Arm CryptoCell 310 - - 4 x SPI/UART/TWI, PDM, I2S, PWM, ADC - -* On-board Interface MCU - - - Built using nRF52820 with 64 MHz Arm Cortex-M4, 256 KB Flash & 32 KB RAM - - Built-in CMSIS-DAP support for debug, programming as well as modem firmware update, - no need for any external tools - - USB-UART bridge for log, trace and terminal emulation - - Interface Shell with helpful commands to access the board-specific functionality - - Self-upgradable UF2 Bootloader featuring drag-and-drop programming for Interface MCU firmware update - - Open source and more features will be released gradually over time - -* BQ25180 I2C programmable Battery Charger with power path management and ultra low quiescent current -* TPS63901 buck-boost converter with 75-nA quiescent current and 1.8V/3.3V configurable power supply for I/Os -* On-board GNSS Low Noise Amplifier (LNA) with 18.2 dB gain and only 0.7 dB noise figure for improved sensitivity -* Shipped with U.FL cabled LTE-M/NB-IoT/NR+ and GNSS antennas -* 31 multi-function GPIOs (8 can be configured as ADC inputs) through edge pins -* Arm Serial Wire Debug (SWD) port through edge pins -* USB-C, LEDs, Buttons, nano-SIM card slot, Battery connector, U.FL receptacles -* Dual-row 40 pins in 55.88mm x 20.32mm (2.2" x 0.8") DIP/SMT form factor -* Available in Loose or Pre-soldered headers options -* Built on open source, supporting nRF Connect SDK and Zephyr RTOS, etc - -## Hardware Diagram - -The following figure illustrates the nRF9151 Connect Kit hardware diagram. The design is available with loose or pre-soldered pin headers. For more details, refer to the [Hardware description][hw-desc] section. - -[![](./docs/assets/images/nrf9151_connectkit_hw_diagram_front.png)][pinout-pdf] - -[![](./docs/assets/images/nrf9151_connectkit_hw_diagram_back.png)][pinout-pdf] - -## Mechanical Dimensions - -nRF9151 Connect Kit is a 4-layer chem. Gold, 55.88mm x 20.32mm (2.2" x 0.8") 1mm thick PCB with a USB Type-C port, a battery connector, a nano-SIM card slot and 40x castellated/through-hole pins. - -[![](./docs/assets/images/nrf9151_connectkit_dimensions_reva.png)][dxf-files] - -## Documentation - -We offer a comprehensive set of documentation, including getting started guides, developer guides, and code examples. These resources are designed to reduce development effort and help you achieve faster time-to-market. - -* [nRF9151 Connect Kit Documentation][wiki] -* [nRF9151 Connect Kit Product Brief][product-brief] -* [nRF9151 Connect Kit Quick Start Guide][quick-start] -* [Develop with nRF Connect SDK][ncs-guide] -* [nRF9151 Connect Kit Programming Guide][programming] -* [nRF9151 Connect Kit Pinout Rev.A][pinout-pdf] -* [nRF9151 Connect Kit Hardware Description][hw-desc] -* [nRF9151 Connect Kit Schematic Rev.A][schematic] -* [nRF9151 Connect Kit Board DXF Files Rev.A][dxf-files] -* [nRF9151 Connect Kit 3D Model Rev.A][3d-model] - -## Where to Buy - -nRF9151 Connect Kit is available on the following channels (click to go directly to the product): - -makerdiary store -Taobao -Tindie - -## Community Support - -Community support is provided via [GitHub Discussions][discussions]. We would love to have more developers contribute to this project! If you're passionate about making this project better, see our [Contributing Guidelines][contributing] for more information. - -## License - -This project is licensed under the Apache License 2.0 unless otherwise stated. For the full license text, please refer to the [LICENSE](./LICENSE) file. - -The nRF Connect SDK and its components are licensed under the 5-Clause Nordic License. See [LICENSE-NORDIC](./LICENSE-NORDIC) for further details. - -This project may include some imported or reused components that are licensed under different terms. Please refer to the license files within those components for details. - - -[nrf9151-connectkit]: https://makerdiary.com/products/nrf9151-connectkit -[nrf9151]: https://www.nordicsemi.com/Products/nRF9151 -[nrf52820]: https://www.nordicsemi.com/Products/nrf52820 -[bq25180]: https://www.ti.com/product/BQ25180 -[tps63901]: https://www.ti.com/product/TPS63901 -[ncs]: https://github.com/nrfconnect/sdk-nrf -[zephyr]: https://github.com/zephyrproject-rtos/zephyr -[hw-desc]: https://wiki.makerdiary.com/nrf9151-connectkit/hardware/ -[pinout-pdf]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connectkit-hardware-diagram_reva.pdf -[wiki]: https://wiki.makerdiary.com/nrf9151-connectkit/ -[product-brief]: https://wiki.makerdiary.com/nrf9151-connectkit/introduction/ -[quick-start]: https://wiki.makerdiary.com/nrf9151-connectkit/getting-started/ -[ncs-guide]: https://wiki.makerdiary.com/nrf9151-connectkit/guides/ncs/ -[programming]: https://wiki.makerdiary.com/nrf9151-connectkit/guides/programming/ -[schematic]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connect-kit-schematic_reva.pdf -[dxf-files]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connectkit-board-dxf_reva.zip -[3d-model]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connect-kit-3d-model_reva.step -[discussions]: https://github.com/makerdiary/nrf9151-connectkit/discussions -[contributing]: https://wiki.makerdiary.com/nrf9151-connectkit/contributing/ +## Flashing +west flash \ No newline at end of file diff --git a/README_NRF_KIT.md b/README_NRF_KIT.md new file mode 100644 index 0000000..3bf29b8 --- /dev/null +++ b/README_NRF_KIT.md @@ -0,0 +1,129 @@ +# nRF9151 Connect Kit + +> Versatile Prototyping Kit based on the nRF9151 SiP supporting LTE-M/NB-IoT Worldwide, DECT NR+ and GNSS + +[![Current Version](https://img.shields.io/github/tag/makerdiary/nrf9151-connectkit.svg)](https://github.com/makerdiary/nrf9151-connectkit/tags) +[![Documentation](https://github.com/makerdiary/nrf9151-connectkit/actions/workflows/documentation.yml/badge.svg?branch=main)](https://wiki.makerdiary.com/nrf9151-connectkit) +[![Twister Apps & Samples](https://github.com/makerdiary/nrf9151-connectkit/actions/workflows/twister-apps-samples.yml/badge.svg?branch=main)](https://wiki.makerdiary.com/nrf9151-connectkit/guides/ncs/) +[![PRs Welcome](https://img.shields.io/badge/Contributing-appreciated-brightgreen.svg?color=informational)](https://wiki.makerdiary.com/nrf9151-connectkit/contributing/) + +## Introduction + +[nRF9151 Connect Kit][nrf9151-connectkit] is a versatile prototyping kit built around the [nRF9151][nrf9151] System-in-Package (SiP) which supports LTE-M, NB-IoT, GNSS, and DECT NR+, making it suitable for global use. It has LTE bands B1-B5, B8, B12, B13, B17-B20, B25, B26, B28, B65, B66 and B85 support, Arm TrustZone CryptoCell 310, unique modem features for further power saving and ease of use. + +The design comes with an Interface MCU built using the [nRF52820][nrf52820], which enables debug, programming as well as modem firmware update, no need for any external tools. The Interface MCU also includes a USB-UART bridge for log, trace and terminal emulation, and an Interface Shell bundled with helpful commands to access the board-specific functionality. + +The board contains a [BQ25180][bq25180] I2C programmable battery charger with power path management and ultra low quiescent current, and a [TPS63901][tps63901] buck-boost converter with 75-nA quiescent current and 1.8V/3.3V configurable power supply for I/Os. + +It also has USB-C, LEDs, Buttons, nano-SIM card slot, Battery connector, U.FL receptacles for U.FL cabled LTE-M/NB-IoT/NR+ and GNSS antennas, Arm Serial Wire Debug (SWD) port and dual-row 40 pins with loose or pre-soldered headers available. + +[nRF Connect SDK][ncs] is supported, including the [Zephyr RTOS][zephyr], various samples, networking protocols, libraries, and hardware drivers, all essential for cellular IoT development. It is open source, and can be leveraged and modified to suit your specific needs. + +[![](./docs/assets/images/nrf9151_connectkit_prod_hero_reva.png)][nrf9151-connectkit] + +## Key Features + +* Nordic Semiconductor nRF9151 SiP + + - Fully integrated SiP with 64 MHz Arm Cortex-M33 and multimode LTE-M/NB-IoT modem with + DECT NR+ support and GNSS + - 700-2200 MHz LTE bands: B1-B5, B8, B12, B13, B17-B20, B25, B26, B28, B65, B66, B85 + - Power Class 5 20 dBm + - Power Class 3 23 dBm + - 1.9GHz NR+ band support + - Certified for global operation + - Dedicated programmable application processor and memory + - 1 MB Flash + 256 KB RAM + - Arm TrustZone + Arm CryptoCell 310 + - 4 x SPI/UART/TWI, PDM, I2S, PWM, ADC + +* On-board Interface MCU + + - Built using nRF52820 with 64 MHz Arm Cortex-M4, 256 KB Flash & 32 KB RAM + - Built-in CMSIS-DAP support for debug, programming as well as modem firmware update, + no need for any external tools + - USB-UART bridge for log, trace and terminal emulation + - Interface Shell with helpful commands to access the board-specific functionality + - Self-upgradable UF2 Bootloader featuring drag-and-drop programming for Interface MCU firmware update + - Open source and more features will be released gradually over time + +* BQ25180 I2C programmable Battery Charger with power path management and ultra low quiescent current +* TPS63901 buck-boost converter with 75-nA quiescent current and 1.8V/3.3V configurable power supply for I/Os +* On-board GNSS Low Noise Amplifier (LNA) with 18.2 dB gain and only 0.7 dB noise figure for improved sensitivity +* Shipped with U.FL cabled LTE-M/NB-IoT/NR+ and GNSS antennas +* 31 multi-function GPIOs (8 can be configured as ADC inputs) through edge pins +* Arm Serial Wire Debug (SWD) port through edge pins +* USB-C, LEDs, Buttons, nano-SIM card slot, Battery connector, U.FL receptacles +* Dual-row 40 pins in 55.88mm x 20.32mm (2.2" x 0.8") DIP/SMT form factor +* Available in Loose or Pre-soldered headers options +* Built on open source, supporting nRF Connect SDK and Zephyr RTOS, etc + +## Hardware Diagram + +The following figure illustrates the nRF9151 Connect Kit hardware diagram. The design is available with loose or pre-soldered pin headers. For more details, refer to the [Hardware description][hw-desc] section. + +[![](./docs/assets/images/nrf9151_connectkit_hw_diagram_front.png)][pinout-pdf] + +[![](./docs/assets/images/nrf9151_connectkit_hw_diagram_back.png)][pinout-pdf] + +## Mechanical Dimensions + +nRF9151 Connect Kit is a 4-layer chem. Gold, 55.88mm x 20.32mm (2.2" x 0.8") 1mm thick PCB with a USB Type-C port, a battery connector, a nano-SIM card slot and 40x castellated/through-hole pins. + +[![](./docs/assets/images/nrf9151_connectkit_dimensions_reva.png)][dxf-files] + +## Documentation + +We offer a comprehensive set of documentation, including getting started guides, developer guides, and code examples. These resources are designed to reduce development effort and help you achieve faster time-to-market. + +* [nRF9151 Connect Kit Documentation][wiki] +* [nRF9151 Connect Kit Product Brief][product-brief] +* [nRF9151 Connect Kit Quick Start Guide][quick-start] +* [Develop with nRF Connect SDK][ncs-guide] +* [nRF9151 Connect Kit Programming Guide][programming] +* [nRF9151 Connect Kit Pinout Rev.A][pinout-pdf] +* [nRF9151 Connect Kit Hardware Description][hw-desc] +* [nRF9151 Connect Kit Schematic Rev.A][schematic] +* [nRF9151 Connect Kit Board DXF Files Rev.A][dxf-files] +* [nRF9151 Connect Kit 3D Model Rev.A][3d-model] + +## Where to Buy + +nRF9151 Connect Kit is available on the following channels (click to go directly to the product): + +makerdiary store +Taobao +Tindie + +## Community Support + +Community support is provided via [GitHub Discussions][discussions]. We would love to have more developers contribute to this project! If you're passionate about making this project better, see our [Contributing Guidelines][contributing] for more information. + +## License + +This project is licensed under the Apache License 2.0 unless otherwise stated. For the full license text, please refer to the [LICENSE](./LICENSE) file. + +The nRF Connect SDK and its components are licensed under the 5-Clause Nordic License. See [LICENSE-NORDIC](./LICENSE-NORDIC) for further details. + +This project may include some imported or reused components that are licensed under different terms. Please refer to the license files within those components for details. + + +[nrf9151-connectkit]: https://makerdiary.com/products/nrf9151-connectkit +[nrf9151]: https://www.nordicsemi.com/Products/nRF9151 +[nrf52820]: https://www.nordicsemi.com/Products/nrf52820 +[bq25180]: https://www.ti.com/product/BQ25180 +[tps63901]: https://www.ti.com/product/TPS63901 +[ncs]: https://github.com/nrfconnect/sdk-nrf +[zephyr]: https://github.com/zephyrproject-rtos/zephyr +[hw-desc]: https://wiki.makerdiary.com/nrf9151-connectkit/hardware/ +[pinout-pdf]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connectkit-hardware-diagram_reva.pdf +[wiki]: https://wiki.makerdiary.com/nrf9151-connectkit/ +[product-brief]: https://wiki.makerdiary.com/nrf9151-connectkit/introduction/ +[quick-start]: https://wiki.makerdiary.com/nrf9151-connectkit/getting-started/ +[ncs-guide]: https://wiki.makerdiary.com/nrf9151-connectkit/guides/ncs/ +[programming]: https://wiki.makerdiary.com/nrf9151-connectkit/guides/programming/ +[schematic]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connect-kit-schematic_reva.pdf +[dxf-files]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connectkit-board-dxf_reva.zip +[3d-model]: https://wiki.makerdiary.com/nrf9151-connectkit/assets/attachments/nrf9151-connect-kit-3d-model_reva.step +[discussions]: https://github.com/makerdiary/nrf9151-connectkit/discussions +[contributing]: https://wiki.makerdiary.com/nrf9151-connectkit/contributing/ diff --git a/samples/mqtt/CMakeLists.txt b/app/CMakeLists.txt similarity index 81% rename from samples/mqtt/CMakeLists.txt rename to app/CMakeLists.txt index b7cff44..119a717 100644 --- a/samples/mqtt/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(mqtt) +project(app) # Include files that are common for all modules add_subdirectory(src/common) @@ -18,3 +18,6 @@ add_subdirectory(src/modules/sampler) add_subdirectory(src/modules/network) add_subdirectory(src/modules/transport) add_subdirectory(src/modules/error) +add_subdirectory(src/modules/camera) +add_subdirectory(src/modules/gnss) +add_subdirectory(drivers/esp32cam) diff --git a/samples/mqtt/Kconfig b/app/Kconfig similarity index 58% rename from samples/mqtt/Kconfig rename to app/Kconfig index 55747fd..6aa3e3e 100644 --- a/samples/mqtt/Kconfig +++ b/app/Kconfig @@ -4,7 +4,7 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -menu "MQTT sample" +menu "Remote guard" config MQTT_SAMPLE_PAYLOAD_CHANNEL_STRING_MAX_SIZE int "Payload maximum string size" @@ -12,11 +12,27 @@ config MQTT_SAMPLE_PAYLOAD_CHANNEL_STRING_MAX_SIZE help Maximum size of the string included messages that are sent over the payload channel. +config MQTT_SAMPLE_CAMERA_CHUNK_SIZE + int "Camera chunk size in bytes" + default 1024 + help + Size of each camera image chunk sent over MQTT. Should be 1-4 KB to balance overhead and RAM. + +config APP_LOG_LEVEL + int "log level" + default 3 + range 0 4 + help + Log level for the application. + rsource "src/modules/trigger/Kconfig.trigger" rsource "src/modules/sampler/Kconfig.sampler" rsource "src/modules/network/Kconfig.network" rsource "src/modules/transport/Kconfig.transport" rsource "src/modules/error/Kconfig.error" +rsource "src/modules/camera/Kconfig.camera" +rsource "src/modules/gnss/Kconfig.gnss" +rsource "drivers/esp32cam/Kconfig" endmenu diff --git a/samples/https_client/Kconfig.sysbuild b/app/Kconfig.sysbuild similarity index 100% rename from samples/https_client/Kconfig.sysbuild rename to app/Kconfig.sysbuild diff --git a/samples/mqtt/boards/nrf9151_connectkit_nrf9151_ns.conf b/app/boards/nrf9151_connectkit_nrf9151_ns.conf similarity index 97% rename from samples/mqtt/boards/nrf9151_connectkit_nrf9151_ns.conf rename to app/boards/nrf9151_connectkit_nrf9151_ns.conf index 57c2672..ccfe7f5 100644 --- a/samples/mqtt/boards/nrf9151_connectkit_nrf9151_ns.conf +++ b/app/boards/nrf9151_connectkit_nrf9151_ns.conf @@ -23,3 +23,4 @@ CONFIG_NET_IPV6_MLD=n # Zephyr NET Connection Manager and Connectivity layer. CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 CONFIG_NRF_MODEM_LIB_NET_IF=y +CONFIG_NEWLIB_LIBC=y diff --git a/app/boards/nrf9151_connectkit_nrf9151_ns.overlay b/app/boards/nrf9151_connectkit_nrf9151_ns.overlay new file mode 100644 index 0000000..b5f45fc --- /dev/null +++ b/app/boards/nrf9151_connectkit_nrf9151_ns.overlay @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + spi1_default: spi1_default { + group1 { + psels = , + , + ; + }; + }; + + spi1_sleep: spi1_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi1 { + status = "okay"; + compatible = "nordic,nrf-spim"; + pinctrl-0 = <&spi1_default>; + pinctrl-1 = <&spi1_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + + esp32cam: esp32cam@0 { + status = "okay"; + compatible = "esp32cam"; + reg = <0>; + spi-max-frequency = <8000000>; + spi-cpol; + spi-cpha; + }; +}; + +/ { + gpio_keys { + compatible = "gpio-keys"; + + user_button: user_button { + label = "User button (P0.25)"; + /* Assumes active-low with pull-up; adjust if wired differently. */ + gpios = <&gpio0 25 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + }; + }; + + aliases { + sw0 = &user_button; + }; +}; diff --git a/app/drivers/esp32cam/CMakeLists.txt b/app/drivers/esp32cam/CMakeLists.txt new file mode 100644 index 0000000..b7d523f --- /dev/null +++ b/app/drivers/esp32cam/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# ESP32-CAM custom SPI camera driver +# + +if(CONFIG_ESP32CAM_DRIVER) +zephyr_library() +zephyr_include_directories(.) +zephyr_library_sources(esp32cam.c) +endif() + diff --git a/app/drivers/esp32cam/Kconfig b/app/drivers/esp32cam/Kconfig new file mode 100644 index 0000000..e405eda --- /dev/null +++ b/app/drivers/esp32cam/Kconfig @@ -0,0 +1,21 @@ +# +# ESP32-CAM custom SPI camera driver +# + +menuconfig ESP32CAM_DRIVER + bool "ESP32-CAM SPI camera driver" + default y + help + Enable the custom driver bound to the esp32,cam-spi devicetree node. + +if ESP32CAM_DRIVER + +config ESP32CAM_DRIVER_LOG_LEVEL + int "ESP32-CAM driver log level" + default 3 + range 0 4 + help + Log level for the ESP32-CAM driver. + +endif # ESP32CAM_DRIVER + diff --git a/app/drivers/esp32cam/esp32cam.c b/app/drivers/esp32cam/esp32cam.c new file mode 100644 index 0000000..effce40 --- /dev/null +++ b/app/drivers/esp32cam/esp32cam.c @@ -0,0 +1,285 @@ +/* + * ESP32-CAM custom SPI camera driver + * + * This driver binds to the esp32,cam-spi devicetree node and exposes + * a Zephyr device that encapsulates the SPI connection to the external + * ESP32-CAM module, providing high-level camera operations. + */ + + #include + #include + #include + #include + + #include "esp32cam.h" + + LOG_MODULE_REGISTER(esp32cam_drv, CONFIG_ESP32CAM_DRIVER_LOG_LEVEL); + + #define DT_DRV_COMPAT esp32_cam_spi + + /* ESP32-CAM command opcodes */ + #define ESP32CAM_CMD_ON 0x01 + #define ESP32CAM_CMD_OFF 0x02 + #define ESP32CAM_CMD_CAPTURE 0x03 + #define ESP32CAM_CMD_FLASH_ON 0x04 + #define ESP32CAM_CMD_FLASH_OFF 0x05 + + /* ESP32-CAM status codes */ + #define ESP32CAM_STATUS_NOT_RESPONDING 0x00 + #define ESP32CAM_STATUS_ACK 0x01 + #define ESP32CAM_STATUS_ERR 0x02 + #define ESP32CAM_STATUS_CAMERA_ACCESS_FAILED 0x03 + + struct esp32cam_config { + struct spi_dt_spec spi; + }; + + static int esp32cam_init(const struct device *dev) + { + const struct esp32cam_config *cfg = dev->config; + + if (!spi_is_ready_dt(&cfg->spi)) { + LOG_ERR("Underlying SPI bus/device not ready"); + return -ENODEV; + } + + LOG_INF("ESP32-CAM driver initialized"); + return 0; + } + + #define ESP32CAM_INIT(inst) \ + static const struct esp32cam_config esp32cam_cfg_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | \ + SPI_TRANSFER_MSB, 0), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &esp32cam_init, NULL, NULL, \ + &esp32cam_cfg_##inst, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); + + DT_INST_FOREACH_STATUS_OKAY(ESP32CAM_INIT) + + static inline const struct esp32cam_config *esp32cam_get_cfg(const struct device *dev) + { + return dev->config; + } + + /* Low-level SPI helpers */ + + static int esp32cam_spi_send_cmd(const struct esp32cam_config *cfg, + uint8_t cmd, uint8_t *status) + { + int ret; + uint8_t tx_buf[1] = { cmd }; + uint8_t rx_buf[1] = { 0 }; + + const struct spi_buf tx_bufs[] = { + { + .buf = tx_buf, + .len = sizeof(tx_buf), + }, + }; + const struct spi_buf rx_bufs[] = { + { + .buf = rx_buf, + .len = sizeof(rx_buf), + }, + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = 1, + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = 1, + }; + + if (!spi_is_ready_dt(&cfg->spi)) { + LOG_ERR("SPI device not ready"); + return -ENODEV; + } + + ret = spi_transceive_dt(&cfg->spi, &tx, &rx); + if (ret) { + LOG_ERR("SPI transceive failed: %d", ret); + return ret; + } + + if (status) { + *status = rx_buf[0]; + if (*status == ESP32CAM_STATUS_NOT_RESPONDING) { + LOG_ERR("ESP32-CAM not responding (status = 0x00)"); + return -ENODEV; + } + } + + return 0; + } + + static int esp32cam_spi_read(const struct esp32cam_config *cfg, + uint8_t *data, size_t len) + { + int ret; + const struct spi_buf rx_bufs[] = { + { + .buf = data, + .len = len, + }, + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = 1, + }; + + if (!spi_is_ready_dt(&cfg->spi)) { + LOG_ERR("SPI device not ready"); + return -ENODEV; + } + + ret = spi_read_dt(&cfg->spi, &rx); + if (ret) { + LOG_ERR("SPI read failed: %d", ret); + return ret; + } + + return 0; + } + + /* Public API */ + + const struct device *esp32cam_get_device(void) + { + const struct device *dev = DEVICE_DT_GET_ANY(esp32_cam_spi); + + if (dev == NULL) { + LOG_ERR("No ESP32-CAM device found"); + } + + return dev; + } + + int esp32cam_turn_on(const struct device *dev) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + uint8_t status = 0; + int ret = esp32cam_spi_send_cmd(cfg, ESP32CAM_CMD_ON, &status); + + if (ret) { + return ret; + } + + if (status != ESP32CAM_STATUS_ACK) { + LOG_ERR("TURN_ON returned status 0x%02x", status); + return -EIO; + } + + return 0; + } + + int esp32cam_turn_off(const struct device *dev) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + uint8_t status = 0; + int ret = esp32cam_spi_send_cmd(cfg, ESP32CAM_CMD_OFF, &status); + + if (ret) { + return ret; + } + + if (status != ESP32CAM_STATUS_ACK) { + LOG_ERR("TURN_OFF returned status 0x%02x", status); + return -EIO; + } + + return 0; + } + + int esp32cam_flash_on(const struct device *dev) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + uint8_t status = 0; + int ret = esp32cam_spi_send_cmd(cfg, ESP32CAM_CMD_FLASH_ON, &status); + + if (ret) { + return ret; + } + + if (status != ESP32CAM_STATUS_ACK) { + LOG_ERR("FLASH_ON returned status 0x%02x", status); + return -EIO; + } + + return 0; + } + + int esp32cam_flash_off(const struct device *dev) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + uint8_t status = 0; + int ret = esp32cam_spi_send_cmd(cfg, ESP32CAM_CMD_FLASH_OFF, &status); + + if (ret) { + return ret; + } + + if (status != ESP32CAM_STATUS_ACK) { + LOG_ERR("FLASH_OFF returned status 0x%02x", status); + return -EIO; + } + + return 0; + } + + int esp32cam_capture_length(const struct device *dev, uint32_t *image_length) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + uint8_t status = 0; + int ret; + uint8_t length_buf[4]; + + if (image_length == NULL) { + return -EINVAL; + } + + ret = esp32cam_spi_send_cmd(cfg, ESP32CAM_CMD_CAPTURE, &status); + if (ret) { + return ret; + } + + if (status == ESP32CAM_STATUS_CAMERA_ACCESS_FAILED) { + LOG_ERR("ESP32 camera access failed"); + return -EIO; + } else if (status != ESP32CAM_STATUS_ACK) { + LOG_ERR("CAPTURE returned status 0x%02x", status); + return -EIO; + } + + ret = esp32cam_spi_read(cfg, length_buf, sizeof(length_buf)); + if (ret) { + LOG_ERR("Failed to read image length: %d", ret); + return ret; + } + + *image_length = (length_buf[3] << 24) | + (length_buf[2] << 16) | + (length_buf[1] << 8) | + length_buf[0]; + + if (*image_length == 0 || *image_length > 1024 * 1024) { + LOG_ERR("Invalid image length: %u", *image_length); + return -EINVAL; + } + + LOG_INF("Image length: %u bytes", *image_length); + return 0; + } + + int esp32cam_capture_read(const struct device *dev, uint8_t *buf, size_t len) + { + const struct esp32cam_config *cfg = esp32cam_get_cfg(dev); + + if (buf == NULL || len == 0) { + return -EINVAL; + } + + return esp32cam_spi_read(cfg, buf, len); + } \ No newline at end of file diff --git a/app/drivers/esp32cam/esp32cam.h b/app/drivers/esp32cam/esp32cam.h new file mode 100644 index 0000000..de8fbc3 --- /dev/null +++ b/app/drivers/esp32cam/esp32cam.h @@ -0,0 +1,31 @@ +/* + * ESP32-CAM high-level driver API + * + * This header exposes high-level operations (power, flash, capture) + * implemented by the ESP32-CAM driver bound to the esp32,cam-spi node. + */ + +#ifndef ESP32CAM_H__ +#define ESP32CAM_H__ + +#include +#include + +/* Get the ESP32-CAM device instance (first esp32,cam-spi node) */ +const struct device *esp32cam_get_device(void); + +/* High-level control APIs */ +int esp32cam_turn_on(const struct device *dev); +int esp32cam_turn_off(const struct device *dev); +int esp32cam_flash_on(const struct device *dev); +int esp32cam_flash_off(const struct device *dev); + +/* Capture APIs: + * - esp32cam_capture_length: trigger capture and return total image length + * - esp32cam_capture_read: read 'len' bytes from the capture stream + */ +int esp32cam_capture_length(const struct device *dev, uint32_t *image_length); +int esp32cam_capture_read(const struct device *dev, uint8_t *buf, size_t len); + +#endif /* ESP32CAM_H__ */ + diff --git a/samples/mqtt/overlay-tls-nrf91.conf b/app/overlay-tls-nrf91.conf similarity index 100% rename from samples/mqtt/overlay-tls-nrf91.conf rename to app/overlay-tls-nrf91.conf diff --git a/samples/mqtt/prj.conf b/app/prj.conf similarity index 55% rename from samples/mqtt/prj.conf rename to app/prj.conf index 04ec50b..b199458 100644 --- a/samples/mqtt/prj.conf +++ b/app/prj.conf @@ -5,11 +5,17 @@ # # Common configurations for all boards - +CONFIG_NEWLIB_LIBC=y # General CONFIG_HW_ID_LIBRARY=y CONFIG_ASSERT=y -CONFIG_HEAP_MEM_POOL_SIZE=1280 +CONFIG_HEAP_MEM_POOL_SIZE=2048 + +CONFIG_PWM=y +CONFIG_GPIO=y + +# SPI for camera +CONFIG_SPI=y # Logging CONFIG_LOG=y @@ -33,3 +39,16 @@ CONFIG_SMF=y # MQTT CONFIG_MQTT_HELPER=y CONFIG_MQTT_CLEAN_SESSION=y +CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME="broker.hivemq.com" + +CONFIG_LTE_NETWORK_MODE_LTE_M_GPS=y +CONFIG_LTE_NETWORK_MODE_NBIOT=n + +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192 + +CONFIG_MQTT_SAMPLE_CAMERA=n +CONFIG_ESP32CAM_DRIVER=n +CONFIG_MQTT_SAMPLE_GNSS=y + +CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE=y \ No newline at end of file diff --git a/samples/mqtt/sample.yaml b/app/sample.yaml similarity index 100% rename from samples/mqtt/sample.yaml rename to app/sample.yaml diff --git a/samples/mqtt/src/common/CMakeLists.txt b/app/src/common/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/common/CMakeLists.txt rename to app/src/common/CMakeLists.txt diff --git a/samples/mqtt/src/common/message_channel.c b/app/src/common/message_channel.c similarity index 50% rename from samples/mqtt/src/common/message_channel.c rename to app/src/common/message_channel.c index 3ddfe8b..91b021c 100644 --- a/samples/mqtt/src/common/message_channel.c +++ b/app/src/common/message_channel.c @@ -41,3 +41,51 @@ ZBUS_CHAN_DEFINE(FATAL_ERROR_CHAN, ZBUS_OBSERVERS(error), ZBUS_MSG_INIT(0) ); + +ZBUS_CHAN_DEFINE(CAMERA_CMD_CHAN, + enum camera_cmd, + NULL, + NULL, + ZBUS_OBSERVERS(camera), + ZBUS_MSG_INIT(CAMERA_CMD_TAKE_PHOTO) +); + +ZBUS_CHAN_DEFINE(CAMERA_CHUNK_CHAN, + struct camera_chunk, + NULL, + NULL, + ZBUS_OBSERVERS(transport), + ZBUS_MSG_INIT(0) +); + +ZBUS_CHAN_DEFINE(CAMERA_ERROR_CHAN, + enum camera_error_type, + NULL, + NULL, + ZBUS_OBSERVERS(transport), + ZBUS_MSG_INIT(CAMERA_ERROR_NRF_INTERNAL) +); + +ZBUS_CHAN_DEFINE(GNSS_CMD_CHAN, + enum gnss_cmd, + NULL, + NULL, + ZBUS_OBSERVERS(gnss), + ZBUS_MSG_INIT(GNSS_CMD_GET_LOCATION) +); + +ZBUS_CHAN_DEFINE(GPS_DATA_CHAN, + struct gps_data, + NULL, + NULL, + ZBUS_OBSERVERS(transport), + ZBUS_MSG_INIT(0) +); + +ZBUS_CHAN_DEFINE(GNSS_ERROR_CHAN, + enum gnss_error_type, + NULL, + NULL, + ZBUS_OBSERVERS(transport), + ZBUS_MSG_INIT(GNSS_ERROR_NRF_INTERNAL) +); diff --git a/samples/mqtt/src/common/message_channel.h b/app/src/common/message_channel.h similarity index 50% rename from samples/mqtt/src/common/message_channel.h rename to app/src/common/message_channel.h index 239f547..870e179 100644 --- a/samples/mqtt/src/common/message_channel.h +++ b/app/src/common/message_channel.h @@ -35,7 +35,54 @@ enum network_status { NETWORK_CONNECTED, }; -ZBUS_CHAN_DECLARE(TRIGGER_CHAN, PAYLOAD_CHAN, NETWORK_CHAN, FATAL_ERROR_CHAN); +enum camera_cmd { + CAMERA_CMD_TAKE_PHOTO, + CAMERA_CMD_FLASH_ON, + CAMERA_CMD_FLASH_OFF, + CAMERA_CMD_CAMERA_ON, + CAMERA_CMD_CAMERA_OFF, +}; + +enum camera_error_type { + CAMERA_ERROR_NRF_INTERNAL, + CAMERA_ERROR_ESP32_NOT_RESPONDING, + CAMERA_ERROR_ESP32_CAMERA_ACCESS_FAILED, +}; + +struct camera_chunk { + uint8_t data[CONFIG_MQTT_SAMPLE_CAMERA_CHUNK_SIZE]; + uint32_t size; + uint32_t sequence; + uint32_t total_chunks; + uint32_t total_size; +}; + +enum gnss_cmd { + GNSS_CMD_GET_LOCATION, +}; + +enum gnss_error_type { + GNSS_ERROR_NRF_INTERNAL, + GNSS_ERROR_INIT_FAILED, + GNSS_ERROR_ACTIVATION_FAILED, + GNSS_ERROR_EVENT_HANDLER_FAILED, + GNSS_ERROR_CONFIG_FAILED, + GNSS_ERROR_START_FAILED, + GNSS_ERROR_STOP_FAILED, + GNSS_ERROR_TIMEOUT, + GNSS_ERROR_INVALID_FIX, + GNSS_ERROR_PVT_READ_FAILED, +}; + +struct gps_data { + double latitude; + double longitude; + float accuracy; +}; + +ZBUS_CHAN_DECLARE(TRIGGER_CHAN, PAYLOAD_CHAN, NETWORK_CHAN, FATAL_ERROR_CHAN, + CAMERA_CMD_CHAN, CAMERA_CHUNK_CHAN, CAMERA_ERROR_CHAN, + GNSS_CMD_CHAN, GPS_DATA_CHAN, GNSS_ERROR_CHAN); #ifdef __cplusplus } diff --git a/app/src/modules/camera/CMakeLists.txt b/app/src/modules/camera/CMakeLists.txt new file mode 100644 index 0000000..26d275f --- /dev/null +++ b/app/src/modules/camera/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +if(CONFIG_MQTT_SAMPLE_CAMERA) +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera.c) +endif() + +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera_stub.c) diff --git a/app/src/modules/camera/Kconfig.camera b/app/src/modules/camera/Kconfig.camera new file mode 100644 index 0000000..125619d --- /dev/null +++ b/app/src/modules/camera/Kconfig.camera @@ -0,0 +1,27 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menuconfig MQTT_SAMPLE_CAMERA + bool "Enable camera module" + default y + help + Enable the camera module for ESP32-CAM communication over SPI. + +if MQTT_SAMPLE_CAMERA + +config MQTT_SAMPLE_CAMERA_THREAD_STACK_SIZE + int "Camera module thread stack size" + default 2048 + help + Stack size for the camera module thread. + +config MQTT_SAMPLE_CAMERA_MESSAGE_QUEUE_SIZE + int "Camera module message queue size" + default 10 + help + Size of the message queue for the camera module. + +endif # MQTT_SAMPLE_CAMERA diff --git a/app/src/modules/camera/camera.c b/app/src/modules/camera/camera.c new file mode 100644 index 0000000..b1fee2a --- /dev/null +++ b/app/src/modules/camera/camera.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include + +#include "message_channel.h" +#include "esp32cam.h" + +/* Register log module */ +LOG_MODULE_REGISTER(camera, CONFIG_APP_LOG_LEVEL); + +/* Register subscriber */ +ZBUS_SUBSCRIBER_DEFINE(camera, CONFIG_MQTT_SAMPLE_CAMERA_MESSAGE_QUEUE_SIZE); + +static enum camera_error_type map_esp32cam_error(int ret) +{ + if (ret == -ENODEV) { + return CAMERA_ERROR_ESP32_NOT_RESPONDING; + } else if (ret == -EIO) { + return CAMERA_ERROR_ESP32_CAMERA_ACCESS_FAILED; + } else { + return CAMERA_ERROR_NRF_INTERNAL; + } +} + +/* Handle camera command via esp32cam driver */ +static int handle_camera_cmd(const struct device *esp32cam_dev, + enum camera_cmd cmd) +{ + int ret; + + switch (cmd) { + case CAMERA_CMD_CAMERA_ON: + ret = esp32cam_turn_on(esp32cam_dev); + if (ret) { + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + } + return ret; + + case CAMERA_CMD_CAMERA_OFF: + ret = esp32cam_turn_off(esp32cam_dev); + if (ret) { + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + } + return ret; + + case CAMERA_CMD_FLASH_ON: + ret = esp32cam_flash_on(esp32cam_dev); + if (ret) { + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + } + return ret; + + case CAMERA_CMD_FLASH_OFF: + ret = esp32cam_flash_off(esp32cam_dev); + if (ret) { + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + } + return ret; + + case CAMERA_CMD_TAKE_PHOTO: { + uint32_t image_length = 0; + + ret = esp32cam_capture_length(esp32cam_dev, &image_length); + if (ret) { + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + return ret; + } + + uint32_t chunk_size = CONFIG_MQTT_SAMPLE_CAMERA_CHUNK_SIZE; + uint32_t total_chunks = (image_length + chunk_size - 1) / chunk_size; + + uint32_t remaining = image_length; + uint32_t sequence = 0; + uint8_t *read_buf = k_malloc(chunk_size); + if (!read_buf) { + LOG_ERR("Failed to allocate read buffer"); + enum camera_error_type error = CAMERA_ERROR_NRF_INTERNAL; + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + return -ENOMEM; + } + + while (remaining > 0) { + uint32_t to_read = (remaining > chunk_size) ? chunk_size : remaining; + + ret = esp32cam_capture_read(esp32cam_dev, read_buf, to_read); + if (ret) { + LOG_ERR("Failed to read image data: %d", ret); + k_free(read_buf); + enum camera_error_type error = map_esp32cam_error(ret); + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + return ret; + } + + struct camera_chunk chunk; + memcpy(chunk.data, read_buf, to_read); + chunk.size = to_read; + chunk.sequence = sequence; + chunk.total_chunks = total_chunks; + chunk.total_size = image_length; + + ret = zbus_chan_pub(&CAMERA_CHUNK_CHAN, &chunk, K_SECONDS(1)); + if (ret) { + LOG_ERR("Failed to publish chunk: %d", ret); + k_free(read_buf); + enum camera_error_type error = CAMERA_ERROR_NRF_INTERNAL; + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + return ret; + } + + LOG_DBG("Published chunk %u/%u (%u bytes)", + sequence + 1, total_chunks, to_read); + remaining -= to_read; + sequence++; + } + + k_free(read_buf); + LOG_INF("Image capture complete: %u chunks", total_chunks); + return 0; + } + + default: + LOG_ERR("Unknown camera command: %d", cmd); + return -EINVAL; + } +} + +/* Camera task */ +static void camera_task(void) +{ + int err; + const struct zbus_channel *chan; + enum camera_cmd cmd; + + const struct device *esp32cam_dev = esp32cam_get_device(); + if (esp32cam_dev == NULL || !device_is_ready(esp32cam_dev)) { + LOG_ERR("ESP32-CAM driver not ready"); + enum camera_error_type error = CAMERA_ERROR_NRF_INTERNAL; + zbus_chan_pub(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + return; + } + + LOG_INF("Camera module initialized"); + + while (!zbus_sub_wait(&camera, &chan, K_FOREVER)) { + if (chan == &CAMERA_CMD_CHAN) { + err = zbus_chan_read(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + continue; + } + + LOG_INF("Received camera command: %d", cmd); + err = handle_camera_cmd(esp32cam_dev, cmd); + if (err) { + LOG_ERR("Failed to handle camera command: %d", err); + } + } + } +} + +K_THREAD_DEFINE(camera_task_id, + CONFIG_MQTT_SAMPLE_CAMERA_THREAD_STACK_SIZE, + camera_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/app/src/modules/camera/camera_stub.c b/app/src/modules/camera/camera_stub.c new file mode 100644 index 0000000..f12a24e --- /dev/null +++ b/app/src/modules/camera/camera_stub.c @@ -0,0 +1,10 @@ +#include +#include "message_channel.h" + +#if !IS_ENABLED(CONFIG_MQTT_SAMPLE_CAMERA) +/* Minimal zbus subscriber stub to satisfy CAMERA_CMD_CHAN observers + * when the camera module is disabled. + */ +ZBUS_SUBSCRIBER_DEFINE(camera, 1); +#endif + diff --git a/samples/mqtt/src/modules/error/CMakeLists.txt b/app/src/modules/error/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/error/CMakeLists.txt rename to app/src/modules/error/CMakeLists.txt diff --git a/samples/mqtt/src/modules/error/Kconfig.error b/app/src/modules/error/Kconfig.error similarity index 100% rename from samples/mqtt/src/modules/error/Kconfig.error rename to app/src/modules/error/Kconfig.error diff --git a/samples/mqtt/src/modules/error/error.c b/app/src/modules/error/error.c similarity index 91% rename from samples/mqtt/src/modules/error/error.c rename to app/src/modules/error/error.c index 9f0aa97..cc1d5c3 100644 --- a/samples/mqtt/src/modules/error/error.c +++ b/app/src/modules/error/error.c @@ -11,7 +11,7 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(error, CONFIG_MQTT_SAMPLE_ERROR_LOG_LEVEL); +LOG_MODULE_REGISTER(error, CONFIG_APP_LOG_LEVEL); void error_callback(const struct zbus_channel *chan) { diff --git a/samples/https_client/overlay-pdn-nrf91-ipv4.conf b/app/src/modules/gnss/CMakeLists.txt similarity index 62% rename from samples/https_client/overlay-pdn-nrf91-ipv4.conf rename to app/src/modules/gnss/CMakeLists.txt index 2506124..0640bcb 100644 --- a/samples/https_client/overlay-pdn-nrf91-ipv4.conf +++ b/app/src/modules/gnss/CMakeLists.txt @@ -4,5 +4,4 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -CONFIG_PDN_DEFAULTS_OVERRIDE=y -CONFIG_PDN_DEFAULT_FAM_IPV4=y +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/gnss.c) diff --git a/app/src/modules/gnss/Kconfig.gnss b/app/src/modules/gnss/Kconfig.gnss new file mode 100644 index 0000000..7931893 --- /dev/null +++ b/app/src/modules/gnss/Kconfig.gnss @@ -0,0 +1,38 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menuconfig MQTT_SAMPLE_GNSS + bool "Enable GNSS module" + default y + help + Enable the GNSS module for GPS location tracking. + +if MQTT_SAMPLE_GNSS + +config MQTT_SAMPLE_GNSS_THREAD_STACK_SIZE + int "GNSS module thread stack size" + default 4096 + help + Stack size for the GNSS module thread. + +config MQTT_SAMPLE_GNSS_MESSAGE_QUEUE_SIZE + int "GNSS module message queue size" + default 10 + help + Size of the message queue for the GNSS module. + +config MQTT_SAMPLE_GNSS_FIX_TIMEOUT + int "GNSS fix timeout in seconds" + default 120 + range 10 600 + help + Maximum time to wait for a GPS fix before timing out. + +endif # MQTT_SAMPLE_GNSS + +module = MQTT_SAMPLE_GNSS +module-str = GNSS +source "subsys/logging/Kconfig.template.log_config" diff --git a/app/src/modules/gnss/gnss.c b/app/src/modules/gnss/gnss.c new file mode 100644 index 0000000..29446df --- /dev/null +++ b/app/src/modules/gnss/gnss.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "message_channel.h" + +/* Register log module */ +LOG_MODULE_REGISTER(gnss, CONFIG_APP_LOG_LEVEL); + +/* Register subscriber */ +ZBUS_SUBSCRIBER_DEFINE(gnss, CONFIG_MQTT_SAMPLE_GNSS_MESSAGE_QUEUE_SIZE); + +/* GNSS state */ +static bool gnss_initialized = false; +static bool gnss_running = false; +static struct nrf_modem_gnss_pvt_data_frame last_pvt; +static K_SEM_DEFINE(pvt_data_sem, 0, 1); + +/* Forward declaration */ +static void publish_gnss_error(enum gnss_error_type error); + +/* GNSS event handler */ +static void gnss_event_handler(int event) +{ + int retval; + + switch (event) { + case NRF_MODEM_GNSS_EVT_PVT: + retval = nrf_modem_gnss_read(&last_pvt, sizeof(last_pvt), NRF_MODEM_GNSS_DATA_PVT); + if (retval == 0) { + k_sem_give(&pvt_data_sem); + } else { + LOG_ERR("Failed to read PVT data: %d", retval); + publish_gnss_error(GNSS_ERROR_PVT_READ_FAILED); + } + break; + + case NRF_MODEM_GNSS_EVT_FIX: + /* Fix obtained, will read PVT data and stop GNSS */ + LOG_INF("GNSS fix obtained"); + break; + + default: + break; + } +} + +/* Helper function to publish GNSS error */ +static void publish_gnss_error(enum gnss_error_type error) +{ + int err = zbus_chan_pub(&GNSS_ERROR_CHAN, &error, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish GNSS error: %d", err); + } +} + +/* Initialize GNSS */ +static int gnss_init(void) +{ + int err; + + if (gnss_initialized) { + return 0; + } + + /* Enable GNSS functional mode */ + err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS); + if (err) { + LOG_ERR("Failed to activate GNSS functional mode: %d", err); + publish_gnss_error(GNSS_ERROR_ACTIVATION_FAILED); + return err; + } + + /* Set GNSS event handler */ + err = nrf_modem_gnss_event_handler_set(gnss_event_handler); + if (err) { + LOG_ERR("Failed to set GNSS event handler: %d", err); + publish_gnss_error(GNSS_ERROR_EVENT_HANDLER_FAILED); + return err; + } + + /* Set use case */ + uint8_t use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START; + err = nrf_modem_gnss_use_case_set(use_case); + if (err) { + LOG_WRN("Failed to set GNSS use case: %d", err); + /* Non-critical, don't publish error */ + } + + /* Set power saving mode for low power */ + uint8_t power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_POWER; + err = nrf_modem_gnss_power_mode_set(power_mode); + if (err) { + LOG_ERR("Failed to set GNSS power saving mode: %d", err); + publish_gnss_error(GNSS_ERROR_CONFIG_FAILED); + return err; + } + + gnss_initialized = true; + LOG_INF("GNSS initialized"); + + return 0; +} + +/* Start GNSS for single fix */ +static int gnss_start_single_fix(void) +{ + int err; + + if (!gnss_initialized) { + err = gnss_init(); + if (err) { + return err; + } + } + + if (gnss_running) { + LOG_WRN("GNSS already running"); + return 0; + } + + /* Configure for single fix mode */ + err = nrf_modem_gnss_fix_retry_set(CONFIG_MQTT_SAMPLE_GNSS_FIX_TIMEOUT); + if (err) { + LOG_ERR("Failed to set GNSS fix retry: %d", err); + publish_gnss_error(GNSS_ERROR_CONFIG_FAILED); + return err; + } + + err = nrf_modem_gnss_fix_interval_set(0); + if (err) { + LOG_ERR("Failed to set GNSS fix interval: %d", err); + publish_gnss_error(GNSS_ERROR_CONFIG_FAILED); + return err; + } + + /* Start GNSS */ + err = nrf_modem_gnss_start(); + if (err) { + LOG_ERR("Failed to start GNSS: %d", err); + publish_gnss_error(GNSS_ERROR_START_FAILED); + return err; + } + + gnss_running = true; + LOG_INF("GNSS started for single fix"); + + return 0; +} + +/* Stop GNSS */ +static int gnss_stop(void) +{ + int err; + + if (!gnss_running) { + return 0; + } + + err = nrf_modem_gnss_stop(); + if (err) { + LOG_ERR("Failed to stop GNSS: %d", err); + publish_gnss_error(GNSS_ERROR_STOP_FAILED); + return err; + } + + gnss_running = false; + LOG_INF("GNSS stopped"); + + return 0; +} + +/* Handle get location command */ +static int handle_get_location(void) +{ + int err; + struct gps_data gps; + int64_t deadline_ms = k_uptime_get() + + (int64_t)K_SECONDS(CONFIG_MQTT_SAMPLE_GNSS_FIX_TIMEOUT).ticks; + + LOG_INF("Handling get location command"); + + err = gnss_start_single_fix(); + if (err) { + LOG_ERR("Failed to start GNSS: %d", err); + /* Error already published in gnss_start_single_fix */ + return err; + } + + /* Wait for a valid fix (PVT frames can arrive before FIX_VALID is set). */ + while (true) { + int64_t now_ms = k_uptime_get(); + int64_t remaining_ms = deadline_ms - now_ms; + + if (remaining_ms <= 0) { + LOG_ERR("Timeout waiting for GPS fix"); + gnss_stop(); + publish_gnss_error(GNSS_ERROR_TIMEOUT); + return -ETIMEDOUT; + } + + err = k_sem_take(&pvt_data_sem, K_MSEC(remaining_ms)); + if (err) { + LOG_ERR("Timeout waiting for GPS fix"); + gnss_stop(); + publish_gnss_error(GNSS_ERROR_TIMEOUT); + return -ETIMEDOUT; + } + + if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { + break; + } + + LOG_WRN("GPS fix not valid yet (flags=0x%08x), waiting...", last_pvt.flags); + } + + /* Extract GPS data */ + gps.latitude = last_pvt.latitude; + gps.longitude = last_pvt.longitude; + gps.accuracy = (float)last_pvt.accuracy; + + LOG_INF("GPS fix obtained: lat=%d.%06d, lon=%d.%06d, accuracy=%d.%01d m", + (int)gps.latitude, abs((int)(gps.latitude * 1000000) % 1000000), + (int)gps.longitude, abs((int)(gps.longitude * 1000000) % 1000000), + (int)gps.accuracy, abs((int)(gps.accuracy * 10) % 10)); + + /* Stop GNSS to save power */ + gnss_stop(); + + /* Publish GPS data */ + err = zbus_chan_pub(&GPS_DATA_CHAN, &gps, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish GPS data: %d", err); + return err; + } + + return 0; +} + +/* GNSS task */ +static void gnss_task(void) +{ + int err; + const struct zbus_channel *chan; + enum gnss_cmd cmd; + + LOG_INF("GNSS module initialized"); + + while (!zbus_sub_wait(&gnss, &chan, K_FOREVER)) { + if (chan == &GNSS_CMD_CHAN) { + err = zbus_chan_read(&GNSS_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + continue; + } + + LOG_INF("Received GNSS command: %d", cmd); + + switch (cmd) { + case GNSS_CMD_GET_LOCATION: + err = handle_get_location(); + if (err) { + LOG_ERR("Failed to get location: %d", err); + } + break; + + default: + LOG_ERR("Unknown GNSS command: %d", cmd); + break; + } + } + } +} + +K_THREAD_DEFINE(gnss_task_id, + CONFIG_MQTT_SAMPLE_GNSS_THREAD_STACK_SIZE, + gnss_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/samples/mqtt/src/modules/network/CMakeLists.txt b/app/src/modules/network/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/network/CMakeLists.txt rename to app/src/modules/network/CMakeLists.txt diff --git a/samples/mqtt/src/modules/network/Kconfig.network b/app/src/modules/network/Kconfig.network similarity index 82% rename from samples/mqtt/src/modules/network/Kconfig.network rename to app/src/modules/network/Kconfig.network index 0fb21f2..512246c 100644 --- a/samples/mqtt/src/modules/network/Kconfig.network +++ b/app/src/modules/network/Kconfig.network @@ -5,7 +5,6 @@ # menu "Network" - depends on NRF_MODEM_LIB_NET_IF || WIFI_NRF70 || BOARD_NATIVE_SIM config MQTT_SAMPLE_NETWORK_THREAD_STACK_SIZE int "Thread stack size" diff --git a/samples/mqtt/src/modules/network/network.c b/app/src/modules/network/network.c similarity index 97% rename from samples/mqtt/src/modules/network/network.c rename to app/src/modules/network/network.c index 8ced016..021d189 100644 --- a/samples/mqtt/src/modules/network/network.c +++ b/app/src/modules/network/network.c @@ -13,7 +13,7 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(network, CONFIG_MQTT_SAMPLE_NETWORK_LOG_LEVEL); +LOG_MODULE_REGISTER(network, CONFIG_APP_LOG_LEVEL); /* This module does not subscribe to any channels */ diff --git a/samples/mqtt/src/modules/sampler/CMakeLists.txt b/app/src/modules/sampler/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/sampler/CMakeLists.txt rename to app/src/modules/sampler/CMakeLists.txt diff --git a/samples/mqtt/src/modules/sampler/Kconfig.sampler b/app/src/modules/sampler/Kconfig.sampler similarity index 100% rename from samples/mqtt/src/modules/sampler/Kconfig.sampler rename to app/src/modules/sampler/Kconfig.sampler diff --git a/samples/mqtt/src/modules/sampler/sampler.c b/app/src/modules/sampler/sampler.c similarity index 95% rename from samples/mqtt/src/modules/sampler/sampler.c rename to app/src/modules/sampler/sampler.c index e1305c9..3c1fe30 100644 --- a/samples/mqtt/src/modules/sampler/sampler.c +++ b/app/src/modules/sampler/sampler.c @@ -13,7 +13,7 @@ #define FORMAT_STRING "Hello MQTT! Current uptime is: %d" /* Register log module */ -LOG_MODULE_REGISTER(sampler, CONFIG_MQTT_SAMPLE_SAMPLER_LOG_LEVEL); +LOG_MODULE_REGISTER(sampler, CONFIG_APP_LOG_LEVEL); /* Register subscriber */ ZBUS_SUBSCRIBER_DEFINE(sampler, CONFIG_MQTT_SAMPLE_SAMPLER_MESSAGE_QUEUE_SIZE); diff --git a/samples/mqtt/src/modules/transport/CMakeLists.txt b/app/src/modules/transport/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/transport/CMakeLists.txt rename to app/src/modules/transport/CMakeLists.txt diff --git a/samples/mqtt/src/modules/transport/Kconfig.transport b/app/src/modules/transport/Kconfig.transport similarity index 89% rename from samples/mqtt/src/modules/transport/Kconfig.transport rename to app/src/modules/transport/Kconfig.transport index 3c2f1b8..41a73f9 100644 --- a/samples/mqtt/src/modules/transport/Kconfig.transport +++ b/app/src/modules/transport/Kconfig.transport @@ -56,6 +56,14 @@ config MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC string "MQTT subscribe topic" default "my/subscribe/topic" +config MQTT_GPS_CMD_TOPIC + string "MQTT gps commands subscribe topic" + default "device/get_gps" + +config MQTT_GPS_DATA_TOPIC + string "MQTT gps data publish topic" + default "device/gps" + module = MQTT_SAMPLE_TRANSPORT module-str = Transport source "subsys/logging/Kconfig.template.log_config" diff --git a/samples/mqtt/src/modules/transport/client_id/CMakeLists.txt b/app/src/modules/transport/client_id/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/transport/client_id/CMakeLists.txt rename to app/src/modules/transport/client_id/CMakeLists.txt diff --git a/samples/mqtt/src/modules/transport/client_id/client_id.c b/app/src/modules/transport/client_id/client_id.c similarity index 100% rename from samples/mqtt/src/modules/transport/client_id/client_id.c rename to app/src/modules/transport/client_id/client_id.c diff --git a/samples/mqtt/src/modules/transport/client_id/client_id.h b/app/src/modules/transport/client_id/client_id.h similarity index 100% rename from samples/mqtt/src/modules/transport/client_id/client_id.h rename to app/src/modules/transport/client_id/client_id.h diff --git a/samples/mqtt/src/modules/transport/credentials/ca-cert.pem b/app/src/modules/transport/credentials/ca-cert.pem similarity index 100% rename from samples/mqtt/src/modules/transport/credentials/ca-cert.pem rename to app/src/modules/transport/credentials/ca-cert.pem diff --git a/samples/mqtt/src/modules/transport/credentials_provision/CMakeLists.txt b/app/src/modules/transport/credentials_provision/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/transport/credentials_provision/CMakeLists.txt rename to app/src/modules/transport/credentials_provision/CMakeLists.txt diff --git a/samples/mqtt/src/modules/transport/credentials_provision/credentials_provision.c b/app/src/modules/transport/credentials_provision/credentials_provision.c similarity index 100% rename from samples/mqtt/src/modules/transport/credentials_provision/credentials_provision.c rename to app/src/modules/transport/credentials_provision/credentials_provision.c diff --git a/app/src/modules/transport/transport.c b/app/src/modules/transport/transport.c new file mode 100644 index 0000000..9b62dbf --- /dev/null +++ b/app/src/modules/transport/transport.c @@ -0,0 +1,801 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "client_id.h" +#include "message_channel.h" + +/* Register log module */ +LOG_MODULE_REGISTER(transport, CONFIG_APP_LOG_LEVEL); + +/* Register subscriber */ +ZBUS_SUBSCRIBER_DEFINE(transport, CONFIG_MQTT_SAMPLE_TRANSPORT_MESSAGE_QUEUE_SIZE); + +/* ID for subscribe topic - Used to verify that a subscription succeeded in on_mqtt_suback(). */ +#define SUBSCRIBE_TOPIC_ID 2469 +#define GET_GPS_TOPIC_ID 2470 + +/* Forward declarations */ +static const struct smf_state state[]; +static void connect_work_fn(struct k_work *work); + +/* Define connection work - Used to handle reconnection attempts to the MQTT broker */ +static K_WORK_DELAYABLE_DEFINE(connect_work, connect_work_fn); + +/* Define stack_area of application workqueue */ +K_THREAD_STACK_DEFINE(stack_area, CONFIG_MQTT_SAMPLE_TRANSPORT_WORKQUEUE_STACK_SIZE); + +/* Declare application workqueue. This workqueue is used to call mqtt_helper_connect(), and + * schedule reconnectionn attempts upon network loss or disconnection from MQTT. + */ +static struct k_work_q transport_queue; + +/* Internal states */ +enum module_state { MQTT_CONNECTED, MQTT_DISCONNECTED }; + +/* MQTT client ID buffer */ +static char client_id[CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID_BUFFER_SIZE]; + +static uint8_t pub_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC)]; +static uint8_t sub_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC)]; +static uint8_t get_gps_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_GPS_CMD_TOPIC)]; +static uint8_t gps_pub_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_GPS_DATA_TOPIC)]; + +/* User defined state object. + * Used to transfer data between state changes. + */ +static struct s_object { + /* This must be first */ + struct smf_ctx ctx; + + /* Last channel type that a message was received on */ + const struct zbus_channel *chan; + + /* Network status */ + enum network_status status; + + /* Payload */ + struct payload payload; +} s_obj; + +/* Callback handlers from MQTT helper library. + * The functions are called whenever specific MQTT packets are received from the broker, or + * some library state has changed. + */ +static void on_mqtt_connack(enum mqtt_conn_return_code return_code, bool session_present) +{ + ARG_UNUSED(return_code); + + smf_set_state(SMF_CTX(&s_obj), &state[MQTT_CONNECTED]); +} + +static void on_mqtt_disconnect(int result) +{ + ARG_UNUSED(result); + + smf_set_state(SMF_CTX(&s_obj), &state[MQTT_DISCONNECTED]); +} + +/* Helper function to check if payload matches a string exactly */ +static bool payload_matches(const struct mqtt_helper_buf *payload, const char *str) +{ + size_t str_len = strlen(str); + return (payload->size == str_len) && (strncmp(payload->ptr, str, str_len) == 0); +} + +/* Helper function to check if topic matches a string */ +static bool topic_matches(const struct mqtt_helper_buf *topic, const char *str) +{ + size_t str_len = strlen(str); + return (topic->size == str_len) && (strncmp(topic->ptr, str, str_len) == 0); +} + +static void on_mqtt_publish(struct mqtt_helper_buf topic, struct mqtt_helper_buf payload) +{ + enum camera_cmd cmd; + enum gnss_cmd gnss_cmd; + int err; + + /* Check for GPS location request */ + if (topic_matches(&topic, (char *)get_gps_topic)) { + gnss_cmd = GNSS_CMD_GET_LOCATION; + err = zbus_chan_pub(&GNSS_CMD_CHAN, &gnss_cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish GNSS command: %d", err); + } else { + LOG_INF("Published get_location command to GNSS"); + } + return; + } + + /* Check for camera commands */ + if (payload_matches(&payload, "take_photo")) { + cmd = CAMERA_CMD_TAKE_PHOTO; + err = zbus_chan_pub(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish camera command: %d", err); + } else { + LOG_INF("Published take_photo command to camera"); + } + } else if (payload_matches(&payload, "flash_on")) { + cmd = CAMERA_CMD_FLASH_ON; + err = zbus_chan_pub(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish camera command: %d", err); + } else { + LOG_INF("Published flash_on command to camera"); + } + } else if (payload_matches(&payload, "flash_off")) { + cmd = CAMERA_CMD_FLASH_OFF; + err = zbus_chan_pub(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish camera command: %d", err); + } else { + LOG_INF("Published flash_off command to camera"); + } + } else if (payload_matches(&payload, "camera_on")) { + cmd = CAMERA_CMD_CAMERA_ON; + err = zbus_chan_pub(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish camera command: %d", err); + } else { + LOG_INF("Published camera_on command to camera"); + } + } else if (payload_matches(&payload, "camera_off")) { + cmd = CAMERA_CMD_CAMERA_OFF; + err = zbus_chan_pub(&CAMERA_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to publish camera command: %d", err); + } else { + LOG_INF("Published camera_off command to camera"); + } + } else if (payload_matches(&payload, "activate motor")) { + LOG_INF("Received payload: %.*s on topic: %.*s", payload.size, + payload.ptr, + topic.size, + topic.ptr); + } else if (payload_matches(&payload, "stop motor")) { + LOG_INF("Received payload: %.*s on topic: %.*s", payload.size, + payload.ptr, + topic.size, + topic.ptr); + } else { + LOG_INF("Received payload: %.*s on topic: %.*s", payload.size, + payload.ptr, + topic.size, + topic.ptr); + } +} + +static void on_mqtt_suback(uint16_t message_id, int result) +{ + if ((message_id == SUBSCRIBE_TOPIC_ID) && (result == 0)) { + LOG_INF("Subscribed to payload topic"); + } else if ((message_id == GET_GPS_TOPIC_ID) && (result == 0)) { + LOG_INF("Subscribed to GPS topic"); + } else if (result) { + LOG_ERR("Topic subscription failed, error: %d", result); + } else { + LOG_WRN("Subscribed to unknown topic, id: %d", message_id); + } +} + +/* Local convenience functions */ + +/* Function that prefixes topics with the Client ID. */ +static int topics_prefix(void) +{ + int len; + + len = snprintk(pub_topic, sizeof(pub_topic), "%s/%s", client_id, + CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC); + if ((len < 0) || (len >= sizeof(pub_topic))) { + LOG_ERR("Publish topic buffer too small"); + return -EMSGSIZE; + } + + len = snprintk(sub_topic, sizeof(sub_topic), "%s/%s", client_id, + CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC); + if ((len < 0) || (len >= sizeof(sub_topic))) { + LOG_ERR("Subscribe topic buffer too small"); + return -EMSGSIZE; + } + + len = snprintk(get_gps_topic, sizeof(get_gps_topic), "%s/%s", client_id, CONFIG_MQTT_GPS_CMD_TOPIC); + if ((len < 0) || (len >= sizeof(get_gps_topic))) { + LOG_ERR("Get GPS topic buffer too small"); + return -EMSGSIZE; + } + + len = snprintk(gps_pub_topic, sizeof(gps_pub_topic), "%s/%s", client_id, CONFIG_MQTT_GPS_DATA_TOPIC); + if ((len < 0) || (len >= sizeof(gps_pub_topic))) { + LOG_ERR("GPS publish topic buffer too small"); + return -EMSGSIZE; + } + + return 0; +} + +static void publish(struct payload *payload) +{ + int err; + + struct mqtt_publish_param param = { + .message.payload.data = payload->string, + .message.payload.len = strlen(payload->string), + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = pub_topic, + .message.topic.topic.size = strlen(pub_topic), + }; + + err = mqtt_helper_publish(¶m); + if (err) { + LOG_WRN("Failed to send payload, err: %d", err); + return; + } + + LOG_INF("Published message: \"%.*s\" on topic: \"%.*s\"", param.message.payload.len, + param.message.payload.data, + param.message.topic.topic.size, + param.message.topic.topic.utf8); +} + +/* Publish camera chunk over MQTT */ +static void publish_camera_chunk(struct camera_chunk *chunk) +{ + int err; + static char photo_meta_topic[sizeof(client_id) + 32]; + static char photo_chunk_topic[sizeof(client_id) + 64]; + static bool meta_published = false; + static uint32_t last_sequence = UINT32_MAX; + + /* Publish meta on first chunk */ + if (chunk->sequence == 0) { + int len = snprintk(photo_meta_topic, sizeof(photo_meta_topic), + "%s/camera/photo/meta", client_id); + if (len < 0 || len >= sizeof(photo_meta_topic)) { + LOG_ERR("Photo meta topic buffer too small"); + return; + } + + /* Meta payload: JSON with id, chunks, size */ + char meta_buf[128]; + len = snprintk(meta_buf, sizeof(meta_buf), + "{\"id\":%u,\"chunks\":%u,\"size\":%u}", + (uint32_t)k_uptime_get_32(), chunk->total_chunks, chunk->total_size); + if (len < 0 || len >= sizeof(meta_buf)) { + LOG_ERR("Meta buffer too small"); + return; + } + + struct mqtt_publish_param meta_param = { + .message.payload.data = meta_buf, + .message.payload.len = len, + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = photo_meta_topic, + .message.topic.topic.size = strlen(photo_meta_topic), + }; + + err = mqtt_helper_publish(&meta_param); + if (err) { + LOG_ERR("Failed to publish photo meta, err: %d", err); + return; + } + + LOG_INF("Published photo meta: %s", meta_buf); + meta_published = true; + } + + /* Publish chunk */ + int len = snprintk(photo_chunk_topic, sizeof(photo_chunk_topic), + "%s/camera/photo/chunk/%u", client_id, chunk->sequence); + if (len < 0 || len >= sizeof(photo_chunk_topic)) { + LOG_ERR("Photo chunk topic buffer too small"); + return; + } + + struct mqtt_publish_param chunk_param = { + .message.payload.data = chunk->data, + .message.payload.len = chunk->size, + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = photo_chunk_topic, + .message.topic.topic.size = strlen(photo_chunk_topic), + }; + + err = mqtt_helper_publish(&chunk_param); + if (err) { + LOG_ERR("Failed to publish photo chunk %u, err: %d", chunk->sequence, err); + return; + } + + LOG_DBG("Published photo chunk %u/%u (%u bytes)", chunk->sequence + 1, + chunk->total_chunks, chunk->size); + + /* Reset meta flag on last chunk */ + if (chunk->sequence == chunk->total_chunks - 1) { + meta_published = false; + last_sequence = UINT32_MAX; + LOG_INF("Photo upload complete: %u chunks", chunk->total_chunks); + } +} + +/* Publish GPS data over MQTT */ +static void publish_gps_data(struct gps_data *gps) +{ + int err; + char gps_json[128]; + int len; + + len = snprintk(gps_json, sizeof(gps_json), + "{\"lat\":%.6f,\"lon\":%.6f,\"accuracy\":%.1f}", + gps->latitude, gps->longitude, gps->accuracy); + if (len < 0 || len >= sizeof(gps_json)) { + LOG_ERR("GPS JSON buffer too small"); + return; + } + + struct mqtt_publish_param param = { + .message.payload.data = (uint8_t *)gps_json, + .message.payload.len = len, + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = gps_pub_topic, + .message.topic.topic.size = strlen(gps_pub_topic), + }; + + err = mqtt_helper_publish(¶m); + if (err) { + LOG_ERR("Failed to publish GPS data, err: %d", err); + return; + } + + LOG_INF("Published GPS data: %s", gps_json); +} + +/* Publish GPS error over MQTT */ +static void publish_gps_error(enum gnss_error_type error) +{ + int err; + static char error_topic[sizeof(client_id) + 32]; + const char *error_str; + + switch (error) { + case GNSS_ERROR_NRF_INTERNAL: + error_str = "nrf_internal_error"; + break; + case GNSS_ERROR_INIT_FAILED: + error_str = "gnss_init_failed"; + break; + case GNSS_ERROR_ACTIVATION_FAILED: + error_str = "gnss_activation_failed"; + break; + case GNSS_ERROR_EVENT_HANDLER_FAILED: + error_str = "gnss_event_handler_failed"; + break; + case GNSS_ERROR_CONFIG_FAILED: + error_str = "gnss_config_failed"; + break; + case GNSS_ERROR_START_FAILED: + error_str = "gnss_start_failed"; + break; + case GNSS_ERROR_STOP_FAILED: + error_str = "gnss_stop_failed"; + break; + case GNSS_ERROR_TIMEOUT: + error_str = "gnss_timeout"; + break; + case GNSS_ERROR_INVALID_FIX: + error_str = "gnss_invalid_fix"; + break; + case GNSS_ERROR_PVT_READ_FAILED: + error_str = "gnss_pvt_read_failed"; + break; + default: + error_str = "unknown"; + break; + } + + int len = snprintk(error_topic, sizeof(error_topic), "%s/device/gps/error", client_id); + if (len < 0 || len >= sizeof(error_topic)) { + LOG_ERR("GPS error topic buffer too small"); + return; + } + + struct mqtt_publish_param param = { + .message.payload.data = (uint8_t *)error_str, + .message.payload.len = strlen(error_str), + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = error_topic, + .message.topic.topic.size = strlen(error_topic), + }; + + err = mqtt_helper_publish(¶m); + if (err) { + LOG_ERR("Failed to publish GPS error, err: %d", err); + return; + } + + LOG_INF("Published GPS error: %s", error_str); +} + +/* Publish camera error over MQTT */ +static void publish_camera_error(enum camera_error_type error) +{ + int err; + static char error_topic[sizeof(client_id) + 32]; + const char *error_str; + + switch (error) { + case CAMERA_ERROR_NRF_INTERNAL: + error_str = "nrf_internal_error"; + break; + case CAMERA_ERROR_ESP32_NOT_RESPONDING: + error_str = "cam_module_not_responding"; + break; + case CAMERA_ERROR_ESP32_CAMERA_ACCESS_FAILED: + error_str = "camera_access_failed"; + break; + default: + error_str = "unknown"; + break; + } + + int len = snprintk(error_topic, sizeof(error_topic), "%s/camera/error", client_id); + if (len < 0 || len >= sizeof(error_topic)) { + LOG_ERR("Error topic buffer too small"); + return; + } + + struct mqtt_publish_param param = { + .message.payload.data = (uint8_t *)error_str, + .message.payload.len = strlen(error_str), + .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, + .message_id = mqtt_helper_msg_id_get(), + .message.topic.topic.utf8 = error_topic, + .message.topic.topic.size = strlen(error_topic), + }; + + err = mqtt_helper_publish(¶m); + if (err) { + LOG_ERR("Failed to publish camera error, err: %d", err); + return; + } + + LOG_INF("Published camera error: %s", error_str); +} + +static void subscribe(void) +{ + int err; + + /* Subscribe to main topic */ + struct mqtt_topic topics[] = { + { + .topic.utf8 = sub_topic, + .topic.size = strlen(sub_topic), + }, + }; + struct mqtt_subscription_list list = { + .list = topics, + .list_count = ARRAY_SIZE(topics), + .message_id = SUBSCRIBE_TOPIC_ID, + }; + + LOG_INF("Subscribing to: %s", (char *)list.list[0].topic.utf8); + err = mqtt_helper_subscribe(&list); + if (err) { + LOG_ERR("Failed to subscribe to topics, error: %d", err); + return; + } + + /* Subscribe to GPS topic */ + struct mqtt_topic gps_topics[] = { + { + .topic.utf8 = get_gps_topic, + .topic.size = strlen(get_gps_topic), + }, + }; + struct mqtt_subscription_list gps_list = { + .list = gps_topics, + .list_count = ARRAY_SIZE(gps_topics), + .message_id = GET_GPS_TOPIC_ID, + }; + + LOG_INF("Subscribing to: %s", (char *)gps_list.list[0].topic.utf8); + err = mqtt_helper_subscribe(&gps_list); + if (err) { + LOG_ERR("Failed to subscribe to GPS topic, error: %d", err); + return; + } +} + +/* Connect work - Used to establish a connection to the MQTT broker and schedule reconnection + * attempts. + */ +static void connect_work_fn(struct k_work *work) +{ + ARG_UNUSED(work); + + int err; + struct mqtt_helper_conn_params conn_params = { + .hostname.ptr = CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME, + .hostname.size = strlen(CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME), + .device_id.ptr = client_id, + .device_id.size = strlen(client_id), + }; + + err = client_id_get(client_id, sizeof(client_id)); + if (err) { + LOG_ERR("client_id_get, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + + err = topics_prefix(); + if (err) { + LOG_ERR("topics_prefix, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + + err = mqtt_helper_connect(&conn_params); + if (err) { + LOG_ERR("Failed connecting to MQTT, error code: %d", err); + } + + k_work_reschedule_for_queue(&transport_queue, &connect_work, + K_SECONDS(CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS)); +} + +/* Zephyr State Machine framework handlers */ + +/* Function executed when the module enters the disconnected state. */ +static void disconnected_entry(void *o) +{ + struct s_object *user_object = o; + + /* Reschedule a connection attempt if we are connected to network and we enter the + * disconnected state. + */ + if (user_object->status == NETWORK_CONNECTED) { + k_work_reschedule_for_queue(&transport_queue, &connect_work, K_NO_WAIT); + } +} + +/* Function executed when the module is in the disconnected state. */ +static void disconnected_run(void *o) +{ + struct s_object *user_object = o; + + if ((user_object->status == NETWORK_DISCONNECTED) && (user_object->chan == &NETWORK_CHAN)) { + /* If NETWORK_DISCONNECTED is received after the MQTT connection is closed, + * we cancel the connect work if it is onging. + */ + k_work_cancel_delayable(&connect_work); + } + + else if ((user_object->status == NETWORK_CONNECTED) && (user_object->chan == &NETWORK_CHAN)) { + + /* Wait for 5 seconds to ensure that the network stack is ready before + * attempting to connect to MQTT. This delay is only needed when building for + * Wi-Fi. + */ + k_work_reschedule_for_queue(&transport_queue, &connect_work, K_SECONDS(5)); + } +} + +/* Function executed when the module enters the connected state. */ +static void connected_entry(void *o) +{ + LOG_INF("Connected to MQTT broker"); + LOG_INF("Hostname: %s", CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME); + LOG_INF("Client ID: %s", client_id); + LOG_INF("Port: %d", CONFIG_MQTT_HELPER_PORT); + LOG_INF("TLS: %s", IS_ENABLED(CONFIG_MQTT_LIB_TLS) ? "Yes" : "No"); + + ARG_UNUSED(o); + + /* Cancel any ongoing connect work when we enter connected state */ + k_work_cancel_delayable(&connect_work); + + subscribe(); +} + +/* Function executed when the module is in the connected state. */ +static void connected_run(void *o) +{ + struct s_object *user_object = o; + + if ((user_object->status == NETWORK_DISCONNECTED) && (user_object->chan == &NETWORK_CHAN)) { + /* Explicitly disconnect the MQTT transport when losing network connectivity. + * This is to cleanup any internal library state. + * The call to this function will cause on_mqtt_disconnect() to be called. + */ + (void)mqtt_helper_disconnect(); + return; + } + + if (user_object->chan != &PAYLOAD_CHAN) { + return; + } + + publish(&user_object->payload); +} + +/* Function executed when the module exits the connected state. */ +static void connected_exit(void *o) +{ + ARG_UNUSED(o); + + LOG_INF("Disconnected from MQTT broker"); +} + +/* Construct state table */ +static const struct smf_state state[] = { + [MQTT_DISCONNECTED] = SMF_CREATE_STATE(disconnected_entry, disconnected_run, NULL, + NULL, NULL), + [MQTT_CONNECTED] = SMF_CREATE_STATE(connected_entry, connected_run, connected_exit, + NULL, NULL), +}; + +static void transport_task(void) +{ + int err; + const struct zbus_channel *chan; + enum network_status status; + struct payload payload; + struct mqtt_helper_cfg cfg = { + .cb = { + .on_connack = on_mqtt_connack, + .on_disconnect = on_mqtt_disconnect, + .on_publish = on_mqtt_publish, + .on_suback = on_mqtt_suback, + }, + }; + + /* Initialize and start application workqueue. + * This workqueue can be used to offload tasks and/or as a timer when wanting to + * schedule functionality using the 'k_work' API. + */ + k_work_queue_init(&transport_queue); + k_work_queue_start(&transport_queue, stack_area, + K_THREAD_STACK_SIZEOF(stack_area), + K_HIGHEST_APPLICATION_THREAD_PRIO, + NULL); + + err = mqtt_helper_init(&cfg); + if (err) { + LOG_ERR("mqtt_helper_init, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + + /* Set initial state */ + smf_set_initial(SMF_CTX(&s_obj), &state[MQTT_DISCONNECTED]); + + while (!zbus_sub_wait(&transport, &chan, K_FOREVER)) { + + s_obj.chan = chan; + + if (&NETWORK_CHAN == chan) { + + err = zbus_chan_read(&NETWORK_CHAN, &status, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + + s_obj.status = status; + } + + else if (&PAYLOAD_CHAN == chan) { + + err = zbus_chan_read(&PAYLOAD_CHAN, &payload, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + + s_obj.payload = payload; + } + + else if (&CAMERA_CHUNK_CHAN == chan) { + struct camera_chunk chunk; + + err = zbus_chan_read(&CAMERA_CHUNK_CHAN, &chunk, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + continue; + } + + /* Only publish if MQTT is connected */ + if (s_obj.status == NETWORK_CONNECTED ) { + // && smf_get_current_leaf_state(SMF_CTX(&s_obj)) == &state[MQTT_CONNECTED]) { + publish_camera_chunk(&chunk); + } + continue; + } + + else if (&CAMERA_ERROR_CHAN == chan) { + enum camera_error_type error; + + err = zbus_chan_read(&CAMERA_ERROR_CHAN, &error, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + continue; + } + + /* Only publish if MQTT is connected */ + if (s_obj.status == NETWORK_CONNECTED ) { + // && smf_get_current_leaf_state(SMF_CTX(&s_obj)) == &state[MQTT_CONNECTED]) { + publish_camera_error(error); + } + continue; + } + + else if (&GPS_DATA_CHAN == chan) { + struct gps_data gps; + + err = zbus_chan_read(&GPS_DATA_CHAN, &gps, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + continue; + } + + /* Only publish if MQTT is connected */ + if (s_obj.status == NETWORK_CONNECTED ) { + // && smf_get_current_leaf_state(SMF_CTX(&s_obj)) == &state[MQTT_CONNECTED]) { + publish_gps_data(&gps); + } + continue; + } + + else if (&GNSS_ERROR_CHAN == chan) { + enum gnss_error_type error; + + err = zbus_chan_read(&GNSS_ERROR_CHAN, &error, K_SECONDS(1)); + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + continue; + } + + /* Only publish if MQTT is connected */ + if (s_obj.status == NETWORK_CONNECTED ) { + // && smf_get_current_leaf_state(SMF_CTX(&s_obj)) == &state[MQTT_CONNECTED]) { + publish_gps_error(error); + } + continue; + } + + err = smf_run_state(SMF_CTX(&s_obj)); + if (err) { + LOG_ERR("smf_run_state, error: %d", err); + SEND_FATAL_ERROR(); + return; + } + } +} + +K_THREAD_DEFINE(transport_task_id, + CONFIG_MQTT_SAMPLE_TRANSPORT_THREAD_STACK_SIZE, + transport_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/samples/mqtt/src/modules/trigger/CMakeLists.txt b/app/src/modules/trigger/CMakeLists.txt similarity index 100% rename from samples/mqtt/src/modules/trigger/CMakeLists.txt rename to app/src/modules/trigger/CMakeLists.txt diff --git a/samples/mqtt/src/modules/trigger/Kconfig.trigger b/app/src/modules/trigger/Kconfig.trigger similarity index 100% rename from samples/mqtt/src/modules/trigger/Kconfig.trigger rename to app/src/modules/trigger/Kconfig.trigger diff --git a/app/src/modules/trigger/trigger.c b/app/src/modules/trigger/trigger.c new file mode 100644 index 0000000..5a061eb --- /dev/null +++ b/app/src/modules/trigger/trigger.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include + +#include "message_channel.h" + +/* Register log module */ +LOG_MODULE_REGISTER(trigger, CONFIG_APP_LOG_LEVEL); + +static const struct gpio_dt_spec user_button = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); +static struct gpio_callback user_button_cb; +static struct k_work gnss_request_work; + +static void request_gnss_fix(void) +{ + enum gnss_cmd cmd = GNSS_CMD_GET_LOCATION; + int err; + + err = zbus_chan_pub(&GNSS_CMD_CHAN, &cmd, K_SECONDS(1)); + if (err) { + LOG_ERR("Failed to request GNSS fix, err: %d", err); + SEND_FATAL_ERROR(); + } +} + +static void gnss_request_work_handler(struct k_work *work) +{ + ARG_UNUSED(work); + request_gnss_fix(); +} + +static void user_button_isr(const struct device *port, + struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + ARG_UNUSED(port); + ARG_UNUSED(cb); + ARG_UNUSED(pins); + + k_work_submit(&gnss_request_work); +} + +static void trigger_task(void) +{ + int err; + + if (!gpio_is_ready_dt(&user_button)) { + LOG_ERR("User button GPIO not ready"); + SEND_FATAL_ERROR(); + return; + } + + k_work_init(&gnss_request_work, gnss_request_work_handler); + + err = gpio_pin_configure_dt(&user_button, GPIO_INPUT); + if (err) { + LOG_ERR("gpio_pin_configure_dt failed: %d", err); + SEND_FATAL_ERROR(); + return; + } + + err = gpio_pin_interrupt_configure_dt(&user_button, GPIO_INT_EDGE_TO_ACTIVE); + if (err) { + LOG_ERR("gpio_pin_interrupt_configure_dt failed: %d", err); + SEND_FATAL_ERROR(); + return; + } + + gpio_init_callback(&user_button_cb, user_button_isr, BIT(user_button.pin)); + err = gpio_add_callback(user_button.port, &user_button_cb); + if (err) { + LOG_ERR("gpio_add_callback failed: %d", err); + SEND_FATAL_ERROR(); + return; + } + + /* Button-only behavior: wait forever. */ + k_sleep(K_FOREVER); +} + +K_THREAD_DEFINE(trigger_task_id, + CONFIG_MQTT_SAMPLE_TRIGGER_THREAD_STACK_SIZE, + trigger_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/applications/ifmcu_firmware/CMakeLists.txt b/applications/ifmcu_firmware/CMakeLists.txt deleted file mode 100644 index 82a887e..0000000 --- a/applications/ifmcu_firmware/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -find_package(Git) -project(IFMCU) - -# NORDIC SDK APP START -target_sources(app PRIVATE - src/main.c - ) -# NORDIC SDK APP END - -# Include application events and disk files -zephyr_library_include_directories( - src/events - src/modules - ) - -# Application sources -add_subdirectory(src/events) -add_subdirectory(src/modules) diff --git a/applications/ifmcu_firmware/Kconfig b/applications/ifmcu_firmware/Kconfig deleted file mode 100644 index 875bcda..0000000 --- a/applications/ifmcu_firmware/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor ASA -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -menu "IFMCU Firmware" -rsource "src/modules/Kconfig" -rsource "src/events/Kconfig" -endmenu - -menu "Zephyr Kernel" -source "Kconfig.zephyr" -endmenu diff --git a/applications/ifmcu_firmware/Kconfig.sysbuild b/applications/ifmcu_firmware/Kconfig.sysbuild deleted file mode 100644 index c3523fc..0000000 --- a/applications/ifmcu_firmware/Kconfig.sysbuild +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor ASA -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Do not use partition manager -config PARTITION_MANAGER - default n - -source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/applications/ifmcu_firmware/VERSION b/applications/ifmcu_firmware/VERSION deleted file mode 100644 index 79053a5..0000000 --- a/applications/ifmcu_firmware/VERSION +++ /dev/null @@ -1,5 +0,0 @@ -VERSION_MAJOR = 1 -VERSION_MINOR = 0 -PATCHLEVEL = 0 -VERSION_TWEAK = 0 -EXTRAVERSION = \ No newline at end of file diff --git a/applications/ifmcu_firmware/prj.conf b/applications/ifmcu_firmware/prj.conf deleted file mode 100644 index 19bcb5e..0000000 --- a/applications/ifmcu_firmware/prj.conf +++ /dev/null @@ -1,101 +0,0 @@ -# General -CONFIG_REBOOT=y -CONFIG_HEAP_MEM_POOL_SIZE=1024 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1024 -CONFIG_ISR_STACK_SIZE=1024 -CONFIG_MAIN_STACK_SIZE=1024 -CONFIG_NET_BUF=y -CONFIG_GPIO=y -CONFIG_POLL=y -CONFIG_APP_EVENT_MANAGER=y -CONFIG_SPEED_OPTIMIZATIONS=y -CONFIG_PM_DEVICE=y -CONFIG_DK_LIBRARY=y - -# Features -CONFIG_IFMCU_CDC_ENABLE=y -CONFIG_IFMCU_CMSIS_DAP_BULK_ENABLE=y -CONFIG_IFMCU_CMSIS_DAP_VENDOR_COMMANDS=y -CONFIG_IFMCU_UTILS_ENABLE=y - -# DAP -CONFIG_DAP=y -CONFIG_DP_DRIVER=y -CONFIG_CMSIS_DAP_BOARD_VENDOR="Makerdiary" -CONFIG_CMSIS_DAP_BOARD_NAME="nRF9151 Connect Kit" -CONFIG_CMSIS_DAP_DEVICE_VENDOR="Nordic Semiconductor ASA" -CONFIG_CMSIS_DAP_DEVICE_NAME="NRF91" - - # USB -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_REMOTE_WAKEUP=n -CONFIG_USB_DEVICE_PID=0x0204 -CONFIG_USB_DEVICE_PRODUCT="IFMCU CMSIS-DAP" -CONFIG_USB_DEVICE_SN="820D9A5F012PLACEHLDRS" # This is overridden at runtime -CONFIG_USB_COMPOSITE_DEVICE=y -CONFIG_USB_CDC_ACM_RINGBUF_SIZE=1024 -CONFIG_USB_MAX_POWER=250 -CONFIG_USB_MAX_NUM_TRANSFERS=8 - -# Settings -CONFIG_FCB=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_FCB=y -CONFIG_FLASH=y -CONFIG_FLASH_PAGE_LAYOUT=y -CONFIG_FLASH_MAP=y -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -# Logging -CONFIG_LOG=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_LOG_BACKEND_RTT=n -CONFIG_LOG_BACKEND_RTT_MODE_DROP=n - -# Event logs -CONFIG_IFMCU_LOG_MODULE_STATE_EVENT=n -CONFIG_IFMCU_LOG_UART_DATA_EVENT=n -CONFIG_IFMCU_LOG_CDC_DATA_EVENT=n -CONFIG_IFMCU_LOG_PEER_CONN_EVENT=n -CONFIG_IFMCU_LOG_POWER_DOWN_EVENT=n - - # UART -CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_0_INTERRUPT_DRIVEN=n -CONFIG_UART_LINE_CTRL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_0_ASYNC=y -CONFIG_UART_USE_RUNTIME_CONFIGURE=y -CONFIG_NRFX_UARTE0=y -CONFIG_NRFX_TIMER1=y -CONFIG_NRFX_PPI=y - -CONFIG_HW_ID_LIBRARY=y -CONFIG_RESET_ON_FATAL_ERROR=n -CONFIG_ASSERT=n -CONFIG_POWEROFF=y - -CONFIG_BOOT_BANNER=n -CONFIG_NCS_BOOT_BANNER=n -CONFIG_HW_STACK_PROTECTION=n - -# Shell -CONFIG_PRINTK=y -CONFIG_SHELL=y -CONFIG_SHELL_STACK_SIZE=2048 -CONFIG_SHELL_BACKEND_SERIAL=y -CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR=y -CONFIG_SHELL_PROMPT_UART="ifsh:~$ " - -CONFIG_APP_EVENT_MANAGER_SHELL=n - -CONFIG_DEVMEM_SHELL=n -CONFIG_THREAD_MONITOR=y -CONFIG_INIT_STACKS=y -CONFIG_THREAD_NAME=y -CONFIG_CBPRINTF_NANO=y -CONFIG_THREAD_STACK_INFO=y - -CONFIG_I2C_SHELL=y -CONFIG_SETTINGS_SHELL=y diff --git a/applications/ifmcu_firmware/sample.yaml b/applications/ifmcu_firmware/sample.yaml deleted file mode 100644 index c50226f..0000000 --- a/applications/ifmcu_firmware/sample.yaml +++ /dev/null @@ -1,8 +0,0 @@ -sample: - name: IFMCU Firmware -tests: - applications.ifmcu_firmware: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf52820 diff --git a/applications/ifmcu_firmware/src/events/CMakeLists.txt b/applications/ifmcu_firmware/src/events/CMakeLists.txt deleted file mode 100644 index 53ba18d..0000000 --- a/applications/ifmcu_firmware/src/events/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/module_state_event.c - ${CMAKE_CURRENT_SOURCE_DIR}/peer_conn_event.c - ${CMAKE_CURRENT_SOURCE_DIR}/cdc_data_event.c - ${CMAKE_CURRENT_SOURCE_DIR}/uart_data_event.c - ${CMAKE_CURRENT_SOURCE_DIR}/power_event.c) diff --git a/applications/ifmcu_firmware/src/events/Kconfig b/applications/ifmcu_firmware/src/events/Kconfig deleted file mode 100644 index a2f52e0..0000000 --- a/applications/ifmcu_firmware/src/events/Kconfig +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -if LOG - -menu "Event options" - -comment "Initially logged events" - -config IFMCU_LOG_MODULE_STATE_EVENT - bool "Module state event" - default y - -config IFMCU_LOG_UART_DATA_EVENT - bool "UART data event" - default y - -config IFMCU_LOG_CDC_DATA_EVENT - bool "CDC data event" - default y - -config IFMCU_LOG_PEER_CONN_EVENT - bool "Peer connection event" - default y - -config IFMCU_LOG_POWER_DOWN_EVENT - bool "Power down event" - default y - -endmenu - -endif diff --git a/applications/ifmcu_firmware/src/events/cdc_data_event.c b/applications/ifmcu_firmware/src/events/cdc_data_event.c deleted file mode 100644 index 4a94354..0000000 --- a/applications/ifmcu_firmware/src/events/cdc_data_event.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include "cdc_data_event.h" - -static void log_cdc_data_event(const struct app_event_header *aeh) -{ - const struct cdc_data_event *event = cast_cdc_data_event(aeh); - - APP_EVENT_MANAGER_LOG(aeh, - "dev:%u buf:%p len:%d", - event->dev_idx, - event->buf, - event->len); -} - -APP_EVENT_TYPE_DEFINE(cdc_data_event, - log_cdc_data_event, - NULL, - APP_EVENT_FLAGS_CREATE( - IF_ENABLED(CONFIG_IFMCU_LOG_CDC_DATA_EVENT, - (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/applications/ifmcu_firmware/src/events/cdc_data_event.h b/applications/ifmcu_firmware/src/events/cdc_data_event.h deleted file mode 100644 index 928b60c..0000000 --- a/applications/ifmcu_firmware/src/events/cdc_data_event.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _CDC_DATA_EVENT_H_ -#define _CDC_DATA_EVENT_H_ - -/** - * @brief CDC Data Event - * @defgroup cdc_data_event CDC Data Event - * @{ - */ - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Peer connection event. */ -struct cdc_data_event { - struct app_event_header header; - - uint8_t dev_idx; - uint8_t *buf; - size_t len; -}; - -APP_EVENT_TYPE_DECLARE(cdc_data_event); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _CDC_DATA_EVENT_H_ */ diff --git a/applications/ifmcu_firmware/src/events/module_state_event.c b/applications/ifmcu_firmware/src/events/module_state_event.c deleted file mode 100644 index 68d9eb7..0000000 --- a/applications/ifmcu_firmware/src/events/module_state_event.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include "module_state_event.h" - -static const char * const state_name[] = { -#define X(name) STRINGIFY(name), - MODULE_STATE_LIST -#undef X -}; - -static void log_module_state_event(const struct app_event_header *aeh) -{ - const struct module_state_event *event = cast_module_state_event(aeh); - - BUILD_ASSERT(ARRAY_SIZE(state_name) == MODULE_STATE_COUNT, - "Invalid number of elements"); - - __ASSERT_NO_MSG(event->state < MODULE_STATE_COUNT); - - APP_EVENT_MANAGER_LOG(aeh, "module:%s state:%s", - (const char *)event->module_id, state_name[event->state]); -} - -APP_EVENT_TYPE_DEFINE(module_state_event, - log_module_state_event, - NULL, - APP_EVENT_FLAGS_CREATE( - IF_ENABLED(CONFIG_IFMCU_LOG_MODULE_STATE_EVENT, - (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/applications/ifmcu_firmware/src/events/module_state_event.h b/applications/ifmcu_firmware/src/events/module_state_event.h deleted file mode 100644 index 3261415..0000000 --- a/applications/ifmcu_firmware/src/events/module_state_event.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _MODULE_STATE_EVENT_H_ -#define _MODULE_STATE_EVENT_H_ - -/** - * @brief Module Event - * @defgroup module_state_event Module State Event - * @{ - */ - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** Module state list. */ -#define MODULE_STATE_LIST \ - X(READY) \ - X(OFF) \ - X(STANDBY) \ - X(ERROR) - -/** Module states. */ -enum module_state { -#define X(name) _CONCAT(MODULE_STATE_, name), - MODULE_STATE_LIST -#undef X - - MODULE_STATE_COUNT -}; - -/** Module event. */ -struct module_state_event { - struct app_event_header header; - - const void *module_id; - enum module_state state; -}; - -APP_EVENT_TYPE_DECLARE(module_state_event); - - -#if defined(MODULE) - -#define MODULE_NAME STRINGIFY(MODULE) - -const void * const _CONCAT(__module_, MODULE) = MODULE_NAME; - -static inline void module_set_state(enum module_state state) -{ - __ASSERT_NO_MSG(state < MODULE_STATE_COUNT); - - struct module_state_event *event = new_module_state_event(); - - event->module_id = _CONCAT(__module_, MODULE); - event->state = state; - APP_EVENT_SUBMIT(event); -} - -#endif - - -static inline bool check_state(const struct module_state_event *event, - const void *module_id, enum module_state state) -{ - if ((event->module_id == module_id) && (event->state == state)) { - return true; - } - return false; -} - - -#define MODULE_ID(mname) ({ \ - extern const void * const _CONCAT(__module_, mname); \ - _CONCAT(__module_, mname); \ - }) - - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _MODULE_STATE_EVENT_H_ */ diff --git a/applications/ifmcu_firmware/src/events/peer_conn_event.c b/applications/ifmcu_firmware/src/events/peer_conn_event.c deleted file mode 100644 index f497183..0000000 --- a/applications/ifmcu_firmware/src/events/peer_conn_event.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include "peer_conn_event.h" - -static const char * const peer_name[] = { -#define X(name) STRINGIFY(name), - PEER_ID_LIST -#undef X -}; - -static void log_peer_conn_event(const struct app_event_header *aeh) -{ - const struct peer_conn_event *event = cast_peer_conn_event(aeh); - - BUILD_ASSERT(ARRAY_SIZE(peer_name) == PEER_ID_COUNT, - "Invalid number of elements"); - - __ASSERT_NO_MSG(event->peer_id < PEER_ID_COUNT); - - APP_EVENT_MANAGER_LOG(aeh, - "%s:%s_%d changed: %d baud:%d", - event->conn_state == PEER_STATE_CONNECTED ? - "CONNECTED" : "DISCONNECTED", - peer_name[event->peer_id], - event->dev_idx, - event->conn_state_changed, - event->baudrate); -} - -APP_EVENT_TYPE_DEFINE(peer_conn_event, - log_peer_conn_event, - NULL, - APP_EVENT_FLAGS_CREATE( - IF_ENABLED(CONFIG_IFMCU_LOG_PEER_CONN_EVENT, - (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/applications/ifmcu_firmware/src/events/peer_conn_event.h b/applications/ifmcu_firmware/src/events/peer_conn_event.h deleted file mode 100644 index 64ceda0..0000000 --- a/applications/ifmcu_firmware/src/events/peer_conn_event.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _PEER_CONN_EVENT_H_ -#define _PEER_CONN_EVENT_H_ - -/** - * @brief Peer Connection Event - * @defgroup peer_conn_event Peer Connection Event - * @{ - */ - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Peer type list. */ -#define PEER_ID_LIST \ - X(USB) \ - X(BLE) - -/** Peer ID list. */ -enum peer_id { -#define X(name) _CONCAT(PEER_ID_, name), - PEER_ID_LIST -#undef X - - PEER_ID_COUNT -}; - -enum peer_conn_state { - PEER_STATE_CONNECTED, - PEER_STATE_DISCONNECTED -}; - -/** Peer connection event. */ -struct peer_conn_event { - struct app_event_header header; - - enum peer_id peer_id; - uint8_t dev_idx; - enum peer_conn_state conn_state; - uint32_t baudrate; - bool conn_state_changed; -}; - -APP_EVENT_TYPE_DECLARE(peer_conn_event); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _PEER_CONN_EVENT_H_ */ diff --git a/applications/ifmcu_firmware/src/events/power_event.c b/applications/ifmcu_firmware/src/events/power_event.c deleted file mode 100644 index e9f559b..0000000 --- a/applications/ifmcu_firmware/src/events/power_event.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "power_event.h" - -APP_EVENT_TYPE_DEFINE(power_down_event, - NULL, - NULL, - APP_EVENT_FLAGS_CREATE( - IF_ENABLED(CONFIG_IFMCU_LOG_POWER_DOWN_EVENT, - (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/applications/ifmcu_firmware/src/events/power_event.h b/applications/ifmcu_firmware/src/events/power_event.h deleted file mode 100644 index 482196f..0000000 --- a/applications/ifmcu_firmware/src/events/power_event.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _POWER_EVENT_H_ -#define _POWER_EVENT_H_ - -/** - * @brief Power Event - * @defgroup power_event Power Event - * @{ - */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct power_down_event { - struct app_event_header header; - bool error; -}; - -APP_EVENT_TYPE_DECLARE(power_down_event); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _POWER_EVENT_H_ */ diff --git a/applications/ifmcu_firmware/src/events/uart_data_event.c b/applications/ifmcu_firmware/src/events/uart_data_event.c deleted file mode 100644 index 06edc6b..0000000 --- a/applications/ifmcu_firmware/src/events/uart_data_event.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include "uart_data_event.h" - -static void log_uart_data_event(const struct app_event_header *aeh) -{ - const struct uart_data_event *event = cast_uart_data_event(aeh); - - APP_EVENT_MANAGER_LOG(aeh, - "dev:%u buf:%p len:%d", - event->dev_idx, - event->buf, - event->len); -} - -APP_EVENT_TYPE_DEFINE(uart_data_event, - log_uart_data_event, - NULL, - APP_EVENT_FLAGS_CREATE( - IF_ENABLED(CONFIG_IFMCU_LOG_UART_DATA_EVENT, - (APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE)))); diff --git a/applications/ifmcu_firmware/src/events/uart_data_event.h b/applications/ifmcu_firmware/src/events/uart_data_event.h deleted file mode 100644 index d378473..0000000 --- a/applications/ifmcu_firmware/src/events/uart_data_event.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _UART_DATA_EVENT_H_ -#define _UART_DATA_EVENT_H_ - -/** - * @brief UART Data Event - * @defgroup uart_data_event UART Data Event - * @{ - */ - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Peer connection event. */ -struct uart_data_event { - struct app_event_header header; - - uint8_t dev_idx; - uint8_t *buf; - size_t len; -}; - -APP_EVENT_TYPE_DECLARE(uart_data_event); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _UART_DATA_EVENT_H_ */ diff --git a/applications/ifmcu_firmware/src/main.c b/applications/ifmcu_firmware/src/main.c deleted file mode 100644 index 108f33c..0000000 --- a/applications/ifmcu_firmware/src/main.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#include -#include - -#define MODULE main -#include "module_state_event.h" - -#include -LOG_MODULE_REGISTER(MODULE); - -static uint8_t usb_serial_str[] = "820D9A5F012PLACEHLDRS"; - -/* Overriding weak function to set iSerialNumber at runtime. */ -uint8_t *usb_update_sn_string_descriptor(void) -{ -#if defined(CONFIG_SOC_SERIES_NRF52X) - snprintk(usb_serial_str, sizeof(usb_serial_str), "820D9A5F0%04X%08X", - (uint32_t)(NRF_FICR->DEVICEADDR[1] & 0x0000FFFF)|0x0000C000, - (uint32_t)NRF_FICR->DEVICEADDR[0]); -#else - char buf[HW_ID_LEN] = {0}; - - if (!hw_id_get(buf, ARRAY_SIZE(buf))) { - snprintk(usb_serial_str, sizeof(usb_serial_str), "820D9A5F0%s", buf); - } -#endif - return usb_serial_str; -} - -int main(void) -{ - if (app_event_manager_init()) { - LOG_ERR("Application Event Manager not initialized"); - } else { - module_set_state(MODULE_STATE_READY); - } - return 0; -} diff --git a/applications/ifmcu_firmware/src/modules/CMakeLists.txt b/applications/ifmcu_firmware/src/modules/CMakeLists.txt deleted file mode 100644 index 844ed83..0000000 --- a/applications/ifmcu_firmware/src/modules/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_sources_ifdef(CONFIG_POWEROFF - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/power_handler.c) - -target_sources_ifdef(CONFIG_SERIAL - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/uart_handler.c) - -target_sources_ifdef(CONFIG_LED - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/led_state.c) - -target_sources_ifdef(CONFIG_CHARGER - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/charger.c) - -target_sources_ifdef(CONFIG_SETTINGS - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/settings.c) - -target_sources_ifdef(CONFIG_IFMCU_CDC_ENABLE - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/usb_cdc_handler.c) - -target_sources_ifdef(CONFIG_IFMCU_CMSIS_DAP_BULK_ENABLE - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/usb_bulk_interface.c) - -target_sources_ifdef(CONFIG_IFMCU_CMSIS_DAP_VENDOR_COMMANDS - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/usb_bulk_commands.c) - -target_sources_ifdef(CONFIG_IFMCU_UTILS_ENABLE - app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/utils.c) diff --git a/applications/ifmcu_firmware/src/modules/Kconfig b/applications/ifmcu_firmware/src/modules/Kconfig deleted file mode 100644 index ebfd165..0000000 --- a/applications/ifmcu_firmware/src/modules/Kconfig +++ /dev/null @@ -1,115 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# Copyright (c) 2016-2025 Makerdiary -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -module = IFMCU_UART -module-str = UART device -source "subsys/logging/Kconfig.template.log_config" - -config IFMCU_CDC_ENABLE - bool "Enable USB CDC ACM" - depends on USB_DEVICE_STACK - select USB_CDC_ACM - help - This option enables USB CDC ACM - and exposes a COM port, bridging the UART0 interface. - -if IFMCU_CDC_ENABLE - -module = IFMCU_CDC -module-str = USB CDC ACM device -source "subsys/logging/Kconfig.template.log_config" - -endif - -config IFMCU_CMSIS_DAP_BULK_ENABLE - bool "Enable USB Bulk" - depends on USB_DEVICE_STACK - select USB_DEVICE_BOS - -config IFMCU_CMSIS_DAP_VENDOR_COMMANDS - bool "Enable vendor specific commands" - depends on IFMCU_CMSIS_DAP_BULK_ENABLE - help - This option enables vendor specific commands for CMSIS-DAP Bulk. - Currently, these are only relevant for the nRF9151 Connect Kit board. - -if IFMCU_CMSIS_DAP_BULK_ENABLE - -module = IFMCU_BULK -module-str = USB Bulk device -source "subsys/logging/Kconfig.template.log_config" - -config BULK_USB_THREAD_STACK_SIZE - int "USB Bulk thread stack size" - default 1024 - help - Size of stack for USB Bulk handler thread. - -endif - -if PM_DEVICE - -module = IFMCU_POWER_MGMT -module-str = Interface MCU power management -source "subsys/logging/Kconfig.template.log_config" - -endif - -config IFMCU_BUF_SIZE - int "Transport interface buffer size" - default 512 - help - Size of transmit/receive buffer for transfer between interfaces. - -config IFMCU_UART_BUF_COUNT - int "UART buffer block count" - default 3 - range 3 255 - help - Number of buffer blocks assigned for UART instances. - This value is scaled with the number of interfaces. - With the default instance count of 1, and for example 3 buffers, - the total will be 3 buffers. - Note that all buffers are shared between UART instances. - -if LED - -module = IFMCU_LEDS -module-str = Interface MCU leds -source "subsys/logging/Kconfig.template.log_config" - -endif # LED - -if CHARGER - -module = IFMCU_CHARGER -module-str = Interface MCU charger -source "subsys/logging/Kconfig.template.log_config" - -endif # CHARGER - -if SETTINGS - -module = IFMCU_SETTINGS -module-str = Interface MCU settings -source "subsys/logging/Kconfig.template.log_config" - -endif # SETTINGS - -config IFMCU_UTILS_ENABLE - bool "Enable utils module" - select SENSOR - help - This option enables utils modules. - -if IFMCU_UTILS_ENABLE - -module = IFMCU_UTILS -module-str = Utils module -source "subsys/logging/Kconfig.template.log_config" - -endif # IFMCU_UTILS_ENABLE diff --git a/applications/ifmcu_firmware/src/modules/charger.c b/applications/ifmcu_firmware/src/modules/charger.c deleted file mode 100644 index 9933abc..0000000 --- a/applications/ifmcu_firmware/src/modules/charger.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#include -#include -#include -#include -#include - -#include "led_state.h" - -#define MODULE charger -#include "module_state_event.h" -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_CHARGER_LOG_LEVEL); - -#define BQ25180_ICHG_CTRL 0x04 -#define BQ25180_TMR_ILIM 0x08 -#define BQ25180_SYS_REG 0x0A - -#define BQ25180_ICHG_CHG_DIS BIT(7) -#define BQ25180_SYS_REG_CTRL_MSK GENMASK(7, 5) -#define BQ25180_ILIM_MSK GENMASK(2, 0) - -#define CHARGING_CHECK_INTERVAL K_MSEC(1000) - -struct charger_config { - struct i2c_dt_spec i2c; - uint32_t initial_current_microamp; - uint32_t max_voltage_microvolt; - uint32_t recharge_voltage_microvolt; - uint32_t precharge_threshold_voltage_microvolt; -}; - -const static char * const sysreg_descr[] = { - [0] = "VSYS = VBAT + 225 mV (3.8 V minimum)", - [1] = "VSYS = 4.4V", - [2] = "VSYS = 4.5V", - [3] = "VSYS = 4.6V", - [4] = "VSYS = 4.7V", - [5] = "VSYS = 4.8V", - [6] = "VSYS = 4.9V", - [7] = "VSYS = VBUS", -}; - -const static char * const ilim_descr[] = { - [0] = "ILIM = 50mA", - [1] = "ILIM = 100mA(max.)", - [2] = "ILIM = 200mA", - [3] = "ILIM = 300mA", - [4] = "ILIM = 400mA", - [5] = "ILIM = 500mA(max.)", - [6] = "ILIM = 700mA", - [7] = "ILIM = 1100mA", -}; - -const static char * const status_descr[] = { - [0] = "Unknown", - [1] = "Charging", - [2] = "Discharging", - [3] = "Not Charging", - [4] = "Charging Full", -}; - -static const struct device *chgdev = DEVICE_DT_GET(DT_NODELABEL(charger)); - -static struct k_work_delayable charging_dwork; - -int bq25180_chgdis_set(uint8_t chgdis) -{ - int ret; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = charger_charge_enable(chgdev, !chgdis); - if (ret < 0) { - return ret; - } - - return 0; -} - -int bq25180_chgdis_get(uint8_t *chgdis) -{ - const struct charger_config *config = chgdev->config; - const struct i2c_dt_spec *i2c = &config->i2c; - int ret; - uint8_t ichg_ctrl; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = i2c_reg_read_byte_dt(i2c, BQ25180_ICHG_CTRL, &ichg_ctrl); - if (ret < 0) { - return ret; - } - - *chgdis = (ichg_ctrl & BQ25180_ICHG_CHG_DIS)? 1 : 0; - - return 0; -} - -int bq25180_sysreg_set(uint8_t mode) -{ - const struct charger_config *config = chgdev->config; - const struct i2c_dt_spec *i2c = &config->i2c; - int ret; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - mode = FIELD_PREP(BQ25180_SYS_REG_CTRL_MSK, mode); - - ret = i2c_reg_update_byte_dt(i2c, BQ25180_SYS_REG, BQ25180_SYS_REG_CTRL_MSK, mode); - if (ret < 0) { - return ret; - } - - return 0; -} - -int bq25180_sysreg_get(uint8_t *mode) -{ - const struct charger_config *config = chgdev->config; - const struct i2c_dt_spec *i2c = &config->i2c; - int ret; - uint8_t sysreg_ctrl; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = i2c_reg_read_byte_dt(i2c, BQ25180_SYS_REG, &sysreg_ctrl); - if (ret < 0) { - return ret; - } - - *mode = FIELD_GET(BQ25180_SYS_REG_CTRL_MSK, sysreg_ctrl); - - return 0; -} - -int bq25180_ichg_set(uint32_t current_ma) -{ - int ret; - union charger_propval val; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - val.const_charge_current_ua = current_ma * 1000; - - ret = charger_set_prop(chgdev, CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA, &val); - - return ret; -} - -int bq25180_ichg_get(uint32_t *current_ma) -{ - int ret; - union charger_propval val; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = charger_get_prop(chgdev, CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA, &val); - if (ret < 0) { - return ret; - } - - *current_ma = val.const_charge_current_ua / 1000; - - return 0; -} - -int bq25180_vbatreg_set(uint32_t voltage_mv) -{ - int ret; - union charger_propval val; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - val.const_charge_voltage_uv = voltage_mv * 1000; - - ret = charger_set_prop(chgdev, CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV, &val); - - return ret; -} - -int bq25180_vbatreg_get(uint32_t *voltage_mv) -{ - int ret; - union charger_propval val; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = charger_get_prop(chgdev, CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV, &val); - if (ret < 0) { - return ret; - } - - *voltage_mv = val.const_charge_voltage_uv / 1000; - - return 0; -} - -int bq25180_ilim_set(uint8_t level) -{ - const struct charger_config *config = chgdev->config; - const struct i2c_dt_spec *i2c = &config->i2c; - int ret; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - level = FIELD_PREP(BQ25180_ILIM_MSK, level); - - ret = i2c_reg_update_byte_dt(i2c, BQ25180_TMR_ILIM, BQ25180_ILIM_MSK, level); - if (ret < 0) { - return ret; - } - - return 0; -} - -int bq25180_ilim_get(uint8_t *level) -{ - const struct charger_config *config = chgdev->config; - const struct i2c_dt_spec *i2c = &config->i2c; - int ret; - uint8_t ilim; - - if (!device_is_ready(chgdev)) { - return -ENODEV; - } - - ret = i2c_reg_read_byte_dt(i2c, BQ25180_TMR_ILIM, &ilim); - if (ret < 0) { - return ret; - } - - *level = FIELD_GET(BQ25180_ILIM_MSK, ilim); - - return 0; -} - -#ifdef CONFIG_SHELL - -static int cmd_charger_chgdis(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - uint8_t chgdis; - char *endptr; - long val; - - if (argc == 1) { - ret = bq25180_chgdis_get(&chgdis); - if (ret < 0) { - shell_error(sh, "Cannot get CHG_DIS: (err = %d)", ret); - return ret; - } - - shell_print(sh, "Battery Charging %s", chgdis? "Disabled" : "Enabled"); - - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val != 0) && (val != 1))) { - shell_error(sh, " must be 0 or 1"); - return -EINVAL; - } - - ret = bq25180_chgdis_set((uint8_t)val); - if (ret < 0) { - shell_error(sh, "Cannot enable or disable charging: (err = %d)", ret); - return ret; - } - - return 0; -} - -static int cmd_charger_sysreg(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - uint8_t mode; - char *endptr; - long val; - - if (argc == 1) { - ret = bq25180_sysreg_get(&mode); - if (ret < 0) { - shell_error(sh, "Cannot get SYS Voltage: (err = %d)", ret); - return ret; - } - shell_print(sh, "[%d]: %s", mode, sysreg_descr[mode]); - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val < 0) && (val > 7))) { - shell_error(sh, " must be in the range 0 to 7"); - return -EINVAL; - } - - ret = bq25180_sysreg_set((uint8_t)val); - if (ret < 0) { - shell_error(sh, "Cannot set SYS Voltage: (err = %d)", ret); - return ret; - } - - return 0; -} - -static int cmd_charger_ichg(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - uint32_t current_ma; - char *endptr; - long val; - - if (argc == 1) { - ret = bq25180_ichg_get(¤t_ma); - if (ret < 0) { - shell_error(sh, "Cannot get Fast Charge Current: (err = %d)", ret); - return ret; - } - shell_print(sh, "%d mA", current_ma); - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val < 0) && (val > 1000))) { - shell_error(sh, " must be in the range 0 to 1000"); - return -EINVAL; - } - - ret = bq25180_ichg_set((uint32_t)val); - if (ret < 0) { - shell_error(sh, "Cannot set Fast Charge Current: (err = %d)", ret); - return ret; - } - - return 0; -} - -static int cmd_charger_vbatreg(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - uint32_t voltage_mv; - char *endptr; - long val; - - if (argc == 1) { - ret = bq25180_vbatreg_get(&voltage_mv); - if (ret < 0) { - shell_error(sh, "Cannot get Battery Regulation Voltage (%d)", ret); - return ret; - } - shell_print(sh, "%d mV", voltage_mv); - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val < 3500) && (val > 4650))) { - shell_error(sh, " must be in the range 3500 to 4650"); - return -EINVAL; - } - - ret = bq25180_vbatreg_set((uint32_t)val); - if (ret < 0) { - shell_error(sh, "Cannot set Battery Regulation Voltage: (err = %d)", ret); - return ret; - } - - return 0; -} - -static int cmd_charger_ilim(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - uint8_t level; - char *endptr; - long val; - - if (argc == 1) { - ret = bq25180_ilim_get(&level); - if (ret < 0) { - shell_error(sh, "Cannot get Input Current Limit: (err = %d)", ret); - return ret; - } - shell_print(sh, "[%d]: %s", level, ilim_descr[level]); - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val < 0) && (val > 7))) { - shell_error(sh, " must be in the range 0 to 7"); - return -EINVAL; - } - - ret = bq25180_ilim_set((uint8_t)val); - if (ret < 0) { - shell_error(sh, "Cannot set Input Current Limit: (err = %d)", ret); - return ret; - } - - return 0; -} - -static int cmd_charger_status(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - union charger_propval val; - - ret = charger_get_prop(chgdev, CHARGER_PROP_STATUS, &val); - if (ret < 0) { - shell_error(sh, "Cannot get Charger Status: (err = %d)", ret); - return ret; - } - - shell_print(sh, "[%d]: %s", val.status, status_descr[val.status]); - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE(sub_charger, - SHELL_CMD_ARG(chgdis, NULL, - "Charge Disable\n" - "Usage: charger chgdis [value: 0|1]", cmd_charger_chgdis, 1, 1), - SHELL_CMD_ARG(sysreg, NULL, - "Get or Set SYS Voltage\n" - "Usage: charger sysreg [mode: 0-7]\n" - "[mode: 0-7] - VBAT+225mV(>=3.8V)|4.4V|4.5V|4.6V|4.7V|4.8V|4.9V|VBUS", - cmd_charger_sysreg, 1, 1), - SHELL_CMD_ARG(ichg, NULL, - "Get or Set Fast Charge Current (0-1000mA)\n" - "Usage: charger ichg [current_ma: 0-1000]", cmd_charger_ichg, 1, 1), - SHELL_CMD_ARG(vbatreg, NULL, - "Get or Set Battery Regulation Voltage (3500-4650mV)\n" - "Usage: charger vbatreg [voltage_mv: 3500-4650]", cmd_charger_vbatreg, 1, 1), - SHELL_CMD_ARG(ilim, NULL, - "Get or Set Input Current Limit\n" - "Usage: charger ilim [level: 0-7]\n" - "[level: 0-7] - 50mA|100mA|200mA|300mA|400mA|500mA|700mA|1100mA", - cmd_charger_ilim, 1, 1), - SHELL_CMD_ARG(status, NULL, - "Get Charging Status", cmd_charger_status, 1, 0), - SHELL_SUBCMD_SET_END /* Array terminated. */ -); - -SHELL_CMD_REGISTER(charger, &sub_charger, - "Charger commands\n" - "Please refer to TI BQ25180 Datasheet for more details.", NULL); - -#endif /* CONFIG_SHELL */ - -static void charging_dwork_handler(struct k_work *work) -{ - int ret; - union charger_propval val0, val1; - - ret = charger_get_prop(chgdev, CHARGER_PROP_ONLINE, &val0); - if (ret < 0) { - LOG_ERR("Could not get the charger online property. (rc: %d)", ret); - goto out; - } - - ret = charger_get_prop(chgdev, CHARGER_PROP_STATUS, &val1); - if (ret < 0) { - LOG_ERR("Could not get the charger status property. (rc: %d)", ret); - goto out; - } - - if (val0.online == CHARGER_ONLINE_OFFLINE) { - set_pgood_led_state(LED_STATE_OFF); - set_charger_led_state(LED_STATE_OFF); - } else { - set_pgood_led_state(LED_STATE_ON); - if (val1.status == CHARGER_STATUS_CHARGING) { - set_charger_led_state(LED_STATE_BREATH); - } else if (val1.status == CHARGER_STATUS_FULL) { - set_charger_led_state(LED_STATE_OFF); - } else { - LOG_WRN("unknown charger state: oneline=%d status=%d", - val0.online, val1.status); - goto out; - } - } - -out: - k_work_schedule(&charging_dwork, CHARGING_CHECK_INTERVAL); -} - -static int init_fn(void) -{ - if (!device_is_ready(chgdev)) { - LOG_ERR("Charger device is not ready"); - return -ENODEV; - } - - k_work_init_delayable(&charging_dwork, charging_dwork_handler); - charging_dwork_handler(&charging_dwork.work); - - return 0; -} - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_module_state_event(aeh)) { - const struct module_state_event *event = cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - /* tell the rest of the system that we are busy. */ - module_set_state(MODULE_STATE_READY); - - int ret = init_fn(); - if (ret) { - LOG_ERR("Failed to initialize the charger, %d", ret); - } - - /* tell the rest of the system that we are done. */ - module_set_state(MODULE_STATE_STANDBY); - } - return false; - } - /* we should not reach this point */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); diff --git a/applications/ifmcu_firmware/src/modules/led_state.c b/applications/ifmcu_firmware/src/modules/led_state.c deleted file mode 100644 index 71611dd..0000000 --- a/applications/ifmcu_firmware/src/modules/led_state.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include "led_state.h" - -#define MODULE led_state -#include "module_state_event.h" -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_LEDS_LOG_LEVEL); - -#define LED_GPIO_NODE_ID DT_COMPAT_GET_ANY_STATUS_OKAY(gpio_leds) -#define LED_GPIO_NUM DT_CHILD_NUM(LED_GPIO_NODE_ID) -#define LED_PWM_NODE_ID DT_COMPAT_GET_ANY_STATUS_OKAY(pwm_leds) -#define LED_PWM_NUM DT_CHILD_NUM(LED_PWM_NODE_ID) - -#define LED_ID_PGOOD_STATE 0 /* Green LED */ -#define LED_ID_CHARGER_STATE 1 /* RGB LED - Green */ -#define LED_ID_UART_STATE 0 /* RGB LED - Red */ -#define LED_ID_DAP_STATE 2 /* RGB LED - Blue */ - -#define LED_STATE_TICK K_MSEC(50) -#define LED_MAX_BRIGHTNESS 80 -#define LED_BREATH_STEP 2 - -static const struct device *led_gpio = DEVICE_DT_GET(LED_GPIO_NODE_ID); -static const struct device *led_pwm = DEVICE_DT_GET(LED_PWM_NODE_ID); - -static bool pgood_led_activity = false; -static bool charger_led_activity = false; -static bool uart_led_activity = false; -static bool dap_led_activity = false; -static led_state_t pgood_led_state = LED_STATE_OFF; -static led_state_t charger_led_state = LED_STATE_OFF; -static led_state_t uart_led_state = LED_STATE_OFF; -static led_state_t dap_led_state = LED_STATE_OFF; - -static void led_state_timer_expiry_fn(struct k_timer *timer); -static K_TIMER_DEFINE(led_state_timer, led_state_timer_expiry_fn, NULL); - -/* Set VIN Power Good LED state */ -void set_pgood_led_state(led_state_t state) -{ - pgood_led_activity = true; - pgood_led_state = state; - return; -} - -/* Set Charger LED state */ -void set_charger_led_state(led_state_t state) -{ - charger_led_activity = true; - charger_led_state = state; - return; -} - -/* Set DAP LED state */ -void set_dap_led_state(led_state_t state) -{ - dap_led_activity = true; - dap_led_state = state; - return; -} - -/* Set UART LED state */ -void set_uart_led_state(led_state_t state) -{ - uart_led_activity = true; - uart_led_state = state; - return; -} - -static void led_state_timer_expiry_fn(struct k_timer *timer) -{ - if (pgood_led_activity) { - - static uint8_t pgood_led_level = 0; - - if (pgood_led_state == LED_STATE_ON) { - - pgood_led_level = LED_MAX_BRIGHTNESS; - - } else if ((pgood_led_state == LED_STATE_BLINK) || (pgood_led_state == LED_STATE_BLINK_PERMANENT)) { - // Toggle LED level - pgood_led_level = pgood_led_level > 0 ? 0 : LED_MAX_BRIGHTNESS; - - // If in blink mode stop after one cycle - if ((pgood_led_level == 0) && (pgood_led_state == LED_STATE_BLINK)) { - pgood_led_activity = false; - pgood_led_state = LED_STATE_OFF; - } - } else { - // LED next state is LED_STATE_OFF - pgood_led_level = 0; - pgood_led_activity = false; - } - - // update LED - (void) led_set_brightness(led_gpio, LED_ID_PGOOD_STATE, pgood_led_level); - } - - if (charger_led_activity) { - - static uint8_t charger_led_level = 0; - - if (charger_led_state == LED_STATE_ON) { - - charger_led_level = LED_MAX_BRIGHTNESS; - - }else if ((charger_led_state == LED_STATE_BLINK) || (charger_led_state == LED_STATE_BLINK_PERMANENT)) { - // Toggle LED level - charger_led_level = charger_led_level > 0 ? 0 : LED_MAX_BRIGHTNESS; - - // If in blink mode stop after one cycle - if ((charger_led_level == 0) && (charger_led_state == LED_STATE_BLINK)) { - charger_led_activity = false; - charger_led_state = LED_STATE_OFF; - } - } else if (charger_led_state == LED_STATE_BREATH) { - - static uint8_t charger_led_dir = 1U; - - if (charger_led_dir) { - charger_led_level += LED_BREATH_STEP; - if (charger_led_level > LED_MAX_BRIGHTNESS) { - charger_led_level -= LED_BREATH_STEP; - charger_led_dir = 0U; - } - } else { - if (charger_led_level > LED_BREATH_STEP) { - charger_led_level -= LED_BREATH_STEP; - } else { - charger_led_level = 0; - charger_led_dir = 1U; - } - } - } else { - // LED next state is LED_STATE_OFF - charger_led_level = 0; - charger_led_activity = false; - } - - // update LED - (void) led_set_brightness(led_pwm, LED_ID_CHARGER_STATE, charger_led_level); - } - - if (uart_led_activity) { - - static uint8_t uart_led_level = 0; - - if (uart_led_state == LED_STATE_ON) { - uart_led_level = LED_MAX_BRIGHTNESS; - } else if ((uart_led_state == LED_STATE_BLINK) || (uart_led_state == LED_STATE_BLINK_PERMANENT)) { - // Toggle LED level - uart_led_level = uart_led_level > 0 ? 0 : LED_MAX_BRIGHTNESS; - - // If in blink mode stop after one cycle - if ((uart_led_level == 0) && (uart_led_state == LED_STATE_BLINK)) { - uart_led_activity = false; - uart_led_state = LED_STATE_OFF; - } - } else { - // LED next state is LED_STATE_OFF - uart_led_level = 0; - uart_led_activity = false; - } - - // update LED - (void) led_set_brightness(led_pwm, LED_ID_UART_STATE, uart_led_level); - } - - if (dap_led_activity) { - - static uint8_t dap_led_level = 0; - - if ((dap_led_state == LED_STATE_BLINK) || (dap_led_state == LED_STATE_BLINK_PERMANENT)) { - // Toggle LED level - dap_led_level = dap_led_level > 0 ? 0 : LED_MAX_BRIGHTNESS; - - // If in blink mode stop after one cycle - if ((dap_led_level == 0) && (dap_led_state == LED_STATE_BLINK)) { - dap_led_activity = false; - dap_led_state = LED_STATE_OFF; - } - } else { - // LED next state is LED_STATE_OFF - dap_led_level = 0; - dap_led_activity = false; - } - - // update LED - (void) led_set_brightness(led_pwm, LED_ID_DAP_STATE, dap_led_level); - } -} - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_module_state_event(aeh)) { - const struct module_state_event *event = cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - /* tell the rest of the system that we are busy. */ - module_set_state(MODULE_STATE_READY); - - k_timer_start(&led_state_timer, LED_STATE_TICK, LED_STATE_TICK); - - /* tell the rest of the system that we are done. */ - module_set_state(MODULE_STATE_STANDBY); - } - return false; - } - /* we should not reach this point */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); diff --git a/applications/ifmcu_firmware/src/modules/led_state.h b/applications/ifmcu_firmware/src/modules/led_state.h deleted file mode 100644 index 80841f3..0000000 --- a/applications/ifmcu_firmware/src/modules/led_state.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _LED_STATE_H_ -#define _LED_STATE_H_ - -/** - * @file - * @defgroup led_state LED state - * @{ - * @brief LED state. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief led states in the application. */ -typedef enum led_state { - LED_STATE_OFF = 0, - LED_STATE_ON, - LED_STATE_BLINK, - LED_STATE_BLINK_PERMANENT, - LED_STATE_BREATH, - LED_STATE_COUNT -} led_state_t; - -void set_pgood_led_state(led_state_t state); -void set_charger_led_state(led_state_t state); -void set_uart_led_state(led_state_t state); -void set_dap_led_state(led_state_t state); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* _LED_STATE_H_ */ diff --git a/applications/ifmcu_firmware/src/modules/power_handler.c b/applications/ifmcu_firmware/src/modules/power_handler.c deleted file mode 100644 index 8378d6c..0000000 --- a/applications/ifmcu_firmware/src/modules/power_handler.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include -#include - -#define MODULE power_handler -#include "module_state_event.h" -#include "power_event.h" - -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_POWER_MGMT_LOG_LEVEL); - -static void power_down_handler(struct k_work *work); - -static K_WORK_DELAYABLE_DEFINE(power_down_work, power_down_handler); -static int module_active_count; - -static void power_down_handler(struct k_work *work) -{ - if (module_active_count == 0) { - struct power_down_event *event = new_power_down_event(); - - event->error = 0; - APP_EVENT_SUBMIT(event); - - /* Keep submitting events as they may be consumed to delay shutdown */ - k_work_reschedule(&power_down_work, K_SECONDS(1)); - } -} - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_module_state_event(aeh)) { - const struct module_state_event *event = - cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - module_active_count = 0; - } else if (event->state == MODULE_STATE_READY) { - module_active_count += 1; - } else if (event->state == MODULE_STATE_STANDBY) { - module_active_count -= 1; - __ASSERT_NO_MSG(module_active_count >= 0); - - if (module_active_count == 0) { - /* All modules went into standby, shutting down system. */ - k_work_reschedule(&power_down_work, K_SECONDS(1)); - } - } - return false; - } - - if (is_power_down_event(aeh)) { - /* Put the chip in SYSTEM OFF mode, to be rebooted when USB is connected. */ - sys_poweroff(); - } - - /* If event is unhandled, unsubscribe. */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); -APP_EVENT_SUBSCRIBE_FINAL(MODULE, power_down_event); diff --git a/applications/ifmcu_firmware/src/modules/settings.c b/applications/ifmcu_firmware/src/modules/settings.c deleted file mode 100644 index ad71b18..0000000 --- a/applications/ifmcu_firmware/src/modules/settings.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#include -#include -#include -#include - -#define MODULE settings -#include "module_state_event.h" - -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_SETTINGS_LOG_LEVEL); - -#define SETTINGS_KEY "cfg" -#define VIOSEL_STORAGE_NAME "viosel" -#define CHARGER_CHGDIS_STORAGE_NAME "chgdis" -#define CHARGER_SYSREG_STORAGE_NAME "sysreg" -#define CHARGER_ICHG_STORAGE_NAME "ichg" -#define CHARGER_VBATREG_STORAGE_NAME "vbatreg" -#define CHARGER_ILIM_STORAGE_NAME "ilim" - -extern int viosel_set(int val); -extern int viosel_get(void); -extern int bq25180_chgdis_set(uint8_t chgdis); -extern int bq25180_chgdis_get(uint8_t *chgdis); -extern int bq25180_sysreg_set(uint8_t mode); -extern int bq25180_sysreg_get(uint8_t *mode); -extern int bq25180_ichg_set(uint32_t current_ma); -extern int bq25180_ichg_get(uint32_t *current_ma); -extern int bq25180_vbatreg_set(uint32_t voltage_mv); -extern int bq25180_vbatreg_get(uint32_t *voltage_mv); -extern int bq25180_ilim_set(uint8_t level); -extern int bq25180_ilim_get(uint8_t *level); - -static int settings_set(const char *key, size_t len_rd, - settings_read_cb read_cb, void *cb_arg) -{ - int ret; - ssize_t rc; - - if (!strcmp(key, VIOSEL_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(int)) { - int viosel; - rc = read_cb(cb_arg, &viosel, sizeof(viosel)); - if (rc == sizeof(viosel)) { - if ((viosel == -1 || viosel == 0 || viosel == 1) && viosel != viosel_get()) { - ret = viosel_set(viosel); - if (ret < 0) { - LOG_ERR("Fail to set VIOSEL: (err = %d)", ret); - return 0; - } - LOG_DBG("Load VIOSEL = %d", viosel); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } else if (!strcmp(key, CHARGER_CHGDIS_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(uint8_t)) { - uint8_t chgdis_stored; - rc = read_cb(cb_arg, &chgdis_stored, sizeof(chgdis_stored)); - if (rc == sizeof(chgdis_stored)) { - uint8_t chgdis; - ret = bq25180_chgdis_get(&chgdis); - if (ret < 0) { - LOG_ERR("Fail to get CHGDIS: (err = %d)", ret); - return 0; - } - if ((chgdis_stored == 0 || chgdis_stored == 1) && chgdis_stored != chgdis) { - ret = bq25180_chgdis_set(chgdis_stored); - if (ret < 0) { - LOG_ERR("Fail to set CHGDIS: (err = %d)", ret); - return 0; - } - LOG_DBG("Load CHGDIS = %d", chgdis_stored); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } else if (!strcmp(key, CHARGER_SYSREG_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(uint8_t)) { - uint8_t sysreg_stored; - rc = read_cb(cb_arg, &sysreg_stored, sizeof(sysreg_stored)); - if (rc == sizeof(sysreg_stored)) { - uint8_t sysreg; - ret = bq25180_sysreg_get(&sysreg); - if (ret < 0) { - LOG_ERR("Fail to get SYSREG: (err = %d)", ret); - return 0; - } - if (sysreg_stored < 8 && sysreg_stored != sysreg) { - ret = bq25180_sysreg_set(sysreg_stored); - if (ret < 0) { - LOG_ERR("Fail to set SYSREG: (err = %d)", ret); - return 0; - } - LOG_DBG("Load SYSREG = %d", sysreg_stored); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } else if (!strcmp(key, CHARGER_ICHG_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(uint8_t)) { - uint32_t ichg_ma_stored; - rc = read_cb(cb_arg, &ichg_ma_stored, sizeof(ichg_ma_stored)); - if (rc == sizeof(ichg_ma_stored)) { - uint32_t ichg_ma; - ret = bq25180_ichg_get(&ichg_ma); - if (ret < 0) { - LOG_ERR("Fail to get ICHG: (err = %d)", ret); - return 0; - } - if (ichg_ma_stored <= 1000 && ichg_ma_stored != ichg_ma) { - ret = bq25180_ichg_set(ichg_ma_stored); - if (ret < 0) { - LOG_ERR("Fail to set ICHG: (err = %d)", ret); - return 0; - } - LOG_DBG("Load ICHG = %d", ichg_ma_stored); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } else if (!strcmp(key, CHARGER_VBATREG_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(uint8_t)) { - uint32_t vbatreg_mv_stored; - rc = read_cb(cb_arg, &vbatreg_mv_stored, sizeof(vbatreg_mv_stored)); - if (rc == sizeof(vbatreg_mv_stored)) { - uint32_t vbatreg_mv; - ret = bq25180_vbatreg_get(&vbatreg_mv); - if (ret < 0) { - LOG_ERR("Fail to get VBATREG: (err = %d)", ret); - return 0; - } - if ((vbatreg_mv_stored >= 3500 && vbatreg_mv_stored <= 4650) && vbatreg_mv_stored != vbatreg_mv) { - ret = bq25180_vbatreg_set(vbatreg_mv_stored); - if (ret < 0) { - LOG_ERR("Fail to set VBATREG: (err = %d)", ret); - return 0; - } - LOG_DBG("Load VBATREG = %d", vbatreg_mv_stored); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } else if (!strcmp(key, CHARGER_ILIM_STORAGE_NAME)) { - /* Ignore record when size is improper. */ - if (len_rd == sizeof(uint8_t)) { - uint8_t ilim_stored; - rc = read_cb(cb_arg, &ilim_stored, sizeof(ilim_stored)); - if (rc == sizeof(ilim_stored)) { - uint8_t ilim; - ret = bq25180_ilim_get(&ilim); - if (ret < 0) { - LOG_ERR("Fail to get ILIM: (err = %d)", ret); - return 0; - } - if (ilim_stored < 8 && ilim_stored != ilim) { - ret = bq25180_ilim_set(ilim_stored); - if (ret < 0) { - LOG_ERR("Fail to set ILIM: (err = %d)", ret); - return 0; - } - LOG_DBG("Load ILIM = %d", ilim_stored); - } - } else { - if (rc < 0) { - LOG_ERR("Settings read-out error"); - return rc; - } - } - } - } - - return 0; -} - -static void settings_init(void) -{ - int err; - - err = settings_subsys_init(); - if (err) { - return; - } - - static struct settings_handler sh = { - .name = SETTINGS_KEY, - .h_set = settings_set, - }; - - err = settings_register(&sh); - if (err) { - return; - } - - err = settings_load(); - if (err) { - return; - } -} - -static int cmd_cfgsync(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - - /* Store VIOSEL */ - char viosel_key[] = SETTINGS_KEY "/" VIOSEL_STORAGE_NAME; - int viosel = viosel_get(); - ret = settings_save_one(viosel_key, &viosel, sizeof(viosel)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", viosel_key, ret); - } - - /* Store CHGDIS */ - char chgdis_key[] = SETTINGS_KEY "/" CHARGER_CHGDIS_STORAGE_NAME; - uint8_t chgdis; - ret = bq25180_chgdis_get(&chgdis); - if (ret < 0) { - shell_error(sh, "Fail to get CHGDIS: (err = %d)", ret); - } else { - ret = settings_save_one(chgdis_key, &chgdis, sizeof(chgdis)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", chgdis_key, ret); - } - } - - /* Store SYSREG */ - char sysreg_key[] = SETTINGS_KEY "/" CHARGER_SYSREG_STORAGE_NAME; - uint8_t sysreg; - ret = bq25180_sysreg_get(&sysreg); - if (ret < 0) { - shell_error(sh, "Fail to get SYSREG: (err = %d)", ret); - } else { - ret = settings_save_one(sysreg_key, &sysreg, sizeof(sysreg)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", sysreg_key, ret); - } - } - - /* Store ICHG */ - char ichg_key[] = SETTINGS_KEY "/" CHARGER_ICHG_STORAGE_NAME; - uint32_t ichg_ma; - ret = bq25180_ichg_get(&ichg_ma); - if (ret < 0) { - shell_error(sh, "Fail to get ICHG: (err = %d)", ret); - } else { - ret = settings_save_one(ichg_key, &ichg_ma, sizeof(ichg_ma)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", ichg_key, ret); - } - } - - /* Store VBATREG */ - char vbatreg_key[] = SETTINGS_KEY "/" CHARGER_VBATREG_STORAGE_NAME; - uint32_t vbatreg_mv; - ret = bq25180_vbatreg_get(&vbatreg_mv); - if (ret < 0) { - shell_error(sh, "Fail to get VBATREG: (err = %d)", ret); - } else { - ret = settings_save_one(vbatreg_key, &vbatreg_mv, sizeof(vbatreg_mv)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", vbatreg_key, ret); - } - } - - /* Store ILIM */ - char ilim_key[] = SETTINGS_KEY "/" CHARGER_ILIM_STORAGE_NAME; - uint8_t ilim; - ret = bq25180_ilim_get(&ilim); - if (ret < 0) { - shell_error(sh, "Fail to get ILIM: (err = %d)", ret); - } else { - ret = settings_save_one(ilim_key, &ilim, sizeof(ilim)); - if (ret) { - shell_error(sh, "Problem storing %s: (err = %d)", ilim_key, ret); - } - } - - return 0; -} - -SHELL_CMD_ARG_REGISTER(cfgsync, NULL, - "Store settings to the non-volatile memory", cmd_cfgsync, 1, 0); - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_module_state_event(aeh)) { - const struct module_state_event *event = - cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - settings_init(); - } - - return false; - } - - /* If event is unhandled, unsubscribe. */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); diff --git a/applications/ifmcu_firmware/src/modules/uart_handler.c b/applications/ifmcu_firmware/src/modules/uart_handler.c deleted file mode 100644 index c9e8371..0000000 --- a/applications/ifmcu_firmware/src/modules/uart_handler.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include - -#include "led_state.h" - -#define MODULE uart_handler -#include "module_state_event.h" -#include "peer_conn_event.h" -#include "cdc_data_event.h" -#include "uart_data_event.h" - -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_UART_LOG_LEVEL); - -static const struct device *devices[] = { - DEVICE_DT_GET(DT_NODELABEL(uart0)), -}; - -#define UART_DEVICE_COUNT ARRAY_SIZE(devices) - -#define UART_BUF_SIZE CONFIG_IFMCU_BUF_SIZE - -#define UART_SLAB_BLOCK_SIZE sizeof(struct uart_rx_buf) -#define UART_SLAB_BLOCK_COUNT (UART_DEVICE_COUNT * CONFIG_IFMCU_UART_BUF_COUNT) -#define UART_SLAB_ALIGNMENT 4 -#define UART_RX_TIMEOUT_USEC 1000 - -#if defined(CONFIG_PM_DEVICE) -#define UART_SET_PM_STATE true -#else -#define UART_SET_PM_STATE false -#endif - -struct uart_rx_buf { - atomic_t ref_counter; - size_t len; - uint8_t buf[UART_BUF_SIZE]; -}; - -struct uart_tx_buf { - struct ring_buf rb; - uint8_t buf[UART_BUF_SIZE]; -}; - -BUILD_ASSERT((sizeof(struct uart_rx_buf) % UART_SLAB_ALIGNMENT) == 0); - -/* Blocks from the same slab is used for RX for all UART instances */ -/* TX has inidividual ringbuffers per UART instance */ - -K_MEM_SLAB_DEFINE(uart_rx_slab, UART_SLAB_BLOCK_SIZE, UART_SLAB_BLOCK_COUNT, UART_SLAB_ALIGNMENT); - -static struct uart_tx_buf uart_tx_ringbufs[UART_DEVICE_COUNT]; -static uint32_t uart_default_baudrate[UART_DEVICE_COUNT]; -/* UART RX only enabled when there is one or more subscribers (power saving) */ -static int subscriber_count[UART_DEVICE_COUNT]; -static bool enable_rx_retry[UART_DEVICE_COUNT]; -static atomic_t uart_tx_started[UART_DEVICE_COUNT]; - -static void enable_uart_rx(uint8_t dev_idx); -static void disable_uart_rx(uint8_t dev_idx); -static void set_uart_power_state(uint8_t dev_idx, bool active); -static int uart_tx_start(uint8_t dev_idx); -static void uart_tx_finish(uint8_t dev_idx, size_t len); - -static inline struct uart_rx_buf *block_start_get(uint8_t *buf) -{ - size_t block_num; - - /* blocks are fixed size units from a continuous memory slab: */ - /* round down to the closest unit size to find beginning of block. */ - - block_num = - (((size_t)buf - (size_t)uart_rx_slab.buffer) / UART_SLAB_BLOCK_SIZE); - - return (struct uart_rx_buf *) &uart_rx_slab.buffer[block_num * UART_SLAB_BLOCK_SIZE]; -} - -static struct uart_rx_buf *uart_rx_buf_alloc(void) -{ - struct uart_rx_buf *buf; - int err; - - /* Async UART driver returns pointers to received data as */ - /* offsets from beginning of RX buffer block. */ - /* This code uses a reference counter to keep track of the number of */ - /* references within a single RX buffer block */ - - err = k_mem_slab_alloc(&uart_rx_slab, (void **) &buf, K_NO_WAIT); - if (err) { - return NULL; - } - - atomic_set(&buf->ref_counter, 1); - - return buf; -} - -static void uart_rx_buf_ref(void *buf) -{ - __ASSERT_NO_MSG(buf); - - atomic_inc(&(block_start_get(buf)->ref_counter)); -} - -static void uart_rx_buf_unref(void *buf) -{ - __ASSERT_NO_MSG(buf); - - struct uart_rx_buf *uart_buf = block_start_get(buf); - atomic_t ref_counter = atomic_dec(&uart_buf->ref_counter); - - /* ref_counter is the uart_buf->ref_counter value prior to decrement */ - if (ref_counter == 1) { - k_mem_slab_free(&uart_rx_slab, (void *)uart_buf); - } -} - -static void uart_callback(const struct device *dev, struct uart_event *evt, - void *user_data) -{ - int dev_idx = (int) user_data; - struct uart_data_event *event; - struct uart_rx_buf *buf; - int err; - - switch (evt->type) { - case UART_RX_RDY: - uart_rx_buf_ref(evt->data.rx.buf); - - event = new_uart_data_event(); - event->dev_idx = dev_idx; - event->buf = &evt->data.rx.buf[evt->data.rx.offset]; - event->len = evt->data.rx.len; - APP_EVENT_SUBMIT(event); - break; - case UART_RX_BUF_RELEASED: - if (evt->data.rx_buf.buf) { - uart_rx_buf_unref(evt->data.rx_buf.buf); - } - break; - case UART_RX_BUF_REQUEST: - buf = uart_rx_buf_alloc(); - if (buf == NULL) { - LOG_WRN("UART_%d RX overflow", dev_idx); - break; - } - - err = uart_rx_buf_rsp(dev, buf->buf, sizeof(buf->buf)); - if (err) { - LOG_ERR("uart_rx_buf_rsp: %d", err); - uart_rx_buf_unref(buf); - } - break; - case UART_RX_DISABLED: - if (enable_rx_retry[dev_idx]) { - enable_uart_rx(dev_idx); - enable_rx_retry[dev_idx] = false; - } else if (UART_SET_PM_STATE) { - set_uart_power_state(dev_idx, false); - } - break; - case UART_TX_DONE: - uart_tx_finish(dev_idx, evt->data.tx.len); - - if (ring_buf_is_empty(&uart_tx_ringbufs[dev_idx].rb)) { - atomic_set(&uart_tx_started[dev_idx], false); - } else { - uart_tx_start(dev_idx); - } - break; - case UART_TX_ABORTED: - uart_tx_finish(dev_idx, evt->data.tx.len); - atomic_set(&uart_tx_started[dev_idx], false); - break; - case UART_RX_STOPPED: - LOG_WRN("UART_%d stop reason %d", dev_idx, evt->data.rx_stop.reason); - - /* Retry automatically in case of unexpected stop. - * Typically happens when the peer does not drive its TX GPIO, - * or if there is a baud rate mismatch. - */ - if (IS_ENABLED(CONFIG_UART_NRFX_UARTE_LEGACY_SHIM)) { - enable_rx_retry[dev_idx] = true; - } - break; - default: - LOG_ERR("Unexpected event: %d", evt->type); - __ASSERT_NO_MSG(false); - break; - } -} - -static void set_uart_baudrate(uint8_t dev_idx, uint32_t baudrate) -{ - const struct device *dev = devices[dev_idx]; - struct uart_config cfg; - int err; - - if (baudrate == 0) { - return; - } - - err = uart_config_get(dev, &cfg); - if (err) { - LOG_ERR("uart_config_get: %d", err); - return; - } - - if (cfg.baudrate == baudrate) { - return; - } - - cfg.baudrate = baudrate; - - err = uart_configure(dev, &cfg); - if (err) { - LOG_ERR("uart_configure: %d", err); - return; - } -} - -static void set_uart_power_state(uint8_t dev_idx, bool active) -{ -#if UART_SET_PM_STATE - const struct device *dev = devices[dev_idx]; - int err; - enum pm_device_action action; - - action = active ? PM_DEVICE_ACTION_RESUME : PM_DEVICE_ACTION_SUSPEND; - - err = pm_device_action_run(dev, action); - if ((err < 0) && (err != -EALREADY)) { - LOG_ERR("pm_device_action_run failed: %d", err); - } -#endif -} - -static void enable_uart_rx(uint8_t dev_idx) -{ - const struct device *dev = devices[dev_idx]; - int err; - struct uart_rx_buf *buf; - - err = uart_callback_set(dev, uart_callback, (void *) (int) dev_idx); - if (err) { - LOG_ERR("uart_callback_set: %d", err); - return; - } - - buf = uart_rx_buf_alloc(); - if (!buf) { - LOG_ERR("uart_rx_buf_alloc error"); - return; - } - - err = uart_rx_enable(dev, buf->buf, sizeof(buf->buf), UART_RX_TIMEOUT_USEC); - if (err) { - uart_rx_buf_unref(buf); - LOG_ERR("uart_rx_enable: %d", err); - return; - } -} - -static void disable_uart_rx(uint8_t dev_idx) -{ - const struct device *dev = devices[dev_idx]; - int err; - - err = uart_rx_disable(dev); - if (err) { - LOG_ERR("uart_rx_disable: %d", err); - return; - } -} - -static int uart_tx_start(uint8_t dev_idx) -{ - int len; - int err; - uint8_t *buf; - - len = ring_buf_get_claim( - &uart_tx_ringbufs[dev_idx].rb, - &buf, - sizeof(uart_tx_ringbufs[dev_idx].buf)); - - err = uart_tx(devices[dev_idx], buf, len, 0); - if (err) { - LOG_ERR("uart_tx: %d", err); - uart_tx_finish(dev_idx, 0); - return err; - } - - return 0; -} - -static void uart_tx_finish(uint8_t dev_idx, size_t len) -{ - int err; - - err = ring_buf_get_finish(&uart_tx_ringbufs[dev_idx].rb, len); - if (err) { - LOG_ERR("ring_buf_get_finish: %d", err); - } -} - -static int uart_tx_enqueue(uint8_t *data, size_t data_len, uint8_t dev_idx) -{ - atomic_t started; - uint32_t written; - int err; - - written = ring_buf_put(&uart_tx_ringbufs[dev_idx].rb, data, data_len); - if (written == 0) { - return -ENOMEM; - } - - started = atomic_set(&uart_tx_started[dev_idx], true); - if (!started) { - err = uart_tx_start(dev_idx); - if (err) { - LOG_ERR("uart_tx_start: %d", err); - atomic_set(&uart_tx_started[dev_idx], false); - } - } - - if (written == data_len) { - return 0; - } else { - return -ENOMEM; - } - - return 0; -} - -static bool app_event_handler(const struct app_event_header *aeh) -{ - int err; - - if (is_uart_data_event(aeh)) { - const struct uart_data_event *event = - cast_uart_data_event(aeh); - - set_uart_led_state(LED_STATE_BLINK); - - /* All subscribers have gotten a chance to copy data at this point */ - uart_rx_buf_unref(event->buf); - - return true; - } - - if (is_cdc_data_event(aeh)) { - const struct cdc_data_event *event = - cast_cdc_data_event(aeh); - - if (event->dev_idx >= UART_DEVICE_COUNT) { - return false; - } - - if (!devices[event->dev_idx]) { - return false; - } - - set_uart_led_state(LED_STATE_BLINK); - - err = uart_tx_enqueue(event->buf, event->len, event->dev_idx); - if (err == -ENOMEM) { - LOG_WRN("CDC_%d->UART_%d overflow", - event->dev_idx, - event->dev_idx); - } else if (err) { - LOG_ERR("uart_tx_enqueue: %d", err); - } - - return false; - } - - if (is_peer_conn_event(aeh)) { - const struct peer_conn_event *event = - cast_peer_conn_event(aeh); - int prev_count; - - if (event->dev_idx >= UART_DEVICE_COUNT) { - return false; - } - - if (!devices[event->dev_idx]) { - return false; - } - - if (!event->conn_state_changed) { - set_uart_baudrate(event->dev_idx, event->baudrate); - return false; - } - - prev_count = subscriber_count[event->dev_idx]; - - if (event->conn_state == PEER_STATE_CONNECTED) { - subscriber_count[event->dev_idx] += 1; - set_uart_baudrate(event->dev_idx, event->baudrate); - } else { - subscriber_count[event->dev_idx] -= 1; - } - - __ASSERT_NO_MSG(subscriber_count[event->dev_idx] >= 0); - - if (subscriber_count[event->dev_idx] == 0) { - LOG_DBG("No subscribers. Close UART_%d RX", event->dev_idx); - set_uart_baudrate( - event->dev_idx, - uart_default_baudrate[event->dev_idx]); - disable_uart_rx(event->dev_idx); - } else if (prev_count == 0) { - LOG_DBG("First subscriber. Open UART_%d RX", event->dev_idx); - if (UART_SET_PM_STATE) { - set_uart_power_state(event->dev_idx, true); - } - enable_uart_rx(event->dev_idx); - } else { - return false; - } - - return false; - } - - if (is_module_state_event(aeh)) { - const struct module_state_event *event = - cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - for (int i = 0; i < UART_DEVICE_COUNT; ++i) { - struct uart_config cfg; - - if (!device_is_ready(devices[i])) { - LOG_ERR("UART device not ready: %s", - devices[i]->name); - continue; - } - - err = uart_config_get(devices[i], &cfg); - if (err) { - LOG_ERR("uart_config_get: %d", err); - return false; - } - uart_default_baudrate[i] = cfg.baudrate; - subscriber_count[i] = 0; - enable_rx_retry[i] = false; - - atomic_set(&uart_tx_started[i], false); - - ring_buf_init( - &uart_tx_ringbufs[i].rb, - sizeof(uart_tx_ringbufs[i].buf), - uart_tx_ringbufs[i].buf); - - if (UART_SET_PM_STATE) { - set_uart_power_state(i, false); - } - } - } - - return false; - } - - /* If event is unhandled, unsubscribe. */ - __ASSERT_NO_MSG(false); - - return false; -} -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); -APP_EVENT_SUBSCRIBE(MODULE, peer_conn_event); -APP_EVENT_SUBSCRIBE(MODULE, cdc_data_event); -APP_EVENT_SUBSCRIBE_FINAL(MODULE, uart_data_event); diff --git a/applications/ifmcu_firmware/src/modules/usb_bulk_commands.c b/applications/ifmcu_firmware/src/modules/usb_bulk_commands.c deleted file mode 100644 index 0b90337..0000000 --- a/applications/ifmcu_firmware/src/modules/usb_bulk_commands.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "led_state.h" - -#include -LOG_MODULE_REGISTER(bulk_commands, CONFIG_IFMCU_BULK_LOG_LEVEL); - -#define IFMCU_FW_INFO_STRING \ - "v" APP_VERSION_STRING "-g" STRINGIFY(APP_BUILD_VERSION) - -#define FULL_FW_INFO_STRING \ - "IFMCU Firmware v" APP_VERSION_STRING "-g" STRINGIFY(APP_BUILD_VERSION) "\r\n" \ - "Zephyr OS " STRINGIFY(BUILD_VERSION) "\r\n" \ - "nRF Connect SDK " STRINGIFY(NCS_BUILD_VERSION) "\r\n" \ - "Hardware: " CONFIG_BOARD_TARGET "\r\n" \ - "Build time: " __DATE__ " " __TIME__ "\r\n" - -#define ID_DAP_VENDOR19 (0x80 + 19) -#define ID_DAP_VENDOR20 (0x80 + 20) -#define ID_DAP_VENDOR21 (0x80 + 21) -#define ID_DAP_VENDOR22 (0x80 + 22) - -#define ID_DAP_VENDOR_NRF91_RESET ID_DAP_VENDOR19 -#define ID_DAP_VENDOR_IFMCU_RESET ID_DAP_VENDOR20 -#define ID_DAP_VENDOR_IFMCU_BOOTLOADER ID_DAP_VENDOR21 -#define ID_DAP_VENDOR_IFMCU_VERSION ID_DAP_VENDOR22 - -#define DAP_COMMAND_SUCCESS 0x00 -#define DAP_COMMAND_FAILED 0xFF - -#define NRF91_RESET_DURATION K_MSEC(100) - -#define USB_BULK_PACKET_SIZE 64 - -static const struct gpio_dt_spec reset_pin = - GPIO_DT_SPEC_GET_OR(DT_INST(0, zephyr_swdp_gpio), reset_gpios, {}); - -static void nrf91_reset_work_handler(struct k_work *work); -K_WORK_DELAYABLE_DEFINE(nrf91_reset_work, nrf91_reset_work_handler); - -static void ifmcu_reset_work_handler(struct k_work *work); -K_WORK_DELAYABLE_DEFINE(ifmcu_reset_work, ifmcu_reset_work_handler); - -static void ifmcu_bootloader_work_handler(struct k_work *work); -K_WORK_DELAYABLE_DEFINE(ifmcu_bootloader_work, ifmcu_bootloader_work_handler); - -/* Handler to reset the nRF91. */ -static void nrf91_reset_work_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - if (!(reset_pin.port && device_is_ready(reset_pin.port))) { - LOG_ERR("reset pin not available"); - return; - } - - /* assert both reset and button signals */ - gpio_pin_configure_dt(&reset_pin, GPIO_OUTPUT_LOW); - /* wait for reset to be registered */ - k_sleep(NRF91_RESET_DURATION); - gpio_pin_configure_dt(&reset_pin, GPIO_DISCONNECTED); -} - -/* Handler to enter the UF2 Bootloader of Interface MCU. */ -static void ifmcu_bootloader_work_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - NRF_POWER->GPREGRET = 0x57; - sys_reboot(SYS_REBOOT_COLD); -} - -/* Handler to reset the Interface MCU. */ -static void ifmcu_reset_work_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - sys_reboot(SYS_REBOOT_WARM); -} - -/* This is a placeholder implementation until proper CMSIS-DAP support is available. - * Only custom vendor commands are supported. - */ -size_t dap_execute_vendor_cmd(uint8_t *in, uint8_t *out) -{ - LOG_DBG("got command 0x%02X", in[0]); - - set_dap_led_state(LED_STATE_BLINK); - - if (in[0] < ID_DAP_VENDOR0) { - return dap_execute_cmd(in, out); - } - if (in[0] == ID_DAP_VENDOR_IFMCU_BOOTLOADER) { - if (!k_work_busy_get(&ifmcu_bootloader_work.work)) { - k_work_reschedule(&ifmcu_bootloader_work, K_NO_WAIT); - } - goto success; - } - if (in[0] == ID_DAP_VENDOR_IFMCU_RESET) { - if (!k_work_busy_get(&ifmcu_reset_work.work)) { - k_work_reschedule(&ifmcu_reset_work, K_NO_WAIT); - } - goto success; - } - if (in[0] == ID_DAP_VENDOR_NRF91_RESET) { - if (!k_work_busy_get(&nrf91_reset_work.work)) { - k_work_reschedule(&nrf91_reset_work, K_NO_WAIT); - } - goto success; - } - if (in[0] == ID_DAP_VENDOR_IFMCU_VERSION) { - const size_t VERSION_STRING_LEN = USB_BULK_PACKET_SIZE - 2; - - int len = snprintf(out + 2, VERSION_STRING_LEN, IFMCU_FW_INFO_STRING); - if (len < 0 || len >= VERSION_STRING_LEN) { - LOG_ERR("Failed to format version string"); - goto error; - } - out[0] = in[0]; - out[1] = len; - return len + 2; - } - -error: - /* default reply: command failed */ - out[0] = in[0]; - out[1] = DAP_COMMAND_FAILED; - return 2; -success: - out[0] = in[0]; - out[1] = DAP_COMMAND_SUCCESS; - return 2; -} - -#if defined(CONFIG_DK_LIBRARY) -static void button_handler(uint32_t button_states, uint32_t has_changed) -{ - if (has_changed & button_states & DK_BTN1_MSK) { - if (!k_work_busy_get(&nrf91_reset_work.work)) { - k_work_reschedule(&nrf91_reset_work, K_NO_WAIT); - } - } -} - -static int button_handling_init(void) -{ - int err = dk_buttons_init(button_handler); - - if (err) { - LOG_ERR("dk_buttons_init, error: %d", err); - } - return 0; -} - -SYS_INIT(button_handling_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); -#endif /* defined(CONFIG_DK_LIBRARY) */ - -static int cmd_version(const struct shell *sh, size_t argc, char **argv) -{ - if (argc == 1) { - shell_print(sh, IFMCU_FW_INFO_STRING); - return 0; - } - - /* No need to enable the getopt and getopt_long for just one option. */ - if (strcmp("-a", argv[1]) && strcmp("--all", argv[1]) != 0) { - shell_error(sh, "Unsupported option: %s", argv[1]); - return -EIO; - } - - shell_print(sh, FULL_FW_INFO_STRING); - - return 0; -} - -static int cmd_bootloader(const struct shell *sh, size_t argc, char **argv) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - shell_print(sh, "Entering IFMCU UF2 Bootloader mode..."); - - if (!k_work_busy_get(&ifmcu_bootloader_work.work)) { - k_work_reschedule(&ifmcu_bootloader_work, K_NO_WAIT); - } - - return 0; -} - -static int cmd_reset(const struct shell *sh, size_t argc, char **argv) -{ - if (argc == 1 || (strcmp("nrf9151", argv[1]) == 0)) { - /* Reset nRF9151 default */ - if (!k_work_busy_get(&nrf91_reset_work.work)) { - k_work_reschedule(&nrf91_reset_work, K_NO_WAIT); - } - return 0; - } - - if (strcmp("nrf52820", argv[1]) == 0) { - if (!k_work_busy_get(&ifmcu_reset_work.work)) { - k_work_reschedule(&ifmcu_reset_work, K_NO_WAIT); - } - } else { - shell_error(sh, "Unknown target: %s", argv[1]); - return -EIO; - } - - return 0; -} - -SHELL_CMD_ARG_REGISTER(version, NULL, - "Show IFMCU Firmware version.\n" - "Use -a or --all option to show more details.", - cmd_version, 1, 1); -SHELL_CMD_ARG_REGISTER(bootloader, NULL, - "Enter IFMCU UF2 Bootloader mode.", - cmd_bootloader, 1, 0); -SHELL_CMD_ARG_REGISTER(reset, NULL, - "Reset a target device.\n" - "Usage: reset [target]\n" - "[target] - nrf9151 or nrf52820 (default: nrf9151)", - cmd_reset, 1, 1); diff --git a/applications/ifmcu_firmware/src/modules/usb_bulk_interface.c b/applications/ifmcu_firmware/src/modules/usb_bulk_interface.c deleted file mode 100644 index 1a78ae2..0000000 --- a/applications/ifmcu_firmware/src/modules/usb_bulk_interface.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MODULE bulk_interface -#include "module_state_event.h" -#include - -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_BULK_LOG_LEVEL); - -/* needs to be included after defining logging config */ -#include "usb_bulk_msosv2.h" - -#include - -#define USB_BULK_PACKET_SIZE 64 -#define USB_BULK_PACKET_COUNT 4 - -/* placeholder for IN endpoint number, will be updated during USB init */ -#define DAP_USB_EP_IN 0x81 -/* placeholder for OUT endpoint number, will be updated during USB init */ -#define DAP_USB_EP_OUT 0x01 - -/* position of OUT endpoint in configuration array */ -#define DAP_USB_EP_OUT_IDX 0 -/* position of IN endpoint in configuration array */ -#define DAP_USB_EP_IN_IDX 1 - -/* bulk RX FIFO and associated NET buf pool */ -static K_FIFO_DEFINE(dap_rx_queue); -NET_BUF_POOL_FIXED_DEFINE(dapusb_rx_pool, USB_BULK_PACKET_COUNT, USB_BULK_PACKET_SIZE, 0, NULL); - -/* Execute CMSIS-DAP command and write reply into output buffer */ -size_t dap_execute_vendor_cmd(uint8_t *in, uint8_t *out); - -/* string descriptor for the interface */ -#define DAP_IFACE_STR_DESC "CMSIS-DAP v2" - -struct dap_iface_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bString[USB_BSTRING_LENGTH(DAP_IFACE_STR_DESC)]; -} __packed; - -USBD_STRING_DESCR_USER_DEFINE(primary) -struct dap_iface_descriptor dap_iface_desc = { - .bLength = USB_STRING_DESCRIPTOR_LENGTH(DAP_IFACE_STR_DESC), - .bDescriptorType = USB_DESC_STRING, - .bString = DAP_IFACE_STR_DESC}; - -/* USB Class descriptor for custom interface */ -USBD_CLASS_DESCR_DEFINE(primary, 0) struct { - struct usb_if_descriptor if0; - struct usb_ep_descriptor if0_out_ep; - struct usb_ep_descriptor if0_in_ep; -} __packed dapusb_desc = { - .if0 = { - .bLength = sizeof(struct usb_if_descriptor), - .bDescriptorType = USB_DESC_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_BCC_VENDOR, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - }, - .if0_out_ep = { - .bLength = sizeof(struct usb_ep_descriptor), - .bDescriptorType = USB_DESC_ENDPOINT, - .bEndpointAddress = DAP_USB_EP_OUT, - .bmAttributes = USB_DC_EP_BULK, - .wMaxPacketSize = sys_cpu_to_le16(USB_BULK_PACKET_SIZE), - .bInterval = 0, - }, - .if0_in_ep = { - .bLength = sizeof(struct usb_ep_descriptor), - .bDescriptorType = USB_DESC_ENDPOINT, - .bEndpointAddress = DAP_USB_EP_IN, - .bmAttributes = USB_DC_EP_BULK, - .wMaxPacketSize = sys_cpu_to_le16(USB_BULK_PACKET_SIZE), - .bInterval = 0, - }, -}; - -static struct usb_ep_cfg_data dapusb_ep_data[] = { - [DAP_USB_EP_OUT_IDX] = {.ep_cb = usb_transfer_ep_callback, .ep_addr = DAP_USB_EP_OUT}, - [DAP_USB_EP_IN_IDX] = {.ep_cb = usb_transfer_ep_callback, .ep_addr = DAP_USB_EP_IN}, -}; - -/* helper function to connect string descriptor to the interface during USB init */ -static void iface_string_desc_init(struct usb_cfg_data *bulk_cfg) -{ - struct usb_if_descriptor *bulk_if = bulk_cfg->interface_descriptor; - - bulk_if->iInterface = usb_get_str_descriptor_idx(&dap_iface_desc); -} - -void dapusb_interface_config(struct usb_desc_header *head, uint8_t bInterfaceNumber) -{ - ARG_UNUSED(head); - - dapusb_desc.if0.bInterfaceNumber = bInterfaceNumber; -#if defined(CONFIG_USB_COMPOSITE_DEVICE) - msosv2_cmsis_dap_desc.subset_header.bFirstInterface = bInterfaceNumber; -#endif -} - -static void dapusb_read_cb(uint8_t ep, int size, void *priv) -{ - struct usb_cfg_data *cfg = priv; - struct net_buf *buf; - static uint8_t rx_buf[USB_BULK_PACKET_SIZE]; - - LOG_DBG("cfg %p ep %x size %u", cfg, ep, size); - - if (size <= 0) { - goto read_cb_done; - } - - buf = net_buf_alloc(&dapusb_rx_pool, K_FOREVER); - net_buf_add_mem(buf, rx_buf, MIN(size, USB_BULK_PACKET_SIZE)); - k_fifo_put(&dap_rx_queue, buf); - -read_cb_done: - usb_transfer(ep, rx_buf, sizeof(rx_buf), USB_TRANS_READ, dapusb_read_cb, cfg); -} - -/* when USB device is configured, start reading RX endpoint */ -static void dapusb_dev_status_cb(struct usb_cfg_data *cfg, enum usb_dc_status_code status, - const uint8_t *param) -{ - ARG_UNUSED(param); - - LOG_WRN("USB status %d", status); - - if (status == USB_DC_CONFIGURED) { - dapusb_read_cb(cfg->endpoint[DAP_USB_EP_OUT_IDX].ep_addr, 0, cfg); - } -} - -/* add interface to USB configuration */ -USBD_DEFINE_CFG_DATA(dapusb_config) = { - .usb_device_description = NULL, - .interface_config = dapusb_interface_config, - .interface_descriptor = &dapusb_desc.if0, - .cb_usb_status = dapusb_dev_status_cb, - .interface = { - .class_handler = NULL, - .custom_handler = NULL, - .vendor_handler = msosv2_vendor_handle_req, - }, - .num_endpoints = ARRAY_SIZE(dapusb_ep_data), - .endpoint = dapusb_ep_data -}; - -static int dap_usb_process(void) -{ - size_t len; - int err; - static uint8_t tx_buf[USB_BULK_PACKET_SIZE]; - struct net_buf *buf = k_fifo_get(&dap_rx_queue, K_FOREVER); - uint8_t ep = dapusb_config.endpoint[DAP_USB_EP_IN_IDX].ep_addr; -#if defined(CONFIG_IFMCU_CMSIS_DAP_VENDOR_COMMANDS) - len = dap_execute_vendor_cmd(buf->data, tx_buf); -#else - len = dap_execute_cmd(buf->data, tx_buf); -#endif /* defined(CONFIG_IFMCU_CMSIS_DAP_VENDOR_COMMANDS) */ - LOG_DBG("response length %u, starting with [0x%02X, 0x%02X]", len, tx_buf[0], tx_buf[1]); - net_buf_unref(buf); - - err = usb_transfer_sync(ep, tx_buf, len, USB_TRANS_WRITE | USB_TRANS_NO_ZLP); - if (err < 0 || err != len) { - LOG_ERR("usb_transfer_sync failed, %d", err); - return -EIO; - } - - return 0; -} - -static int dap_usb_thread_fn(const struct device *dev) -{ - ARG_UNUSED(dev); - - while (1) { - dap_usb_process(); - } - - return 0; -} - -const struct device *const swd_dev = DEVICE_DT_GET_ONE(zephyr_swdp_gpio); - -K_THREAD_DEFINE(dap_usb_thread, - CONFIG_BULK_USB_THREAD_STACK_SIZE, dap_usb_thread_fn, NULL, NULL, NULL, 5, 0, 0); - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_module_state_event(aeh)) { - const struct module_state_event *event = cast_module_state_event(aeh); - - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - /* tell the rest of the system that we are busy. */ - module_set_state(MODULE_STATE_READY); - - /* add MS OS 2.0 BOS descriptor to BOS structure. */ - usb_bos_register_cap((void *)&bos_cap_msosv2); - /* point interface index to string descriptor. */ - iface_string_desc_init(&dapusb_config); - - if (!device_is_ready(swd_dev)) { - LOG_ERR("SWD device is not ready"); - } - - int ret = dap_setup(swd_dev); - - if (ret) { - LOG_ERR("Failed to initialize DAP controller, %d", ret); - } - - /* tell the usb_cdc_handler we are done. */ - module_set_state(MODULE_STATE_STANDBY); - } - return false; - } - /* we should not reach this point */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); diff --git a/applications/ifmcu_firmware/src/modules/usb_bulk_msosv2.h b/applications/ifmcu_firmware/src/modules/usb_bulk_msosv2.h deleted file mode 100644 index eaa54a8..0000000 --- a/applications/ifmcu_firmware/src/modules/usb_bulk_msosv2.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */ -#define CMSIS_DAP_V2_DEVICE_INTERFACE_GUID \ - '{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, '3', 0x00, 'B', 0x00, \ - '5', 0x00, 'A', 0x00, 'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, \ - '3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, '6', 0x00, '6', 0x00, \ - '3', 0x00, '-', 0x00, 'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, \ - '-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, 'E', 0x00, '4', 0x00, \ - '6', 0x00, '4', 0x00, '6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, \ - '6', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 - -#define COMPATIBLE_ID_WINUSB \ - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 - -#define WINUSB_VENDOR_CODE 0x20 - -static struct msosv2_descriptor { - struct msosv2_descriptor_set_header header; -#if defined(CONFIG_USB_COMPOSITE_DEVICE) - struct msosv2_function_subset_header subset_header; -#endif - struct msosv2_compatible_id compatible_id; - struct msosv2_guids_property guids_property; -} __packed msosv2_cmsis_dap_desc = { - /* - * Microsoft OS 2.0 descriptor set. This tells Windows what kind - * of device this is and to install the WinUSB driver. - */ - .header = { - .wLength = sizeof(struct msosv2_descriptor_set_header), - .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, - .dwWindowsVersion = 0x06030000, - .wTotalLength = sizeof(struct msosv2_descriptor), - }, -#if defined(CONFIG_USB_COMPOSITE_DEVICE) - .subset_header = { - .wLength = sizeof(struct msosv2_function_subset_header), - .wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION, - .wSubsetLength = sizeof(struct msosv2_function_subset_header) - + sizeof(struct msosv2_compatible_id) - + sizeof(struct msosv2_guids_property), - }, -#endif - .compatible_id = { - .wLength = sizeof(struct msosv2_compatible_id), - .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, - .CompatibleID = {COMPATIBLE_ID_WINUSB}, - }, - .guids_property = { - .wLength = sizeof(struct msosv2_guids_property), - .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, - .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, - .wPropertyNameLength = 42, - .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, - .wPropertyDataLength = 80, - .bPropertyData = {CMSIS_DAP_V2_DEVICE_INTERFACE_GUID}, - }, -}; - -USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { - struct usb_bos_platform_descriptor platform; - struct usb_bos_capability_msos cap; -} __packed bos_cap_msosv2 = { - /* Microsoft OS 2.0 Platform Capability Descriptor */ - .platform = { - .bLength = sizeof(struct usb_bos_platform_descriptor) - + sizeof(struct usb_bos_capability_msos), - .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, - .bReserved = 0, - .PlatformCapabilityUUID = { - /** - * MS OS 2.0 Platform Capability ID - * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F - */ - 0xDF, 0x60, 0xDD, 0xD8, - 0x89, 0x45, - 0xC7, 0x4C, - 0x9C, 0xD2, - 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, - }, - }, - .cap = { - /* Windows version (8.1) (0x06030000) */ - .dwWindowsVersion = sys_cpu_to_le32(0x06030000), - .wMSOSDescriptorSetTotalLength = - sys_cpu_to_le16(sizeof(msosv2_cmsis_dap_desc)), - .bMS_VendorCode = WINUSB_VENDOR_CODE, - .bAltEnumCode = 0x00 - }, -}; - -static int msosv2_vendor_handle_req(struct usb_setup_packet *setup, - int32_t *len, uint8_t **data) -{ - if (usb_reqtype_is_to_device(setup)) { - return -ENOTSUP; - } - - if (setup->bRequest == WINUSB_VENDOR_CODE && - setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { - *data = (uint8_t *)(&msosv2_cmsis_dap_desc); - *len = sizeof(msosv2_cmsis_dap_desc); - - LOG_DBG("Get MS OS Descriptors v2"); - - return 0; - } - - return -ENOTSUP; -} diff --git a/applications/ifmcu_firmware/src/modules/usb_cdc_handler.c b/applications/ifmcu_firmware/src/modules/usb_cdc_handler.c deleted file mode 100644 index fe533f1..0000000 --- a/applications/ifmcu_firmware/src/modules/usb_cdc_handler.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include -#include - -#define MODULE usb_cdc -#include "module_state_event.h" -#include "peer_conn_event.h" -#include "cdc_data_event.h" -#include "uart_data_event.h" - -#include -LOG_MODULE_REGISTER(MODULE, CONFIG_IFMCU_CDC_LOG_LEVEL); - -static const struct device *devices[] = { - DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)), -}; - -#define CDC_DEVICE_COUNT ARRAY_SIZE(devices) - -#define USB_CDC_DTR_POLL_MS 500 -#define USB_CDC_RX_BLOCK_SIZE CONFIG_IFMCU_BUF_SIZE -#define USB_CDC_RX_BLOCK_COUNT (CDC_DEVICE_COUNT * 3) -#define USB_CDC_SLAB_ALIGNMENT 4 - -static void cdc_dtr_timer_handler(struct k_timer *timer); -static void cdc_dtr_work_handler(struct k_work *work); - -static K_TIMER_DEFINE(cdc_dtr_timer, cdc_dtr_timer_handler, NULL); -static K_WORK_DEFINE(cdc_dtr_work, cdc_dtr_work_handler); -/* Incoming data from any CDC instance is copied into a block from this slab */ -K_MEM_SLAB_DEFINE(cdc_rx_slab, USB_CDC_RX_BLOCK_SIZE, USB_CDC_RX_BLOCK_COUNT, USB_CDC_SLAB_ALIGNMENT); - -static uint32_t cdc_ready[CDC_DEVICE_COUNT]; -static uint32_t cdc_baudrate[CDC_DEVICE_COUNT]; - -static uint8_t overflow_buf[64]; - -static bool bulk_module_ready; - -static void cdc_dtr_timer_handler(struct k_timer *timer) -{ - k_work_submit(&cdc_dtr_work); -} - -static void poll_dtr(void) -{ - for (int i = 0; i < CDC_DEVICE_COUNT; ++i) { - int err; - uint32_t cdc_val; - uint32_t baudrate; - - err = uart_line_ctrl_get(devices[i], - UART_LINE_CTRL_DTR, - &cdc_val); - if (err) { - LOG_WRN("uart_line_ctrl_get(DTR): %d", err); - continue; - } - - err = uart_line_ctrl_get(devices[i], - UART_LINE_CTRL_BAUD_RATE, - &baudrate); - if (err) { - LOG_WRN("uart_line_ctrl_get(BAUD_RATE): %d", err); - continue; - } - - if (cdc_val != cdc_ready[i] || baudrate != cdc_baudrate[i]) { - struct peer_conn_event *event = new_peer_conn_event(); - - event->peer_id = PEER_ID_USB; - event->dev_idx = i; - event->baudrate = baudrate; - event->conn_state_changed = cdc_val != cdc_ready[i]; - event->conn_state = - cdc_val == 0 ? PEER_STATE_DISCONNECTED : PEER_STATE_CONNECTED; - APP_EVENT_SUBMIT(event); - - cdc_ready[i] = cdc_val; - cdc_baudrate[i] = baudrate; - } - } -} - -static void cdc_dtr_work_handler(struct k_work *work) -{ - poll_dtr(); -} - -static void cdc_uart_interrupt_handler(const struct device *dev, void *user_data) -{ - int dev_idx = (int) user_data; - - uart_irq_update(dev); - - while (uart_irq_rx_ready(dev)) { - void *rx_buf; - int err; - int data_length; - - poll_dtr(); - - err = k_mem_slab_alloc(&cdc_rx_slab, &rx_buf, K_NO_WAIT); - if (err) { - data_length = uart_fifo_read( - dev, - overflow_buf, - sizeof(overflow_buf)); - LOG_WRN("CDC_%d RX overflow", dev_idx); - } else { - data_length = uart_fifo_read( - dev, - rx_buf, - USB_CDC_RX_BLOCK_SIZE); - - if (data_length) { - struct cdc_data_event *event = new_cdc_data_event(); - - event->dev_idx = dev_idx; - event->buf = rx_buf; - event->len = data_length; - APP_EVENT_SUBMIT(event); - } else { - k_mem_slab_free(&cdc_rx_slab, rx_buf); - } - } - } -} - -static void enable_rx_irq(int dev_idx) -{ - uart_irq_callback_user_data_set( - devices[dev_idx], - cdc_uart_interrupt_handler, - (void *)dev_idx); - uart_irq_rx_enable(devices[dev_idx]); -} - -static void usbd_status(enum usb_dc_status_code cb_status, const uint8_t *param) -{ - switch (cb_status) { - case USB_DC_ERROR: - LOG_ERR("USB_DC_ERROR"); - break; - case USB_DC_RESET: - LOG_DBG("USB_DC_RESET"); - break; - case USB_DC_CONNECTED: - LOG_DBG("USB_DC_CONNECTED"); - module_set_state(MODULE_STATE_READY); - break; - case USB_DC_CONFIGURED: - LOG_DBG("USB_DC_CONFIGURED"); - break; - case USB_DC_DISCONNECTED: - LOG_DBG("USB_DC_DISCONNECTED"); - module_set_state(MODULE_STATE_STANDBY); - break; - case USB_DC_SUSPEND: - LOG_DBG("USB_DC_SUSPEND"); - break; - case USB_DC_RESUME: - LOG_DBG("USB_DC_RESUME"); - break; - default: - break; - } -} - -static bool app_event_handler(const struct app_event_header *aeh) -{ - if (is_uart_data_event(aeh)) { - const struct uart_data_event *event = - cast_uart_data_event(aeh); - int tx_written; - - if (event->dev_idx >= CDC_DEVICE_COUNT) { - return false; - } - - if (cdc_ready[event->dev_idx] == 0) { - return false; - } - - tx_written = uart_fifo_fill( - devices[event->dev_idx], - event->buf, - event->len); - - if (tx_written != event->len) { - LOG_DBG("UART_%d->CDC_%d overflow", - event->dev_idx, - event->dev_idx); - } - - return false; - } - - if (is_cdc_data_event(aeh)) { - const struct cdc_data_event *event = - cast_cdc_data_event(aeh); - - /* All subscribers have gotten a chance to copy data at this point */ - k_mem_slab_free(&cdc_rx_slab, (void *)event->buf); - - return true; - } - - if (is_module_state_event(aeh)) { - const struct module_state_event *event = - cast_module_state_event(aeh); - -#if CONFIG_IFMCU_CMSIS_DAP_BULK_ENABLE - if (check_state(event, MODULE_ID(bulk_interface), MODULE_STATE_STANDBY)) { - /* Enable USBD once file system is populated */ - bulk_module_ready = true; - } -#endif - if ((!IS_ENABLED(CONFIG_IFMCU_CMSIS_DAP_BULK_ENABLE) || bulk_module_ready)) { - /* Enable USBD */ - int err; - - err = usb_enable(usbd_status); - if (err) { - LOG_ERR("usb_enable: %d", err); - return false; - } - for (int i = 0; i < CDC_DEVICE_COUNT; ++i) { - cdc_ready[i] = 0; - if (device_is_ready(devices[i])) { - enable_rx_irq(i); - LOG_DBG("%s available", devices[i]->name); - } else { - LOG_ERR("%s not available", devices[i]->name); - } - } - - /* CDC port status needs to be polled (no irq/callback) */ - /* (keeping serial ports open has a power penalty) */ - k_timer_start( - &cdc_dtr_timer, - K_MSEC(USB_CDC_DTR_POLL_MS), - K_MSEC(USB_CDC_DTR_POLL_MS)); - } - - return false; - } - - /* If event is unhandled, unsubscribe. */ - __ASSERT_NO_MSG(false); - - return false; -} - -APP_EVENT_LISTENER(MODULE, app_event_handler); -APP_EVENT_SUBSCRIBE(MODULE, module_state_event); -APP_EVENT_SUBSCRIBE(MODULE, uart_data_event); -APP_EVENT_SUBSCRIBE_FINAL(MODULE, cdc_data_event); diff --git a/applications/ifmcu_firmware/src/modules/utils.c b/applications/ifmcu_firmware/src/modules/utils.c deleted file mode 100644 index 306dddc..0000000 --- a/applications/ifmcu_firmware/src/modules/utils.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * Copyright (c) 2016-2025 Makerdiary - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(utils, CONFIG_IFMCU_UTILS_LOG_LEVEL); - -static const struct device *temp_sensor = DEVICE_DT_GET(DT_ALIAS(die_temp)); - -static const struct gpio_dt_spec viosel_gpio = - GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), viosel_gpios, {}); - -static const struct gpio_dt_spec simdet_gpio = - GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), simdet_gpios, {}); - -static int viosel = -1; - -static int cmd_temp(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - struct sensor_value val; - - if (!device_is_ready(temp_sensor)) { - shell_error(sh, "sensor: device %s not ready.", temp_sensor->name); - return -ENODEV; - } - - /* fetch sensor samples */ - ret = sensor_sample_fetch(temp_sensor); - if (ret) { - shell_error(sh, "Failed to fetch sample (%d).", ret); - return ret; - } - - ret = sensor_channel_get(temp_sensor, SENSOR_CHAN_DIE_TEMP, &val); - if (ret) { - shell_error(sh, "Failed to get data (%d).", ret); - return ret; - } - - shell_print(sh, "%d.%d °C", val.val1, val.val2/100000); - - return 0; -} - -static int cmd_simdet(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - - if (!device_is_ready(simdet_gpio.port)) { - shell_error(sh, "SIMDET GPIO controller not ready."); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&simdet_gpio, GPIO_INPUT); - if (ret < 0) { - shell_error(sh, "Could not configure SIMDET GPIO."); - return ret; - } - - k_sleep(K_MSEC(1)); /* Wait for the rail to come up and stabilize */ - - ret = gpio_pin_get_dt(&simdet_gpio); - if (ret < 0) { - shell_error(sh, "Could not read SIMDET GPIO."); - goto error; - } else { - shell_print(sh, "%s: %s", argv[0], ret? "Inserted" : "Uninserted"); - } - -error: - ret = gpio_pin_configure_dt(&simdet_gpio, GPIO_DISCONNECTED); - return ret; -} - -int viosel_set(int val) -{ - int ret; - - if (!device_is_ready(viosel_gpio.port)) { - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&viosel_gpio, val? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - return ret; - } - - viosel = val; - - return 0; -} - -int viosel_get(void) -{ - return viosel; -} - -static int cmd_viosel(const struct shell *sh, size_t argc, char **argv) -{ - int ret; - char *endptr; - long val; - - if (argc == 1) { - if (viosel < 0) { - shell_print(sh, "VIO = 3.3V def."); - } else { - shell_print(sh, "VIO = %s", viosel? "1.8V" : "3.3V"); - - } - return 0; - } - - endptr = argv[1]; - val = strtol(argv[1], &endptr, 10); - if ((endptr == argv[1]) || ((val != 0) && (val != 1))) { - shell_error(sh, " must be 0 or 1"); - return -EINVAL; - } - - ret = gpio_pin_configure_dt(&viosel_gpio, val? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - shell_error(sh, "Cannot configure VIOSEL (%d)", ret); - return ret; - } - - viosel = (int)val; - - return 0; -} - -SHELL_CMD_ARG_REGISTER(temp, NULL, - "Get the die temperature", cmd_temp, 1, 0); -SHELL_CMD_ARG_REGISTER(simdet, NULL, - "Display nano-SIM Card status", cmd_simdet, 1, 0); -SHELL_CMD_ARG_REGISTER(viosel, NULL, - "Get or set VIO voltage\n" - "Usage: viosel [sel: 0|1]\n" - "[sel: 0|1] - 3.3V|1.8V", cmd_viosel, 1, 1); diff --git a/applications/modem_shell/CMakeLists.txt b/applications/modem_shell/CMakeLists.txt deleted file mode 100644 index b68a527..0000000 --- a/applications/modem_shell/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(MOSH) -target_include_directories(app PRIVATE src) - -target_sources(app PRIVATE src/main.c) -target_sources(app PRIVATE src/shell.c) - -add_subdirectory(src/print) -add_subdirectory(src/utils) -add_subdirectory(src/uart) -add_subdirectory(src/at) -add_subdirectory(src/link) -add_subdirectory_ifdef(CONFIG_MOSH_NRF91_NON_OFFLOADING_DEV src/drivers) -add_subdirectory_ifdef(CONFIG_MOSH_WORKER_THREADS src/th) -add_subdirectory_ifdef(CONFIG_MOSH_SOCK src/sock) -add_subdirectory_ifdef(CONFIG_MOSH_PING src/ping) -add_subdirectory_ifdef(CONFIG_MOSH_GNSS src/gnss) -add_subdirectory_ifdef(CONFIG_MOSH_SMS src/sms) -add_subdirectory_ifdef(CONFIG_MOSH_LOCATION src/location) -add_subdirectory_ifdef(CONFIG_MOSH_PPP src/ppp) -add_subdirectory_ifdef(CONFIG_MOSH_FOTA src/fota) -add_subdirectory_ifdef(CONFIG_MOSH_REST src/rest) -add_subdirectory_ifdef(CONFIG_MOSH_STARTUP_CMDS src/startup_cmd) -add_subdirectory_ifdef(CONFIG_MOSH_GPIO_COUNT src/gpio_count) -add_subdirectory(src/cloud) - -if(NOT ENV{PROJECT_NAME}) - zephyr_compile_definitions( - PROJECT_NAME=${CMAKE_PROJECT_NAME} - ) -endif() diff --git a/applications/modem_shell/Kconfig b/applications/modem_shell/Kconfig deleted file mode 100644 index 1dd2a61..0000000 --- a/applications/modem_shell/Kconfig +++ /dev/null @@ -1,249 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -menu "Nordic Modem Shell config" - -config MOSH_IPERF3 - bool "iPerf3" - default y - select NRF_IPERF3 - -config NRF_IPERF3_PROMPTLESS - bool - default y - -config MOSH_SOCK - bool "Socket tool" - default y - help - Socket tool with TCP, UDP, RAW, IPv4, IPv6 and packet socket support. - -config MOSH_PING - bool "ICMP ping" - default y - help - Ping is a tool for testing the reachability of a host on an IP network. - -config MOSH_CURL - bool "cURL" - default y - select NRF_CURL - -config NRF_CURL_PROMPTLESS - bool - default y - -config MOSH_GNSS - bool "GNSS" - default y - help - GNSS feature for searching the location of the device. - -config MOSH_PPP - bool "PPP" - help - Point-to-Point Protocol for enabling dial-up access to the Internet. - -config MOSH_SMS - bool "SMS" - default y - help - SMS tool for sending and receiving SMS messages. - -config MOSH_LOCATION - bool "Location" - default y - select LOCATION - select NRF_CLOUD_LOCATION if MOSH_CLOUD_MQTT && (LOCATION_METHOD_CELLULAR || LOCATION_METHOD_WIFI) - help - Tool for location queries via location library. - -config MOSH_FOTA - bool "FOTA" - default y - help - FOTA for performing software updates over-the-air for both modem and application side. - -config MOSH_REST - bool "REST client" - default y - select REST_CLIENT - help - REST client for sending and receiving simple REST requests/responses. - -config MOSH_CLOUD_REST - bool "nRFCloud commands over REST" - default y - select NRF_CLOUD_REST - select MODEM_JWT - select NRF_CLOUD_AGNSS_FILTERED if NRF_CLOUD_AGNSS && !NRF_CLOUD_MQTT - select NRF_CLOUD_AGNSS_FILTERED_RUNTIME if NRF_CLOUD_AGNSS && !NRF_CLOUD_MQTT - -config MOSH_CLOUD_MQTT - bool "MQTT connection to nRF Cloud" - select NRF_CLOUD_MQTT - help - MQTT connection to nRF Cloud. - -config MOSH_CLOUD_COAP - bool "CoAP connection to nRF Cloud" - select NRF_CLOUD_COAP - select MODEM_JWT - help - CoAP connection to nRF Cloud. - -config MOSH_CLOUD_LWM2M - bool "Cloud connection using LwM2M" - help - Cloud connection using LwM2M. - -config MOSH_AT_CMD_MODE - bool "Specific AT command mode" - default y - -config MOSH_GPIO_COUNT - bool "GPIO pin pulse counter" - default n if BOARD_THINGY91_NRF9160_NS - default y - help - Tool for counting the number of pulses on a GPIO pin. - -config MOSH_PRINT_BUFFER_SIZE - int "Buffer size used when printing modem shell output" - default 1024 - help - If the printed string exceeds this buffer, an error message is printed first and - then the requested string cut into the length of this buffer. - -config MOSH_COMMON_WORKQUEUE_STACK_SIZE - int "Common workqueue stack size" - default 7168 if MOSH_CLOUD_REST || MOSH_CLOUD_MQTT - default 6144 if MOSH_STARTUP_CMDS && MOSH_CURL - default 4096 - -config MOSH_COMMON_WORKQUEUE_PRIORITY - int "Common workqueue priority" - default 5 - -if NRF_IPERF3 - -config NRF_IPERF3_RESULTS_WAIT_TIME - default 180 -endif - -if MOSH_IPERF3 || MOSH_PING -menu "MoSH iperf3 and ping command selections" - -config MOSH_WORKER_THREADS - bool "Possibility to run iperf3 or ping instances in separate threads" - default y - -config MOSH_STARTUP_CMDS - bool "Possibility to run stored MoSh commands from settings after bootup" - default y - -config MOSH_NRF91_NON_OFFLOADING_DEV - bool "Possibility to run iperf3 with Zephyr TCP/IP stack" - -endmenu -endif - -if MOSH_AT_CMD_MODE -choice - prompt "Command termination" - default MOSH_AT_CMD_MODE_CR_LF_TERMINATION - help - Sets the command termination ending from the serial terminal - Levels are: - - NULL Termination - - CR Termination - - LF Termination - - CR+LF Termination - config MOSH_AT_CMD_MODE_NULL_TERMINATION - bool "NULL Termination" - config MOSH_AT_CMD_MODE_CR_TERMINATION - bool "CR Termination" - config MOSH_AT_CMD_MODE_LF_TERMINATION - bool "LF Termination" - config MOSH_AT_CMD_MODE_CR_LF_TERMINATION - bool "CR+LF Termination" -endchoice -config MOSH_AT_CMD_MODE_TERMINATION - int - default 0 if MOSH_AT_CMD_MODE_NULL_TERMINATION - default 1 if MOSH_AT_CMD_MODE_CR_TERMINATION - default 2 if MOSH_AT_CMD_MODE_LF_TERMINATION - default 3 if MOSH_AT_CMD_MODE_CR_LF_TERMINATION -endif - -menu "MoSH link control selections" - -config MOSH_LINK_SETT_NORMAL_MODE_AT_CMD_STR_LEN - int "Link settings AT command length" - default 127 - help - String length for custom AT commands stored into settings to be used - when going to normal mode. - -endmenu - -if MOSH_WORKER_THREADS - -config MOSH_WORKER_THREADS_OUTPUT_BUFFER_SIZE - int "Buffer size for storing output of the background thread commands" - default 4096 - -config MOSH_WORKER_THREADS_STACK_SIZE - int "Worker thread stack size" - default 4096 - -endif #MOSH_WORKER_THREADS - -if MOSH_CLOUD_LWM2M - -config MOSH_LWM2M_PSK - string "LwM2M pre-shared key for communication" - help - Pre-shared key must be identical to the PSK registered with the device on the LwM2M server. - Use the hexadecimal representation. - -config MOSH_LWM2M_ENDPOINT_PREFIX - string "Prefix used in the LwM2M endpoint name" - default "urn:imei:" - help - Sets the prefix of the endpoint name used when connecting to the LwM2M server. - -# Make AVSystem the default LwM2M server. -config LWM2M_CLIENT_UTILS_SERVER - string "LwM2M server address" - default "coaps://eu.iot.avsystem.cloud:5684" - help - Kconfig redefinition, please see the help text of the original definition. - -endif # MOSH_CLOUD_LWM2M - -# For power measurement purposes, activate low power mode for asynchronous UARTs. -if UART_0_ASYNC - -config UART_0_NRF_ASYNC_LOW_POWER - bool "Low power mode" - default y - -endif # UART_0_ASYNC - -if UART_1_ASYNC - -config UART_1_NRF_ASYNC_LOW_POWER - bool "Low power mode" - default y - -endif # UART_1_ASYNC - -endmenu # Modem Shell - -menu "Zephyr Kernel" -source "Kconfig.zephyr" -endmenu diff --git a/applications/modem_shell/overlay-app_fota.conf b/applications/modem_shell/overlay-app_fota.conf deleted file mode 100644 index 62b2d6b..0000000 --- a/applications/modem_shell/overlay-app_fota.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Some of the MoSh features need to be switched off to free enough flash -CONFIG_MOSH_IPERF3=n -CONFIG_MOSH_CURL=n -CONFIG_MOSH_REST=n -CONFIG_MOSH_WORKER_THREADS=n -CONFIG_MOSH_LOCATION=n - -CONFIG_BOOTLOADER_MCUBOOT=y -CONFIG_IMG_MANAGER=y -CONFIG_STREAM_FLASH=y -CONFIG_IMG_ERASE_PROGRESSIVELY=y diff --git a/applications/modem_shell/overlay-carrier.conf b/applications/modem_shell/overlay-carrier.conf deleted file mode 100644 index eb6c7c9..0000000 --- a/applications/modem_shell/overlay-carrier.conf +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_LWM2M_CARRIER=y -CONFIG_LWM2M_CARRIER_SETTINGS=y -CONFIG_LWM2M_CARRIER_SHELL=y - -CONFIG_FLASH=y -CONFIG_FLASH_PAGE_LAYOUT=y - -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -CONFIG_NVS=y -CONFIG_NVS_LOG_LEVEL_OFF=y - -CONFIG_DOWNLOADER=y - -CONFIG_MODEM_KEY_MGMT=y - -CONFIG_REBOOT=y - -# Some of the MoSh features need to be switched off to free enough flash -CONFIG_MOSH_REST=n -CONFIG_MOSH_WORKER_THREADS=n - -# Also modem shell FOTA support needs to be disabled -CONFIG_MOSH_FOTA=n -CONFIG_BOOTLOADER_MCUBOOT=n -CONFIG_IMG_MANAGER=n -CONFIG_IMG_ERASE_PROGRESSIVELY=n - -# DFU target library -CONFIG_DFU_TARGET=y - -# IPv4 (IPv6 is enabled by default) -CONFIG_NET_IPV4=y diff --git a/applications/modem_shell/overlay-cloud_coap.conf b/applications/modem_shell/overlay-cloud_coap.conf deleted file mode 100644 index 799fcc3..0000000 --- a/applications/modem_shell/overlay-cloud_coap.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Modem Shell -CONFIG_MOSH_CLOUD_COAP=y -CONFIG_MOSH_CLOUD_REST=n - -# Zephyr CoAP client -CONFIG_COAP_CLIENT=y -CONFIG_COAP_CLIENT_BLOCK_SIZE=1024 -CONFIG_COAP_CLIENT_STACK_SIZE=6144 -CONFIG_COAP_CLIENT_THREAD_PRIORITY=0 -CONFIG_COAP_EXTENDED_OPTIONS_LEN=y -CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=80 - -# Report standard information to shadow -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS=y -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_NETWORK=y -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_SIM=y -CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_UI=y -CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_FOTA=n -CONFIG_NRF_CLOUD_ENABLE_SVC_INF_UI_RSRP=n diff --git a/applications/modem_shell/overlay-cloud_mqtt.conf b/applications/modem_shell/overlay-cloud_mqtt.conf deleted file mode 100644 index 9daff37..0000000 --- a/applications/modem_shell/overlay-cloud_mqtt.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Modem Shell -CONFIG_MOSH_CLOUD_MQTT=y -CONFIG_MOSH_CLOUD_REST=n - -# Report standard information to shadow -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS=y -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_NETWORK=y -CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_SIM=y -CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_UI=y -CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_FOTA=n -CONFIG_NRF_CLOUD_ENABLE_SVC_INF_UI_RSRP=n diff --git a/applications/modem_shell/overlay-debug.conf b/applications/modem_shell/overlay-debug.conf deleted file mode 100644 index b07d0b7..0000000 --- a/applications/modem_shell/overlay-debug.conf +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Forces a maximal log level for all modules. -# Modules saturates their specified level if it is greater than this option, -# otherwise they use the level specified by this option instead of their default -# or whatever was manually set. Levels are: -# -# 0 OFF, logging is turned off -# 1 ERROR, maximal level set to LOG_LEVEL_ERR -# 2 WARNING, maximal level set to LOG_LEVEL_WRN -# 3 INFO, maximal level set to LOG_LEVEL_INFO -# 4 DEBUG, maximal level set to LOG_LEVEL_DBG -CONFIG_LOG_MAX_LEVEL=4 - -# Increase log buffer size to prevent logs being dropped. -CONFIG_LOG_BUFFER_SIZE=2048 - -# Location library -CONFIG_LOCATION_LOG_LEVEL_DBG=y - -# SMS library -CONFIG_SMS_LOG_LEVEL_DBG=y - -# nRF Cloud -CONFIG_NRF_CLOUD_LOG_LEVEL_DBG=y -CONFIG_NRF_CLOUD_GPS_LOG_LEVEL_DBG=y -CONFIG_NRF_CLOUD_REST_LOG_LEVEL_DBG=y - -# REST client library -CONFIG_REST_CLIENT_LOG_LEVEL_DBG=y - -# Date time -CONFIG_DATE_TIME_LOG_LEVEL_DBG=y - -# Settings -CONFIG_SETTINGS_LOG_LEVEL_DBG=y - -# nRF Modem Library -#CONFIG_NRF_MODEM_LOG=y -#CONFIG_NRF_MODEM_LIB_LOG_LEVEL_DBG=y - -# AT monitor -#CONFIG_AT_MONITOR_LOG_LEVEL_DBG=y - -# LTE link control library -#CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=y diff --git a/applications/modem_shell/overlay-lwm2m.conf b/applications/modem_shell/overlay-lwm2m.conf deleted file mode 100644 index 4c94cc5..0000000 --- a/applications/modem_shell/overlay-lwm2m.conf +++ /dev/null @@ -1,96 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_MOSH_CLOUD_LWM2M=y -CONFIG_MOSH_LOCATION=y - -# Heap size needs to be increased due to LwM2M A-GNSS data buffer -CONFIG_HEAP_MEM_POOL_SIZE=10240 -CONFIG_LWM2M_ENGINE_STACK_SIZE=3072 - -# Handle Location library GNSS data and cellular location requests in the application -CONFIG_LOCATION_SERVICE_EXTERNAL=y - -# Set the LwM2M pre-shared key (PSK) here -#CONFIG_MOSH_LWM2M_PSK="000102030405060708090a0b0c0d0e0f" - -# LwM2M client utils library -CONFIG_LWM2M_CLIENT_UTILS=y -CONFIG_LWM2M_CLIENT_UTILS_SECURITY_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_CONN_MON_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_LOCATION_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_FIRMWARE_UPDATE_OBJ_SUPPORT=n -CONFIG_LWM2M_CLIENT_UTILS_SIGNAL_MEAS_INFO_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_GROUND_FIX_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_GNSS_ASSIST_OBJ_SUPPORT=y -CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS=y -CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_CELL=y - -# LwM2M and IPSO -CONFIG_LWM2M=y -CONFIG_LWM2M_COAP_BLOCK_SIZE=512 -CONFIG_LWM2M_COAP_MAX_MSG_SIZE=1280 -CONFIG_LWM2M_ENGINE_MAX_OBSERVER=15 -CONFIG_LWM2M_ENGINE_MAX_MESSAGES=15 -CONFIG_LWM2M_ENGINE_MAX_PENDING=15 -CONFIG_LWM2M_ENGINE_MAX_REPLIES=15 -CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=30 -CONFIG_LWM2M_DNS_SUPPORT=y -CONFIG_LWM2M_RW_JSON_SUPPORT=n -CONFIG_LWM2M_RW_OMA_TLV_SUPPORT=y -CONFIG_LWM2M_SERVER_DEFAULT_PMIN=1 -CONFIG_LWM2M_SERVER_DEFAULT_PMAX=300 -CONFIG_LWM2M_IPSO_SUPPORT=y -# Enable LwM2M 1.1 -CONFIG_LWM2M_VERSION_1_1=y -CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE=10 -# Enable SenML-CBOR content format -CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT=y -CONFIG_ZCBOR=y -CONFIG_ZCBOR_CANONICAL=y -CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=35 - -# IPSO v1.1 -CONFIG_LWM2M_SERVER_OBJECT_VERSION_1_1=y - -# DTLS settings -CONFIG_LWM2M_DTLS_SUPPORT=y - -# Enable LwM2M Queue Mode -CONFIG_LWM2M_QUEUE_MODE_ENABLED=y -# Optimize power usage by using tickless mode in LwM2M engine -CONFIG_LWM2M_TICKLESS=y -# Required by tickless mode -CONFIG_NET_SOCKETPAIR=y -# Enable TLS session caching to prevent doing a full TLS handshake for every send. -CONFIG_LWM2M_TLS_SESSION_CACHING=y -# Socket close is skipped at RX off idle state to optimize power consumption. -# Socket close call activates RCC connection to send Alert message to the server. -# Alert is now sent before opening a new connection. -CONFIG_LWM2M_RD_CLIENT_SUSPEND_SOCKET_AT_IDLE=y -# Sets the duration that the LwM2M engine will poll for data after transmission before -# the socket is closed. -CONFIG_LWM2M_QUEUE_MODE_UPTIME=30 -# Lifetime 12 hours. -CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=43200 -# Send registration update 10 minutes before connection lifetime expiration. -CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=600 - -# Support HEX style PSK values (double the size + NULL char) -CONFIG_LWM2M_SECURITY_KEY_SIZE=33 - -# Extend CoAP retry timeout to 15 seconds -CONFIG_COAP_INIT_ACK_TIMEOUT_MS=15000 - -# Enable CoAP extended option length -CONFIG_COAP_EXTENDED_OPTIONS_LEN=y -CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 - -# Enable shell -CONFIG_LWM2M_SHELL=y - -# AVSystem CDM-665 workaround: force object version reporting. -CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_3=y diff --git a/applications/modem_shell/overlay-lwm2m_bootstrap.conf b/applications/modem_shell/overlay-lwm2m_bootstrap.conf deleted file mode 100644 index 4e5e7b9..0000000 --- a/applications/modem_shell/overlay-lwm2m_bootstrap.conf +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# LwM2M bootstrap overlay configuration, to be used in combination with overlay-lwm2m.conf - -CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP=y -CONFIG_LWM2M_CLIENT_UTILS_SERVER="coaps://eu.iot.avsystem.cloud:5694" -CONFIG_LWM2M_SECURITY_INSTANCE_COUNT=3 diff --git a/applications/modem_shell/overlay-lwm2m_pgps.conf b/applications/modem_shell/overlay-lwm2m_pgps.conf deleted file mode 100644 index 7e0b0fb..0000000 --- a/applications/modem_shell/overlay-lwm2m_pgps.conf +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# LwM2M P-GPS overlay configuration, to be used in combination with overlay-lwm2m.conf and -# overlay-pgps.conf - -# LwM2M client -CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS=y - -# nRF Cloud P-GPS -CONFIG_NRF_CLOUD_PGPS_TRANSPORT_NONE=y -CONFIG_NRF_CLOUD_PGPS_DOWNLOAD_TRANSPORT_CUSTOM=y - -# Disable throughput tools to save memory -CONFIG_MOSH_IPERF3=n -CONFIG_MOSH_CURL=n diff --git a/applications/modem_shell/overlay-memfault.conf b/applications/modem_shell/overlay-memfault.conf deleted file mode 100644 index f9a5b3f..0000000 --- a/applications/modem_shell/overlay-memfault.conf +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Memfault -CONFIG_MEMFAULT=y -CONFIG_MEMFAULT_NCS_PROJECT_KEY="" -CONFIG_MEMFAULT_SHELL=y -CONFIG_MEMFAULT_HTTP_PERIODIC_UPLOAD=y -CONFIG_MEMFAULT_NCS_LTE_METRICS=y -CONFIG_MEMFAULT_LOGGING_ENABLE=y -CONFIG_MEMFAULT_LOG_LEVEL_DBG=y -CONFIG_MEMFAULT_NCS_DEVICE_ID_IMEI=y - -# Add to pick up support for sending Memfault data over HTTP -CONFIG_MEMFAULT_HTTP_ENABLE=y - -# nRF9160 only, uses modem to store root CAs -CONFIG_MEMFAULT_ROOT_CERT_STORAGE_NRF9160_MODEM=y -CONFIG_MODEM_KEY_MGMT=y diff --git a/applications/modem_shell/overlay-modem-trace-ram.conf b/applications/modem_shell/overlay-modem-trace-ram.conf deleted file mode 100644 index 8eb1333..0000000 --- a/applications/modem_shell/overlay-modem-trace-ram.conf +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_OFF=y - -# Modem trace flash backend -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_RAM=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_RAM_LENGTH=32768 diff --git a/applications/modem_shell/overlay-modem_fota_full.conf b/applications/modem_shell/overlay-modem_fota_full.conf deleted file mode 100644 index 45a1012..0000000 --- a/applications/modem_shell/overlay-modem_fota_full.conf +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Full modem FOTA -CONFIG_DFU_TARGET=y -CONFIG_DFU_TARGET_STREAM=y -CONFIG_DFU_TARGET_FULL_MODEM=y -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_SPI_NOR_SFDP_DEVICETREE=y -CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y -CONFIG_ZCBOR=y -CONFIG_STREAM_FLASH_ERASE=y -CONFIG_STREAM_FLASH=y -CONFIG_FMFU_FDEV=y -CONFIG_DOWNLOADER_STACK_SIZE=2560 -CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y diff --git a/applications/modem_shell/overlay-non-offloading.conf b/applications/modem_shell/overlay-non-offloading.conf deleted file mode 100644 index 542e7d3..0000000 --- a/applications/modem_shell/overlay-non-offloading.conf +++ /dev/null @@ -1,105 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_MOSH_NRF91_NON_OFFLOADING_DEV=y - -CONFIG_MOSH_PPP=n -CONFIG_MOSH_IPERF3=y -CONFIG_MOSH_WORKER_THREADS=n -CONFIG_MOSH_SOCK=n -CONFIG_MOSH_PING=n -CONFIG_MOSH_CURL=n -CONFIG_MOSH_GNSS=n -CONFIG_MOSH_SMS=n -CONFIG_MOSH_LOCATION=n -CONFIG_MOSH_REST=n -CONFIG_MOSH_CLOUD_REST=n -CONFIG_MOSH_AT_CMD_MODE=n -CONFIG_MOSH_STARTUP_CMDS=n -CONFIG_MOSH_FOTA=n - -CONFIG_DATE_TIME=n -CONFIG_SMS=n -CONFIG_NRF_CLOUD_AGNSS=n - -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=3072 - -# Enable net shell commands -CONFIG_NET_SHELL=y -CONFIG_NET_STATISTICS_USER_API=y - -# Enable needed stuff from native net stack -CONFIG_NETWORKING=y -CONFIG_NET_NATIVE=y -CONFIG_NET_STATISTICS=y -CONFIG_NET_STATISTICS_IPV4=n -CONFIG_NET_L2_DUMMY=y - -CONFIG_NET_LOG=y -CONFIG_NET_CONFIG_AUTO_INIT=y - -CONFIG_NET_SOCKETS=y -CONFIG_NET_SOCKETS_OFFLOAD=n - -CONFIG_NET_IF_MAX_IPV4_COUNT=1 -CONFIG_NET_IF_MAX_IPV6_COUNT=1 - -CONFIG_NET_TCP=y - -# Disable certain parts of Zephyr IPv6 stack -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n -CONFIG_NET_IPV6_FRAGMENT=n - -#Following selects MBEDTLS_MAC_MD5_ENABLED that needs bunch of other features -CONFIG_NET_TCP_ISN_RFC6528=n - -#Default RTO is too short and causes spurious retransmissions in uplink -CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=1500 -CONFIG_NET_TCP_RETRY_COUNT=6 - -# Enable the DNS resolver: -# as a default the ones from LTE default context are used -CONFIG_DNS_RESOLVER=y - -#CONFIG_DNS_SERVER_IP_ADDRESSES=y -#CONFIG_DNS_SERVER1="8.8.8.8" - -CONFIG_NET_IP_ADDR_CHECK=n -CONFIG_NET_DRIVERS=y - -# Uncomment to get maximum throughput. -#CONFIG_NRF_MODEM_LIB_SHMEM_TX_SIZE=32768 -#CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=16384 - -# Network buffers -CONFIG_NET_BUF=y -CONFIG_NET_BUF_DATA_SIZE=128 -CONFIG_NET_BUF_POOL_USAGE=y - -CONFIG_NET_PKT_RX_COUNT=30 -CONFIG_NET_BUF_RX_COUNT=60 - -CONFIG_NET_PKT_TX_COUNT=150 -CONFIG_NET_BUF_TX_COUNT=300 - -CONFIG_NET_TC_RX_COUNT=0 - -# Debug options -CONFIG_NET_CORE_LOG_LEVEL_WRN=y -CONFIG_NET_IF_LOG_LEVEL_WRN=y -CONFIG_NET_TCP_LOG_LEVEL_WRN=y - -CONFIG_NET_PKT_LOG_LEVEL_WRN=y -CONFIG_NET_DEBUG_NET_PKT_ALLOC=y - -CONFIG_NET_CONTEXT_LOG_LEVEL_WRN=y -CONFIG_UART_CONSOLE_LOG_LEVEL_WRN=y - -CONFIG_NET_BUF_LOG_LEVEL_OFF=y - -CONFIG_NET_CONN_LOG_LEVEL_WRN=y -CONFIG_NET_BUF_WARN_ALLOC_INTERVAL=0 diff --git a/applications/modem_shell/overlay-pgps.conf b/applications/modem_shell/overlay-pgps.conf deleted file mode 100644 index ab9872c..0000000 --- a/applications/modem_shell/overlay-pgps.conf +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# P-GPS overlay configuration - -# P-GPS -CONFIG_NRF_CLOUD_PGPS=y -CONFIG_NRF_CLOUD_PGPS_REPLACEMENT_THRESHOLD=4 - -# Storage for P-GPS -CONFIG_STREAM_FLASH=y -CONFIG_FLASH=y -CONFIG_FLASH_PAGE_LAYOUT=y -CONFIG_FLASH_MAP=y -CONFIG_FCB=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_FCB=y -CONFIG_MPU_ALLOW_FLASH_WRITE=y - -# Library that maintains the current date and UTC time -CONFIG_DATE_TIME=y diff --git a/applications/modem_shell/overlay-ppp.conf b/applications/modem_shell/overlay-ppp.conf deleted file mode 100644 index a93e6a0..0000000 --- a/applications/modem_shell/overlay-ppp.conf +++ /dev/null @@ -1,136 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Enable PPP MoSH support: -CONFIG_MOSH_PPP=y -CONFIG_MOSH_IPERF3=y -CONFIG_MOSH_WORKER_THREADS=n -CONFIG_MOSH_SOCK=n -CONFIG_MOSH_PING=y -CONFIG_MOSH_CURL=n -CONFIG_MOSH_GNSS=n -CONFIG_MOSH_SMS=n -CONFIG_MOSH_LOCATION=n -CONFIG_MOSH_REST=n -CONFIG_DATE_TIME=n -CONFIG_SMS=n - -# Enable net shell commands -CONFIG_NET_SHELL=y -CONFIG_NET_STATISTICS_PPP=y -CONFIG_NET_STATISTICS_USER_API=y - -# Enable needed stuff from native net stack -CONFIG_NET_NATIVE=y -CONFIG_NET_STATISTICS=y -CONFIG_NET_STATISTICS_PPP=y -CONFIG_NET_STATISTICS_IPV4=n -CONFIG_NET_STATISTICS_ICMP=n -CONFIG_NET_STATISTICS_UDP=n - -CONFIG_NET_MGMT_EVENT_STACK_SIZE=1024 - -CONFIG_NET_LOG=y -CONFIG_NET_CONFIG_AUTO_INIT=y - -CONFIG_NET_SOCKETS=y -CONFIG_NET_SOCKETS_PACKET=y -CONFIG_NET_SOCKETS_PACKET_DGRAM=n - -CONFIG_NET_IF_MAX_IPV4_COUNT=2 -CONFIG_NET_IF_MAX_IPV6_COUNT=2 - -CONFIG_NET_IP_ADDR_CHECK=n - -CONFIG_NET_DRIVERS=y - -# Default PPP net_if -CONFIG_NET_DEFAULT_IF_PPP=y -CONFIG_PPP_NET_IF_NO_AUTO_START=y - -# Asynch UART API used for PPP -CONFIG_SERIAL=y - -CONFIG_UART_ASYNC_API=y -CONFIG_UART_LINE_CTRL=y - -CONFIG_UART_0_INTERRUPT_DRIVEN=n -CONFIG_UART_0_ASYNC=y -CONFIG_UART_0_NRF_HW_ASYNC=y -CONFIG_UART_0_NRF_HW_ASYNC_TIMER=1 -#CONFIG_UART_0_NRF_ASYNC_LOW_POWER=y - -CONFIG_NET_PPP_UART_BUF_LEN=2048 -CONFIG_NET_PPP_ASYNC_UART_TX_BUF_LEN=4096 - -#CONFIG_NET_PPP_RX_PRIORITY=15 -CONFIG_NET_PPP_DRV_NAME="ppp" -CONFIG_NET_PPP_RINGBUF_SIZE=4096 -CONFIG_NET_PPP_RX_STACK_SIZE=2048 -CONFIG_NET_PPP_VERIFY_FCS=n -#CONFIG_NET_PPP_ASYNC_UART_RX_ENABLE_TIMEOUT=10 -#CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT=10 - -#CONFIG_NRF_MODEM_LIB_SHMEM_TX_SIZE=32768 -#CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=32768 - -# UART PPP driver -CONFIG_NET_PPP=y -CONFIG_NET_PPP_ASYNC_UART=y - -# L2 protocol configs -CONFIG_NET_L2_PPP=y -CONFIG_NET_L2_PPP_MGMT=y - -CONFIG_NET_L2_PPP_OPTION_MRU=y -CONFIG_NET_L2_PPP_OPTION_SERVE_IP=y -CONFIG_NET_L2_PPP_OPTION_SERVE_DNS=y -CONFIG_NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS=1 -CONFIG_NET_L2_PPP_TIMEOUT=5000 -CONFIG_NET_L2_PPP_MAX_CONFIGURE_REQ_RETRANSMITS=20 - -# Windows support -CONFIG_PPP_CLIENT_CLIENTSERVER=y - -# Default PPP MRU option config -CONFIG_NET_PPP_MTU_MRU=1280 - -# Network buffers -CONFIG_NET_BUF=y -CONFIG_NET_BUF_DATA_SIZE=128 -CONFIG_NET_BUF_POOL_USAGE=y - -CONFIG_NET_PKT_RX_COUNT=44 -CONFIG_NET_BUF_RX_COUNT=88 - -CONFIG_NET_PKT_TX_COUNT=44 -CONFIG_NET_BUF_TX_COUNT=88 - -CONFIG_NET_TC_RX_COUNT=0 - -# UART traces cannot be enabled -CONFIG_NRF_MODEM_LIB_TRACE=n - -# Debug options -CONFIG_NET_PPP_LOG_LEVEL_WRN=y -CONFIG_NET_L2_PPP_LOG_LEVEL_WRN=y -CONFIG_NET_CORE_LOG_LEVEL_WRN=y -CONFIG_NET_IF_LOG_LEVEL_WRN=y - -CONFIG_NET_PKT_LOG_LEVEL_WRN=y -CONFIG_NET_DEBUG_NET_PKT_ALLOC=y - -CONFIG_NET_CONTEXT_LOG_LEVEL_WRN=y -CONFIG_UART_CONSOLE_LOG_LEVEL_WRN=y - -CONFIG_NET_BUF_LOG_LEVEL_OFF=y - -CONFIG_NET_CONN_LOG_LEVEL_WRN=y -CONFIG_NET_BUF_WARN_ALLOC_INTERVAL=0 - -CONFIG_ASSERT=y -CONFIG_RESET_ON_FATAL_ERROR=n -CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=4096 diff --git a/applications/modem_shell/overlay-rtt.conf b/applications/modem_shell/overlay-rtt.conf deleted file mode 100644 index d4d3368..0000000 --- a/applications/modem_shell/overlay-rtt.conf +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_USE_SEGGER_RTT=y - -CONFIG_RTT_CONSOLE=y -CONFIG_UART_CONSOLE=n - -CONFIG_SHELL_BACKEND_RTT=y -CONFIG_SHELL_PROMPT_RTT="mosh:~$ " -CONFIG_SHELL_BACKEND_SERIAL=n -CONFIG_SHELL_PROMPT_UART="" diff --git a/applications/modem_shell/ppp.overlay b/applications/modem_shell/ppp.overlay deleted file mode 100644 index ccbbe0c..0000000 --- a/applications/modem_shell/ppp.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/ { - chosen { - zephyr,ppp-uart = &uart0; - }; -}; diff --git a/applications/modem_shell/prj.conf b/applications/modem_shell/prj.conf deleted file mode 100644 index 72e9396..0000000 --- a/applications/modem_shell/prj.conf +++ /dev/null @@ -1,184 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# -# General config - -CONFIG_MOSH_IPERF3=y -CONFIG_MOSH_SOCK=y -CONFIG_MOSH_PING=y -CONFIG_MOSH_CURL=y -CONFIG_MOSH_SMS=y -CONFIG_MOSH_GNSS=y -CONFIG_MOSH_LOCATION=y - -# Stacks and heaps -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_HEAP_MEM_POOL_SIZE=8192 - -# System queue is used e.g. by AT monitor and SMS lib -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 - -# Shell configurations -CONFIG_SHELL=y -CONFIG_SHELL_WILDCARD=n -CONFIG_SHELL_PROMPT_UART="mosh:~$ " -CONFIG_SHELL_ARGC_MAX=40 -# -h and --help options are handled in Modem Shell -CONFIG_SHELL_HELP_OPT_PARSE=n -# Command line buffer is set this large to enable writing of certificates and injecting A-GNSS data on command line. -CONFIG_SHELL_CMD_BUFF_SIZE=3584 -# Shell stack has impact for modem shell application, not CONFIG_MAIN_STACK_SIZE -CONFIG_SHELL_STACK_SIZE=9216 -# Shell RX buffer needs to be increased to avoid problems with test automation -CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE=512 -# Use interrupt driven shell UART, otherwise we won't be able to suspend the UART -CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN=y -# LTE shell is unnecessary with Modem Shell -CONFIG_LTE_SHELL=n -# Enable use of vsnprintfcb() for extending mosh_print() format -CONFIG_CBPRINTF_LIBC_SUBSTS=y - -CONFIG_MINIMAL_LIBC=n -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_FLOAT_SCANF=y -CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y -CONFIG_FPU=y -CONFIG_CJSON_LIB=y - -# Getopt -CONFIG_GETOPT_LIB=y -# Need to disable devmem shell since it enforces Zephyr's internal version of getopt -CONFIG_DEVMEM_SHELL=n - -# Device power management -CONFIG_PM_DEVICE=y - -# Needed for changing the UART baudrate at runtime -CONFIG_UART_USE_RUNTIME_CONFIGURE=y - -# Modem info -CONFIG_MODEM_INFO=y - -# Modem key management -CONFIG_MODEM_KEY_MGMT=y - -# Network -CONFIG_NETWORKING=y -CONFIG_NET_NATIVE=n -CONFIG_NET_SOCKETS=y -CONFIG_NET_SOCKETS_OFFLOAD=y -CONFIG_NET_SOCKETS_POSIX_NAMES=n -CONFIG_NET_IPV4=y -CONFIG_NET_IPV6=y - -CONFIG_POSIX_API=y -CONFIG_PTHREAD_IPC=n # There are issues with posix api if this is set -CONFIG_ZVFS_OPEN_MAX=10 -# Need to be the same as MAX_FDS -CONFIG_NET_SOCKETS_POLL_MAX=10 - -# Modem library -CONFIG_NRF_MODEM_LIB=y -CONFIG_NRF_MODEM_LIB_SHMEM_TX_SIZE=22528 -CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=8192 -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y - -# AT monitor library -CONFIG_AT_MONITOR=y - -# Increase AT monitor heap because %NCELLMEAS notifications can be long. -# Note: with legacy NCELLMEAS types, 512 is enough, but with GCI search types -# it could be even longer: theoretical maximum of 4020 bytes. -CONFIG_AT_MONITOR_HEAP_SIZE=1024 - -# Custom AT commands -CONFIG_AT_CMD_CUSTOM=y -CONFIG_AT_CMD_CUSTOM_LOG_LEVEL_OFF=y - -# PDN library -CONFIG_PDN=y -CONFIG_PDN_ESM_STRERROR=y - -# SMS -CONFIG_SMS=y - -# LTE link control -CONFIG_LTE_LINK_CONTROL=y -# Use modem system mode setting by default -CONFIG_LTE_NETWORK_MODE_DEFAULT=y -# These can be enabled at runtime using shell commands -CONFIG_LTE_LC_MODEM_SLEEP_NOTIFICATIONS=n -CONFIG_LTE_LC_TAU_PRE_WARNING_NOTIFICATIONS=n -# Minimum values for thresholds -CONFIG_LTE_LC_TAU_PRE_WARNING_THRESHOLD_MS=10240 -CONFIG_LTE_LC_MODEM_SLEEP_NOTIFICATIONS_THRESHOLD_MS=10240 -# Maximum number of neighbor cells for neighbor cell measurement -CONFIG_LTE_NEIGHBOR_CELLS_MAX=17 -# Enable required modules -CONFIG_LTE_LC_CONN_EVAL_MODULE=y -CONFIG_LTE_LC_EDRX_MODULE=y -CONFIG_LTE_LC_NEIGHBOR_CELL_MEAS_MODULE=y -CONFIG_LTE_LC_PERIODIC_SEARCH_MODULE=y -CONFIG_LTE_LC_PSM_MODULE=y -CONFIG_LTE_LC_RAI_MODULE=y -CONFIG_LTE_LC_MODEM_SLEEP_MODULE=y -CONFIG_LTE_LC_TAU_PRE_WARNING_MODULE=y - -CONFIG_DATE_TIME=y - -# nRF Cloud A-GNSS, disable this in case you want to enable SUPL below -CONFIG_NRF_CLOUD_AGNSS=y - -# SUPL A-GNSS support, needs the nRF9160 SiP SUPL client library from nRF9160 DK product page -#CONFIG_SUPL_CLIENT_LIB=y - -# Library for buttons and LEDs -# We don't have any LEDs for indicating so just disable it by default. -CONFIG_DK_LIBRARY=n - -# FOTA -CONFIG_FLASH=y -CONFIG_REBOOT=y -CONFIG_DFU_TARGET=y -CONFIG_FOTA_DOWNLOAD=y -CONFIG_DOWNLOADER=y -CONFIG_DOWNLOADER_SHELL=y -# BOOTLOADER_MCUBOOT reduces usable flash size by half so it's disabled by default -# This means application FOTA is disabled. Modem FOTA works without these. -CONFIG_BOOTLOADER_MCUBOOT=n -CONFIG_IMG_MANAGER=n -CONFIG_IMG_ERASE_PROGRESSIVELY=n - -# Settings -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_MPU_ALLOW_FLASH_WRITE=y -CONFIG_NVS=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_NVS=y -CONFIG_NVS_LOG_LEVEL_WRN=y - -# Debugging configurations -CONFIG_ASSERT=y -CONFIG_LOG=y -# Keep printk() synchronous -CONFIG_LOG_PRINTK=n -CONFIG_DEBUG_INFO=y -#CONFIG_DEBUG_OPTIMIZATIONS=y -#CONFIG_NO_OPTIMIZATIONS=y -#CONFIG_FORCE_NO_ASSERT=y -CONFIG_ASSERT_VERBOSE=y -#CONFIG_ASSERT_LEVEL=2 -#CONFIG_ASSERT_ON_ERRORS=y -#CONFIG_FAULT_DUMP=2 -CONFIG_RESET_ON_FATAL_ERROR=n -CONFIG_EXTRA_EXCEPTION_INFO=y -#CONFIG_WATCHDOG=y -CONFIG_SYS_HEAP_RUNTIME_STATS=y -# Enable TF-M logging on UART0 -CONFIG_TFM_SECURE_UART0=y -CONFIG_TFM_LOG_LEVEL_SILENCE=n -CONFIG_TFM_EXCEPTION_INFO_DUMP=y -CONFIG_TFM_SPM_LOG_LEVEL_DEBUG=y diff --git a/applications/modem_shell/sample.yaml b/applications/modem_shell/sample.yaml deleted file mode 100644 index bdcffb8..0000000 --- a/applications/modem_shell/sample.yaml +++ /dev/null @@ -1,128 +0,0 @@ -sample: - name: Modem Shell -tests: - applications.modem_shell: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell_debug: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_args: EXTRA_CONF_FILE=overlay-debug.conf - applications.modem_shell.cloud_mqtt_only: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_configs: - - CONFIG_LOCATION_SERVICE_NRF_CLOUD_GNSS_POS_SEND=y - extra_args: EXTRA_CONF_FILE=overlay-cloud_mqtt.conf - applications.modem_shell.cloud_mqtt_rest: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_configs: - - CONFIG_MOSH_CLOUD_MQTT=y - - CONFIG_MOSH_CLOUD_REST=y - applications.modem_shell.cloud_coap_only: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_configs: - - CONFIG_LOCATION_SERVICE_NRF_CLOUD_GNSS_POS_SEND=y - extra_args: EXTRA_CONF_FILE=overlay-cloud_coap.conf - applications.modem_shell.non_offloading_ip: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_args: EXTRA_CONF_FILE=overlay-non-offloading.conf - applications.modem_shell.app_fota: - sysbuild: true - build_only: true - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - extra_args: EXTRA_CONF_FILE=overlay-app_fota.conf - SB_CONFIG_BOOTLOADER_MCUBOOT=y - applications.modem_shell.carrier: - sysbuild: true - build_only: true - extra_args: EXTRA_CONF_FILE=overlay-carrier.conf - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.lwm2m: - sysbuild: true - build_only: true - extra_configs: - - CONFIG_MOSH_LWM2M_PSK="000102030405060708090a0b0c0d0e0f" - extra_args: EXTRA_CONF_FILE=overlay-lwm2m.conf - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.lwm2m_bootstrap: - sysbuild: true - build_only: true - extra_configs: - - CONFIG_MOSH_LWM2M_PSK="000102030405060708090a0b0c0d0e0f" - extra_args: EXTRA_CONF_FILE="overlay-lwm2m.conf;overlay-lwm2m_bootstrap.conf" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.lwm2m_pgps: - sysbuild: true - build_only: true - extra_configs: - - CONFIG_MOSH_LWM2M_PSK="000102030405060708090a0b0c0d0e0f" - extra_args: EXTRA_CONF_FILE="overlay-lwm2m.conf;overlay-lwm2m_pgps.conf;overlay-pgps.conf" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.pgps: - sysbuild: true - build_only: true - extra_args: EXTRA_CONF_FILE=overlay-pgps.conf - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.pgps_coap: - sysbuild: true - build_only: true - extra_args: EXTRA_CONF_FILE="overlay-pgps.conf;overlay-cloud_coap.conf" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.location_service_ext: - sysbuild: true - build_only: true - extra_configs: - - CONFIG_LOCATION_SERVICE_EXTERNAL=y - extra_args: EXTRA_CONF_FILE=overlay-cloud_mqtt.conf - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.ppp: - sysbuild: true - build_only: true - extra_args: EXTRA_CONF_FILE="overlay-ppp.conf;overlay-rtt.conf" EXTRA_DTC_OVERLAY_FILE="ppp.overlay" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.rtt: - sysbuild: true - build_only: true - extra_args: EXTRA_CONF_FILE=overlay-rtt.conf - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - # Configurations with modem RTT traces to make sure they fit into image. - applications.modem_shell_modem_uart_rtt: - sysbuild: true - build_only: true - extra_args: modem_shell_SNIPPET="nrf91-modem-trace-rtt" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns - applications.modem_shell.non_offloading_ip_modem_rtt_trace: - sysbuild: true - build_only: true - extra_args: - EXTRA_CONF_FILE=overlay-non-offloading.conf - modem_shell_SNIPPET="nrf91-modem-trace-rtt" - integration_platforms: - - nrf9151_connectkit/nrf9151/ns diff --git a/applications/modem_shell/src/at/CMakeLists.txt b/applications/modem_shell/src/at/CMakeLists.txt deleted file mode 100644 index 0174129..0000000 --- a/applications/modem_shell/src/at/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# -target_include_directories(app PRIVATE .) - -target_sources(app PRIVATE at_shell.c) -target_sources_ifdef(CONFIG_MOSH_AT_CMD_MODE app PRIVATE at_cmd_mode.c) -target_sources_ifdef(CONFIG_MOSH_AT_CMD_MODE app PRIVATE at_cmd_mode_sett.c) -target_sources_ifdef(CONFIG_MOSH_AT_CMD_MODE app PRIVATE at_cmd_mode_custom.c) diff --git a/applications/modem_shell/src/at/at_cmd_mode.c b/applications/modem_shell/src/at/at_cmd_mode.c deleted file mode 100644 index 87f82bd..0000000 --- a/applications/modem_shell/src/at/at_cmd_mode.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - - -#ifdef _POSIX_C_SOURCE -#undef _POSIX_C_SOURCE -#endif -/* Define _POSIX_C_SOURCE before including in order to use `strtok_r`. */ -#define _POSIX_C_SOURCE 200809L - -#include -#include - -#include -#include -#include - -#include "at_cmd_mode.h" - -extern struct k_work_q mosh_common_work_q; - -bool at_cmd_mode_dont_print; - -static enum line_termination term_mode = CONFIG_MOSH_AT_CMD_MODE_TERMINATION; - -#define AT_CMD_MODE_AT_CMD_MAX_LEN CONFIG_SHELL_CMD_BUFF_SIZE -#define AT_CMD_MODE_PIPELINED_AT_CMD_MAX_LEN 1023 - -static uint8_t at_buf[AT_CMD_MODE_AT_CMD_MAX_LEN + 1]; -static uint8_t at_buf_pipelined[AT_CMD_MODE_PIPELINED_AT_CMD_MAX_LEN + 1]; - -AT_MONITOR(mosh_at_cmd_mode_handler, ANY, at_cmd_mode_event_handler, PAUSED); - -struct at_cmd_mode_pipelining_info { - uint8_t *pipelined_cmd_start; /* Pointers to at_buf with pipelining */ - int pipelined_cmd_len; -}; - -#define AT_MAX_CMD_PIPELINED 10 -struct at_cmd_mode_work_data { - struct k_work work; - int pipe_cnt; - struct at_cmd_mode_pipelining_info pipe_infos[AT_MAX_CMD_PIPELINED]; -}; -static struct at_cmd_mode_work_data at_cmd_mode_work; - -static bool at_cmd_mode_active; -static bool inside_quotes; -static bool writing; -static size_t at_cmd_len; - -K_MUTEX_DEFINE(at_buf_mutex); - -static void at_cmd_mode_event_handler(const char *response) -{ - if (writing) { - /* 1st we need to clear current writings */ - printk("\r"); - for (int i = 0; i < at_cmd_len; i++) { - printk(" "); - } - - /* Then print AT notification */ - printk("\r%s", response); - - /* And at last, print the command that user was writing back */ - k_mutex_lock(&at_buf_mutex, K_FOREVER); - at_buf[at_cmd_len] = '\0'; - printk("%s", at_buf); - k_mutex_unlock(&at_buf_mutex); - } else { - printk("%s", response); - } -} - -static void at_cmd_mode_send_at_cmd(const char *at_str, char *rsp_buf, int rsp_buf_len) -{ - int err; - - err = nrf_modem_at_cmd(rsp_buf, rsp_buf_len, "%s", at_str); - if (err < 0) { - sprintf(rsp_buf, "ERROR: AT command failed: %d\n", err); - } /* else if (err > 0): print error from modem */ - - /* Response */ - printk("%s", rsp_buf); -} - -static void at_cmd_mode_send_at_cmd_from_at_buf(void) -{ - at_cmd_mode_send_at_cmd(at_buf, at_buf, sizeof(at_buf)); -} - -static void at_cmd_mode_worker(struct k_work *item) -{ - int i; - struct at_cmd_mode_work_data *data = CONTAINER_OF(item, struct at_cmd_mode_work_data, work); - struct at_cmd_mode_pipelining_info *pipes = data->pipe_infos; - - if (data->pipe_cnt) { - for (i = 0; i < AT_MAX_CMD_PIPELINED; i++) { - if (pipes[i].pipelined_cmd_len) { - strncpy(at_buf_pipelined, pipes[i].pipelined_cmd_start, - pipes[i].pipelined_cmd_len); - at_buf_pipelined[pipes[i].pipelined_cmd_len] = '\0'; - - at_cmd_mode_send_at_cmd(at_buf_pipelined, at_buf_pipelined, - sizeof(at_buf_pipelined)); - pipes[i].pipelined_cmd_len = 0; - } - } - } else { - at_cmd_mode_send_at_cmd_from_at_buf(); - } - data->pipe_cnt = 0; -} - -static void at_cmd_mode_cmd_rx_handler(uint8_t character) -{ - writing = true; - - /* Handle control characters */ - switch (character) { - case 0x08: /* Backspace. */ - /* Fall through. */ - case 0x7F: /* DEL character */ - if (at_cmd_len > 0) { - /* Reprint with DEL/Backspace */ - k_mutex_lock(&at_buf_mutex, K_FOREVER); - at_buf[at_cmd_len] = '\0'; - at_cmd_len--; - at_buf[at_cmd_len] = ' '; - printk("\r%s", at_buf); - at_buf[at_cmd_len] = '\0'; - printk("\r%s", at_buf); - k_mutex_unlock(&at_buf_mutex); - } - return; - } - - /* Handle termination characters, if outside quotes. */ - if (!inside_quotes) { - switch (character) { - case '\0': - if (term_mode == NULL_TERM) { - goto send; - } - /* Ignored null and will terminate string early. */ - break; - case '\r': - if (term_mode == CR_TERM) { - goto send; - } - break; - case '\n': - if (term_mode == LF_TERM) { - goto send; - } - if (term_mode == CR_LF_TERM && at_cmd_len > 0 && - at_buf[at_cmd_len - 1] == '\r') { - goto send; - } - break; - } - } - - /* Detect AT command buffer overflow, leaving space for null */ - if (at_cmd_len + 1 > sizeof(at_buf) - 1) { - printk("Buffer overflow, dropping '%c'\n", character); - return; - } - - /* Write character to AT buffer */ - k_mutex_lock(&at_buf_mutex, K_FOREVER); - at_buf[at_cmd_len] = character; - at_cmd_len++; - k_mutex_unlock(&at_buf_mutex); - - /* Handle special written character */ - if (character == '"') { - inside_quotes = !inside_quotes; - } - - /* Echo */ - printk("%c", character); - return; -send: - - k_mutex_lock(&at_buf_mutex, K_FOREVER); - at_buf[at_cmd_len] = '\0'; /* Terminate the command string */ - inside_quotes = false; - at_cmd_len = 0; - k_mutex_unlock(&at_buf_mutex); - - /* Scan AT command buffer for possible pipelined at commands */ - at_cmd_mode_work.pipe_cnt = 0; - - if (strchr(at_buf, '|')) { - struct at_cmd_mode_pipelining_info *pipes = at_cmd_mode_work.pipe_infos; - char *next_char, *save_next_char; - char *tmp; - int pipelined_at_cmd_len; - - next_char = at_buf; - tmp = strtok_r(next_char, "|", &save_next_char); - - while (tmp != NULL) { - if (at_cmd_mode_work.pipe_cnt >= AT_MAX_CMD_PIPELINED) { - printk("\nMax %d pipelined at commands supported, dropping: \"%s\"", - AT_MAX_CMD_PIPELINED, tmp); - } else { - pipelined_at_cmd_len = strlen(tmp); - if (pipelined_at_cmd_len > AT_CMD_MODE_PIPELINED_AT_CMD_MAX_LEN) { - printk("\nPipelined AT cmd max len is %d," - " too long %d bytes AT cmd dropped", - AT_CMD_MODE_PIPELINED_AT_CMD_MAX_LEN, - pipelined_at_cmd_len); - } else { - pipes[at_cmd_mode_work.pipe_cnt].pipelined_cmd_start = tmp; - pipes[at_cmd_mode_work.pipe_cnt].pipelined_cmd_len = - pipelined_at_cmd_len; - at_cmd_mode_work.pipe_cnt++; - } - } - tmp = strtok_r(NULL, "|", &save_next_char); - } - } - - /* Echo a line feed */ - printk("\n"); - - writing = false; - - k_work_submit_to_queue(&mosh_common_work_q, &at_cmd_mode_work.work); -} - -/* ctrl + x */ -#define CHAR_CAN 0x18 -/* ctrl + q */ -#define CHAR_DC1 0x11 - -static void at_cmd_mode_bypass_cb(const struct shell *sh, uint8_t *recv, size_t len) -{ - static uint8_t tail; - bool escape = false; - - /* Check if escape criteria is met. */ - if (tail == CHAR_CAN && recv[0] == CHAR_DC1) { - escape = true; - } else { - for (int i = 0; i < (len - 1); i++) { - if (recv[i] == CHAR_CAN && recv[i + 1] == CHAR_DC1) { - escape = true; - break; - } - } - } - - if (escape) { - /* Cannot use shell/mosh_print in bybass callback */ - printk("===========================================================\n"); - printk("MoSh AT command mode exited\n"); - - shell_set_bypass(sh, NULL); - at_cmd_mode_dont_print = false; - at_monitor_pause(&mosh_at_cmd_mode_handler); - at_cmd_mode_active = false; - inside_quotes = false; - tail = 0; - at_cmd_len = 0; - return; - } - - /* Store last byte for escape sequence detection */ - tail = recv[len - 1]; - - /* Handle byte by byte. */ - for (int i = 0; i < len; i++) { - at_cmd_mode_cmd_rx_handler(recv[i]); - } -} - -void at_cmd_mode_line_termination_set(enum line_termination line_term) -{ - term_mode = line_term; -} - -int at_cmd_mode_start(const struct shell *sh) -{ - if (at_cmd_mode_active) { - printk("AT command mode already started\n"); - return -EBUSY; - } - - k_work_init(&at_cmd_mode_work.work, at_cmd_mode_worker); - at_cmd_mode_work.pipe_cnt = 0; - - printk("MoSh AT command mode started, press ctrl-x ctrl-q to escape\n"); - printk("MoSh specific AT commands:\n"); -#if defined(CONFIG_MOSH_PING) - printk(" ICMP Ping: "); - printk("AT+NPING=[,,," - "[,[,]]]\n"); -#endif - printk("Other custom functionalities:\n"); - printk(" AT command pipelining, for example:\n" - " at+cgmr|at+cfun?|at+nping=\"example.com\"\n"); - printk("===========================================================\n"); - at_cmd_mode_dont_print = true; - at_cmd_mode_active = true; - - at_monitor_resume(&mosh_at_cmd_mode_handler); - shell_set_bypass(sh, at_cmd_mode_bypass_cb); - - return 0; -} diff --git a/applications/modem_shell/src/at/at_cmd_mode.h b/applications/modem_shell/src/at/at_cmd_mode.h deleted file mode 100644 index 2b30aba..0000000 --- a/applications/modem_shell/src/at/at_cmd_mode.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOSH_AT_CMD_MODE_H -#define MOSH_AT_CMD_MODE_H - -/** @brief Line Termination Modes. */ -enum line_termination { - NULL_TERM, /**< Null Termination */ - CR_TERM, /**< CR Termination */ - LF_TERM, /**< LF Termination */ - CR_LF_TERM /**< CR+LF Termination */ -}; - -int at_cmd_mode_start(const struct shell *sh); - -void at_cmd_mode_line_termination_set(enum line_termination line_term); - -#endif /* MOSH_AT_CMD_MODE_H */ diff --git a/applications/modem_shell/src/at/at_cmd_mode_custom.c b/applications/modem_shell/src/at/at_cmd_mode_custom.c deleted file mode 100644 index 735da7a..0000000 --- a/applications/modem_shell/src/at/at_cmd_mode_custom.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "mosh_defines.h" -#include "mosh_print.h" - -#if defined(CONFIG_MOSH_PING) -#include "icmp_ping.h" -#endif - -#define MOSH_AT_CMD_MAX_PARAM 8 - -extern bool at_cmd_mode_dont_print; - -#if defined(CONFIG_MOSH_PING) - -AT_CMD_CUSTOM(nping_custom, "AT+NPING", nping_callback); - -/**@brief handle AT+NPING commands - * AT+NPING=,[,,[,[,]]] - * AT+NPING? READ command not supported - * AT+NPING=? TEST command not supported - */ -static int at_cmd_ping_handle(struct at_parser *parser, enum at_parser_cmd_type cmd_type) -{ - int err; - int size = ICMP_MAX_ADDR; - bool dont_print_prev; - struct icmp_ping_shell_cmd_argv ping_args; - size_t count; - - if (cmd_type != AT_PARSER_CMD_TYPE_SET) { - return -EINVAL; - } - - /* ping is an exception where we want to use mosh_print during AT command mode */ - dont_print_prev = at_cmd_mode_dont_print; - at_cmd_mode_dont_print = false; - - icmp_ping_cmd_defaults_set(&ping_args); - - err = at_parser_string_get(parser, 1, ping_args.target_name, &size); - if (err < 0 || size == 0) { - err = -EINVAL; - return err; - } - - err = at_parser_cmd_count_get(parser, &count); - if (err) { - return err; - } - - if (count > 2) { - err = at_parser_num_get(parser, 2, &ping_args.len); - if (err) { - return err; - } - } - - if (count > 3) { - err = at_parser_num_get(parser, 3, &ping_args.timeout); - if (err) { - return err; - } - } - - if (count > 4) { - err = at_parser_num_get(parser, 4, &ping_args.count); - if (err) { - return err; - }; - } - - if (count > 5) { - err = at_parser_num_get(parser, 5, &ping_args.interval); - if (err) { - return err; - }; - } - - if (count > 6) { - err = at_parser_num_get(parser, 6, &ping_args.cid); - if (err) { - return err; - }; - } - - err = icmp_ping_start(&ping_args); - - at_cmd_mode_dont_print = dont_print_prev; - - return err; -} - -static int nping_callback(char *buf, size_t len, char *at_cmd) -{ - int err; - struct at_parser parser; - enum at_parser_cmd_type type; - - err = at_parser_init(&parser, at_cmd); - if (err) { - printk("Could not init AT parser, error: %d\n", err); - goto exit; - } - - err = at_parser_cmd_type_get(&parser, &type); - if (err) { - printk("Could not get AT command type, error: %d\n", err); - goto exit; - } - - err = at_cmd_ping_handle(&parser, type); - -exit: - return at_cmd_custom_respond(buf, len, "%s", err ? "ERROR\r\n" : "OK\r\n"); -} - -#endif /* CONFIG_MOSH_PING*/ diff --git a/applications/modem_shell/src/at/at_cmd_mode_sett.c b/applications/modem_shell/src/at/at_cmd_mode_sett.c deleted file mode 100644 index 01c744f..0000000 --- a/applications/modem_shell/src/at/at_cmd_mode_sett.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include - -#include -#include - -#include "mosh_print.h" -#include "at_cmd_mode_sett.h" - -#define AT_CMD_MODE_SETT_KEY "at_cmd_mode_settings" - -#define AT_CMD_MODE_SETT_AUTOSTART "autostart_enabled" - -static bool sett_autostart_enabled; - -/******************************************************************************/ - -/**@brief Callback when settings_load() is called. */ -static int at_cmd_mode_sett_handler(const char *key, size_t len, settings_read_cb read_cb, - void *cb_arg) -{ - int ret; - - if (strcmp(key, AT_CMD_MODE_SETT_AUTOSTART) == 0) { - ret = read_cb(cb_arg, &sett_autostart_enabled, sizeof(sett_autostart_enabled)); - if (ret < 0) { - mosh_error("Failed to read sett_autostart_enabled, error: %d", ret); - return ret; - } - } - return 0; -} - -/******************************************************************************/ - -int at_cmd_mode_sett_autostart_enabled(bool enabled) -{ - const char *key_enabled = AT_CMD_MODE_SETT_KEY "/" AT_CMD_MODE_SETT_AUTOSTART; - int err; - - sett_autostart_enabled = enabled; - - mosh_print("at_cmd_mode autostarting %s", ((enabled == true) ? "enabled" : "disabled")); - - err = settings_save_one(key_enabled, &sett_autostart_enabled, - sizeof(sett_autostart_enabled)); - if (err) { - mosh_error("sett_autostart_enabled: err %d from settings_save_one()", err); - return err; - } - - return 0; -} - -bool at_cmd_mode_sett_is_autostart_enabled(void) -{ - return sett_autostart_enabled; -} - -/******************************************************************************/ - -static struct settings_handler cfg = { .name = AT_CMD_MODE_SETT_KEY, - .h_set = at_cmd_mode_sett_handler }; - -int at_cmd_mode_sett_init(void) -{ - int ret = 0; - - sett_autostart_enabled = false; - - ret = settings_subsys_init(); - if (ret) { - mosh_error("Failed to initialize settings subsystem, error: %d", ret); - return ret; - } - - ret = settings_register(&cfg); - if (ret) { - mosh_error("Cannot register settings handler %d", ret); - return ret; - } - - ret = settings_load(); - if (ret) { - mosh_error("Cannot load settings %d", ret); - return ret; - } - return ret; -} diff --git a/applications/modem_shell/src/at/at_cmd_mode_sett.h b/applications/modem_shell/src/at/at_cmd_mode_sett.h deleted file mode 100644 index 3f37441..0000000 --- a/applications/modem_shell/src/at/at_cmd_mode_sett.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOSH_AT_CMD_MODE_SETT_H -#define MOSH_AT_CMD_MODE_SETT_H - -int at_cmd_mode_sett_init(void); -int at_cmd_mode_sett_autostart_enabled(bool enabled); -bool at_cmd_mode_sett_is_autostart_enabled(void); - -#endif /* MOSH_AT_CMD_MODE_SETT_H */ diff --git a/applications/modem_shell/src/at/at_shell.c b/applications/modem_shell/src/at/at_shell.c deleted file mode 100644 index 2a01587..0000000 --- a/applications/modem_shell/src/at/at_shell.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#include -#include -#include - -#include "mosh_defines.h" -#include "mosh_print.h" - -#if defined(CONFIG_MOSH_AT_CMD_MODE) -#include "at_cmd_mode.h" -#include "at_cmd_mode_sett.h" -#endif - -extern char mosh_at_resp_buf[MOSH_AT_CMD_RESPONSE_MAX_LEN]; -extern struct k_mutex mosh_at_resp_buf_mutex; - -AT_MONITOR(mosh_at_handler, ANY, at_cmd_handler, PAUSED); - -#if defined(CONFIG_MOSH_AT_CMD_MODE) - -static int at_shell_cmd_mode_start(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_start(shell); - return 0; -} - -static int at_shell_cmd_mode_enable_autostart(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_sett_autostart_enabled(true); - return 0; -} -static int at_shell_cmd_mode_disable_autostart(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_sett_autostart_enabled(false); - return 0; -} -static int at_shell_cmd_mode_term_cr_lf(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_line_termination_set(CR_LF_TERM); - return 0; -} -static int at_shell_cmd_mode_term_lf(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_line_termination_set(LF_TERM); - return 0; -} -static int at_shell_cmd_mode_term_cr(const struct shell *shell, size_t argc, char **argv) -{ - at_cmd_mode_line_termination_set(CR_TERM); - return 0; -} -#endif - -static void at_cmd_handler(const char *response) -{ - mosh_print("AT event handler: %s", response); -} - -static int sub_at_cmd_events_enable(const struct shell *shell, size_t argc, char **argv) -{ - at_monitor_resume(&mosh_at_handler); - mosh_print("AT command events enabled"); - - return 0; -} - -static int sub_at_cmd_events_disable(const struct shell *shell, size_t argc, char **argv) -{ - at_monitor_pause(&mosh_at_handler); - mosh_print("AT command events disabled"); - - return 0; -} - -static int cmd_at(const struct shell *shell, size_t argc, char **argv) -{ - int err; - - if (argc < 2 || (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { - shell_help(shell); - } else { - k_mutex_lock(&mosh_at_resp_buf_mutex, K_FOREVER); - err = nrf_modem_at_cmd(mosh_at_resp_buf, sizeof(mosh_at_resp_buf), "%s", argv[1]); - if (err == 0) { - mosh_print("%s", mosh_at_resp_buf); - } else if (err > 0) { - mosh_error("%s", mosh_at_resp_buf); - err = -EINVAL; - } else { - /* Negative values are error codes */ - mosh_error("Failed to send AT command, err %d", err); - } - k_mutex_unlock(&mosh_at_resp_buf_mutex); - } - - return 0; -} - -#if defined(CONFIG_MOSH_AT_CMD_MODE) -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_cmd_at_cmd_mode, - SHELL_CMD(start, NULL, - "Start AT command mode.", - at_shell_cmd_mode_start), - SHELL_CMD(enable_autostart, NULL, - "Enable AT command autostart on bootup.", - at_shell_cmd_mode_enable_autostart), - SHELL_CMD(disable_autostart, NULL, - "Disable AT command mode autostart on bootup.", - at_shell_cmd_mode_disable_autostart), - SHELL_CMD(term_cr_lf, NULL, - "Receive CR+LF as command line termination.", - at_shell_cmd_mode_term_cr_lf), - SHELL_CMD(term_lf, NULL, - "Receive LF as command line termination.", - at_shell_cmd_mode_term_lf), - SHELL_CMD(term_cr, NULL, - "Receive CR as command line termination.", - at_shell_cmd_mode_term_cr), - SHELL_SUBCMD_SET_END); -#endif - -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_at_shell, - SHELL_CMD_ARG(events_enable, NULL, - "Enable AT event handler which prints AT notifications.", - sub_at_cmd_events_enable, 1, 0), - SHELL_CMD(events_disable, NULL, - "Disable AT event handler.", - sub_at_cmd_events_disable), -#if defined(CONFIG_MOSH_AT_CMD_MODE) - SHELL_CMD(at_cmd_mode, &sub_cmd_at_cmd_mode, - "Enable/disable AT command mode.", - mosh_print_help_shell), -#endif - SHELL_SUBCMD_SET_END); - -SHELL_CMD_REGISTER( - at, - &sub_at_shell, - "Execute an AT command. Any subcommand not listed below is interpreted " - "as AT command and sent to the modem.", - cmd_at); diff --git a/applications/modem_shell/src/cloud/CMakeLists.txt b/applications/modem_shell/src/cloud/CMakeLists.txt deleted file mode 100644 index edf05d3..0000000 --- a/applications/modem_shell/src/cloud/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_include_directories(app PRIVATE .) - -target_sources_ifdef(CONFIG_MOSH_CLOUD_MQTT app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cloud_mqtt_shell.c) -target_sources_ifdef(CONFIG_MOSH_CLOUD_REST app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cloud_rest_shell.c) -target_sources_ifdef(CONFIG_MOSH_CLOUD_COAP app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cloud_coap_shell.c) -target_sources_ifdef(CONFIG_MOSH_CLOUD_LWM2M app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cloud_lwm2m_shell.c) -target_sources_ifdef(CONFIG_MOSH_CLOUD_LWM2M app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cloud_lwm2m.c) diff --git a/applications/modem_shell/src/cloud/cloud_coap_shell.c b/applications/modem_shell/src/cloud/cloud_coap_shell.c deleted file mode 100644 index 79f2cb5..0000000 --- a/applications/modem_shell/src/cloud/cloud_coap_shell.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include -#include "mosh_print.h" - -BUILD_ASSERT(IS_ENABLED(CONFIG_NRF_CLOUD_COAP)); - -BUILD_ASSERT(!IS_ENABLED(CONFIG_MOSH_CLOUD_LWM2M)); - -extern struct k_work_q mosh_common_work_q; - -static bool connected; - -static void coap_connect_work_fn(struct k_work *item) -{ - ARG_UNUSED(item); - - int err; - - if (connected) { - mosh_error("Already connected to nRF Cloud"); - return; - } - - err = nrf_cloud_coap_connect(NULL); - if (err) { - mosh_error("Connecting to nRF Cloud failed, error: %d", err); - return; - } - - connected = true; -} - -K_WORK_DEFINE(coap_connect_work, coap_connect_work_fn); - -static void cmd_cloud_coap_connect(const struct shell *shell, size_t argc, char **argv) -{ - ARG_UNUSED(shell); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - int err; - static bool initialized; - - if (!initialized) { - err = nrf_cloud_coap_init(); - if (err) { - mosh_error("Initializing nRF Cloud CoAP library failed, error: %d", err); - return; - } - - initialized = true; - } - - k_work_submit_to_queue(&mosh_common_work_q, &coap_connect_work); -} - -static void cmd_cloud_coap_disconnect(const struct shell *shell, size_t argc, char **argv) -{ - ARG_UNUSED(shell); - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - int err; - - if (!connected) { - mosh_error("Not connected to nRF Cloud"); - return; - } - - err = nrf_cloud_coap_disconnect(); - if (err) { - mosh_error("Disconnecting from nRF Cloud failed, error: %d", err); - } - - connected = false; -} - -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_cloud, - SHELL_CMD_ARG(connect, NULL, "Establish CoAP connection to nRF Cloud.", - cmd_cloud_coap_connect, 1, 0), - SHELL_CMD_ARG(disconnect, NULL, "Disconnect from nRF Cloud.", - cmd_cloud_coap_disconnect, 1, 0), - SHELL_SUBCMD_SET_END -); - -SHELL_CMD_REGISTER(cloud, &sub_cloud, "CoAP connection to nRF Cloud", mosh_print_help_shell); diff --git a/applications/modem_shell/src/cloud/cloud_lwm2m.c b/applications/modem_shell/src/cloud/cloud_lwm2m.c deleted file mode 100644 index 2a0b6cc..0000000 --- a/applications/modem_shell/src/cloud/cloud_lwm2m.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include -#include -#include - -#include "mosh_print.h" -#include "cloud_lwm2m.h" - -BUILD_ASSERT(sizeof(CONFIG_MOSH_LWM2M_PSK) > 1, "LwM2M pre-shared key (PSK) must be configured"); - -/* Device RIDs */ -#define MANUFACTURER_RID 0 -#define MODEL_NUMBER_RID 1 -#define SERIAL_NUMBER_RID 2 -#define FACTORY_RESET_RID 5 -#define POWER_SOURCE_RID 6 -#define POWER_SOURCE_VOLTAGE_RID 7 -#define POWER_SOURCE_CURRENT_RID 8 -#define CURRENT_TIME_RID 13 -#define UTC_OFFSET_RID 14 -#define TIMEZONE_RID 15 -#define DEVICE_TYPE_RID 17 -#define HARDWARE_VERSION_RID 18 -#define SOFTWARE_VERSION_RID 19 -#define BATTERY_STATUS_RID 20 -#define MEMORY_TOTAL_RID 21 - -#define IMEI_LEN 15 -static uint8_t imei_buf[IMEI_LEN + sizeof("\r\nOK\r\n")]; -#define ENDPOINT_NAME_LEN (IMEI_LEN + sizeof(CONFIG_MOSH_LWM2M_ENDPOINT_PREFIX) + 1) -static uint8_t endpoint_name[ENDPOINT_NAME_LEN + 1]; -static struct lwm2m_ctx client; - -#define APP_MANUFACTURER "Nordic Semiconductor ASA" -#define CLIENT_MODEL_NUMBER CONFIG_BOARD -#define CLIENT_HW_VER CONFIG_SOC -#define CLIENT_FLASH_SIZE CONFIG_FLASH_SIZE -#define UTC_OFFSET_STR_LEN 7 /* '+00:00' + '\0' = 7 */ -static char utc_offset[UTC_OFFSET_STR_LEN] = ""; -#define TIMEZONE_STR_LEN 33 /* Longest: 'America/Argentina/ComodRivadavia' + '\0' = 33 */ -static char timezone[TIMEZONE_STR_LEN] = ""; -#define APP_DEVICE_TYPE "OMA-LWM2M Client" -#if defined(APP_VERSION) -#define CLIENT_SW_VER ("v" NCS_VERSION_STRING "-" NCS_COMMIT_STRING) -#else -#define CLIENT_SW_VER "unknown" -#endif -static uint8_t bat_status = LWM2M_DEVICE_BATTERY_STATUS_CHARGING; -static int mem_total = CLIENT_FLASH_SIZE; -static uint8_t bat_idx = LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT; -static int bat_mv = 3800; -static int bat_ma = 125; -static uint8_t usb_idx = LWM2M_DEVICE_PWR_SRC_TYPE_USB; -static int usb_mv = 5000; -static int usb_ma = 900; - -static bool connected; -static bool no_serv_suspended; -static bool update_session_lifetime; - -static void cloud_lwm2m_init(void); -static void cloud_lwm2m_rd_client_stop(void); - -NRF_MODEM_LIB_ON_INIT(cloud_lwm2m_init_hook, on_modem_lib_init, NULL); - -static void on_modem_lib_init(int ret, void *ctx) -{ - ARG_UNUSED(ret); - ARG_UNUSED(ctx); - - static bool initialized; - - if (!initialized) { - cloud_lwm2m_init(); - - initialized = true; - } -} - -static int cloud_lwm2m_init_device(char *serial_num) -{ - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MANUFACTURER_RID), - APP_MANUFACTURER, sizeof(APP_MANUFACTURER), - sizeof(APP_MANUFACTURER), LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MODEL_NUMBER_RID), - CLIENT_MODEL_NUMBER, sizeof(CLIENT_MODEL_NUMBER), - sizeof(CLIENT_MODEL_NUMBER), LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, SERIAL_NUMBER_RID), - serial_num, strlen(serial_num), strlen(serial_num), - LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, UTC_OFFSET_RID), - utc_offset, sizeof(utc_offset), sizeof(utc_offset), 0); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, TIMEZONE_RID), - timezone, sizeof(timezone), sizeof(timezone), 0); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_TYPE_RID), - APP_DEVICE_TYPE, sizeof(APP_DEVICE_TYPE), - sizeof(APP_DEVICE_TYPE), LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, HARDWARE_VERSION_RID), - CLIENT_HW_VER, sizeof(CLIENT_HW_VER), sizeof(CLIENT_HW_VER), - LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, SOFTWARE_VERSION_RID), - CLIENT_SW_VER, sizeof(CLIENT_SW_VER), sizeof(CLIENT_SW_VER), - LWM2M_RES_DATA_FLAG_RO); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, BATTERY_STATUS_RID), - &bat_status, sizeof(bat_status), sizeof(bat_status), 0); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MEMORY_TOTAL_RID), - &mem_total, sizeof(mem_total), sizeof(mem_total), 0); - - /* Add power source resource instances. */ - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_RID, 0)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_RID, 0), - &bat_idx, sizeof(bat_idx), sizeof(bat_idx), 0); - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_VOLTAGE_RID, 0)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_VOLTAGE_RID, 0), - &bat_mv, sizeof(bat_mv), sizeof(bat_mv), 0); - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_CURRENT_RID, 0)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_CURRENT_RID, 0), - &bat_ma, sizeof(bat_ma), sizeof(bat_ma), 0); - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_RID, 1)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_RID, 1), - &usb_idx, sizeof(usb_idx), sizeof(usb_idx), 0); - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_VOLTAGE_RID, 1)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_VOLTAGE_RID, 1), - &usb_mv, sizeof(usb_mv), sizeof(usb_mv), 0); - lwm2m_create_res_inst(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_CURRENT_RID, 1)); - lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, POWER_SOURCE_CURRENT_RID, 1), - &usb_ma, sizeof(usb_ma), sizeof(usb_ma), 0); - - return 0; -} - -static void cloud_lwm2m_lte_lc_evt_handler(const struct lte_lc_evt *const evt) -{ - if (evt->type != LTE_LC_EVT_NW_REG_STATUS) { - return; - } - - switch (evt->nw_reg_status) { - case LTE_LC_NW_REG_REGISTERED_HOME: - case LTE_LC_NW_REG_REGISTERED_ROAMING: - if (connected && no_serv_suspended) { - mosh_print("LwM2M: LTE connected, resuming LwM2M engine"); - lwm2m_engine_resume(); - } - no_serv_suspended = false; - break; - - case LTE_LC_NW_REG_NOT_REGISTERED: - case LTE_LC_NW_REG_REGISTRATION_DENIED: - case LTE_LC_NW_REG_UNKNOWN: - case LTE_LC_NW_REG_UICC_FAIL: - if (connected) { - mosh_print("LwM2M: LTE not connected, suspending LwM2M engine"); - lwm2m_engine_pause(); - no_serv_suspended = true; - } - break; - - case LTE_LC_NW_REG_SEARCHING: - /* Transient status, don't trigger suspend yet. */ - default: - break; - } -} - -static void cloud_lwm2m_init(void) -{ - int ret; - - lte_lc_register_handler(cloud_lwm2m_lte_lc_evt_handler); - - ret = modem_info_init(); - if (ret < 0) { - printk("LwM2M: Unable to init modem_info (%d)", ret); - return; - } - - /* Query IMEI. */ - ret = modem_info_string_get(MODEM_INFO_IMEI, imei_buf, sizeof(imei_buf)); - if (ret < 0) { - printk("LwM2M: Unable to get IMEI"); - return; - } - - /* Use IMEI as unique endpoint name. */ - snprintk(endpoint_name, sizeof(endpoint_name), "%s%s", CONFIG_MOSH_LWM2M_ENDPOINT_PREFIX, - imei_buf); - - cloud_lwm2m_init_device(imei_buf); - lwm2m_init_security(&client, endpoint_name, NULL); - - if (sizeof(CONFIG_MOSH_LWM2M_PSK) > 1) { - /* Write hard-coded PSK key to the engine. First security instance is the right - * one, because in bootstrap mode, it is the bootstrap PSK. In normal mode, it is - * the server key. - */ - lwm2m_security_set_psk(0, CONFIG_MOSH_LWM2M_PSK, - sizeof(CONFIG_MOSH_LWM2M_PSK), true, - endpoint_name); - } - - /* Disable unnecessary time updates. */ - lwm2m_update_device_service_period(0); -} - -static void cloud_lwm2m_rd_client_update_lifetime(int srv_obj_inst) -{ - lwm2m_set_u32(&LWM2M_OBJ(1, srv_obj_inst, 1), CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME); - mosh_print("LwM2M: Set session lifetime to default value %d", - CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME); - - update_session_lifetime = false; -} - -static void cloud_lwm2m_rd_client_event_cb(struct lwm2m_ctx *client_ctx, - enum lwm2m_rd_client_event client_event) -{ - switch (client_event) { - case LWM2M_RD_CLIENT_EVENT_SERVER_DISABLED: - case LWM2M_RD_CLIENT_EVENT_DEREGISTER: - case LWM2M_RD_CLIENT_EVENT_NONE: - /* Do nothing. */ - break; - - case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE: - mosh_print("LwM2M: Bootstrap registration failure!"); - cloud_lwm2m_rd_client_stop(); - break; - - case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE: - mosh_print("LwM2M: Bootstrap registration complete"); - connected = false; - /* After bootstrapping the session lifetime needs to be set to the configured - * default, otherwise the default value from the server is taken into use. - */ - update_session_lifetime = true; - break; - - case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE: - mosh_print("LwM2M: Bootstrap transfer complete"); - break; - - case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE: - mosh_print("LwM2M: Registration failure!"); - connected = false; - cloud_lwm2m_rd_client_stop(); - break; - - case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE: - mosh_print("LwM2M: Registration complete"); - connected = true; - /* Check if session lifetime needs to be updated. */ - if (update_session_lifetime) { - cloud_lwm2m_rd_client_update_lifetime(client.srv_obj_inst); - } - break; - - case LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT: - mosh_print("LwM2M: Registration timed out!"); - connected = false; - cloud_lwm2m_rd_client_stop(); - break; - - case LWM2M_RD_CLIENT_EVENT_REG_UPDATE: - mosh_print("LwM2M: Registration update started"); - break; - - case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE: - mosh_print("LwM2M: Registration update complete"); - connected = true; - break; - - case LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE: - mosh_print("LwM2M: Deregister failure!"); - connected = false; - break; - - case LWM2M_RD_CLIENT_EVENT_DISCONNECT: - mosh_print("LwM2M: Disconnected"); - connected = false; - break; - - case LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF: - mosh_print("LwM2M: Queue mode RX window closed"); - break; - - case LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED: - mosh_print("LwM2M: Engine suspended"); - break; - - case LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR: - mosh_error("LwM2M: Engine reported a network error"); - connected = false; - cloud_lwm2m_rd_client_stop(); - break; - } -} - -static void cloud_lwm2m_rd_client_stop_work_fn(struct k_work *work) -{ - ARG_UNUSED(work); - - mosh_print("LwM2M: Stopping LwM2M client"); - - lwm2m_rd_client_stop(&client, cloud_lwm2m_rd_client_event_cb, false); -} - -static K_WORK_DEFINE(cloud_lwm2m_rd_client_stop_work, cloud_lwm2m_rd_client_stop_work_fn); - -static void cloud_lwm2m_rd_client_stop(void) -{ - k_work_submit(&cloud_lwm2m_rd_client_stop_work); -} - -struct lwm2m_ctx *cloud_lwm2m_client_ctx_get(void) -{ - return &client; -} - -bool cloud_lwm2m_is_connected(void) -{ - return connected && !no_serv_suspended; -} - -int cloud_lwm2m_connect(void) -{ - uint32_t flags = 0; - - if (lwm2m_security_needs_bootstrap()) { - flags |= LWM2M_RD_CLIENT_FLAG_BOOTSTRAP; - } - - mosh_print("LwM2M: Starting LwM2M client"); - - return lwm2m_rd_client_start(&client, endpoint_name, flags, - cloud_lwm2m_rd_client_event_cb, NULL); -} - -int cloud_lwm2m_disconnect(void) -{ - mosh_print("LwM2M: Stopping LwM2M client"); - - return lwm2m_rd_client_stop(&client, cloud_lwm2m_rd_client_event_cb, true); -} - -int cloud_lwm2m_suspend(void) -{ - return lwm2m_engine_pause(); -} - -int cloud_lwm2m_resume(void) -{ - return lwm2m_engine_resume(); -} - -void cloud_lwm2m_update(void) -{ - lwm2m_rd_client_update(); -} diff --git a/applications/modem_shell/src/cloud/cloud_lwm2m.h b/applications/modem_shell/src/cloud/cloud_lwm2m.h deleted file mode 100644 index 8ceefca..0000000 --- a/applications/modem_shell/src/cloud/cloud_lwm2m.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOSH_CLOUD_LWM2M_H -#define MOSH_CLOUD_LWM2M_H - -struct lwm2m_ctx *cloud_lwm2m_client_ctx_get(void); - -bool cloud_lwm2m_is_connected(void); - -int cloud_lwm2m_connect(void); - -int cloud_lwm2m_disconnect(void); - -int cloud_lwm2m_suspend(void); - -int cloud_lwm2m_resume(void); - -void cloud_lwm2m_update(void); - -#endif /* MOSH_CLOUD_LWM2M_H */ diff --git a/applications/modem_shell/src/cloud/cloud_lwm2m_shell.c b/applications/modem_shell/src/cloud/cloud_lwm2m_shell.c deleted file mode 100644 index 13e83e1..0000000 --- a/applications/modem_shell/src/cloud/cloud_lwm2m_shell.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include - -#include "mosh_print.h" -#include "cloud_lwm2m.h" - -BUILD_ASSERT(!IS_ENABLED(CONFIG_MOSH_CLOUD_MQTT)); - -static int cmd_lwm2m_connect(const struct shell *shell, size_t argc, char **argv) -{ - if (cloud_lwm2m_connect() != 0) { - mosh_error("LwM2M: Establishing LwM2M connection failed"); - return -ENOEXEC; - } - - return 0; -} - -static int cmd_lwm2m_disconnect(const struct shell *shell, size_t argc, char **argv) -{ - if (cloud_lwm2m_disconnect() != 0) { - mosh_error("LwM2M: Disconnecting LwM2M connection failed"); - return -ENOEXEC; - } - - return 0; -} - -static int cmd_lwm2m_suspend(const struct shell *shell, size_t argc, char **argv) -{ - if (cloud_lwm2m_suspend() != 0) { - mosh_error("LwM2M: Suspending LwM2M connection failed"); - return -ENOEXEC; - } - - return 0; -} - -static int cmd_lwm2m_resume(const struct shell *shell, size_t argc, char **argv) -{ - if (cloud_lwm2m_resume() != 0) { - mosh_error("LwM2M: Resuming LwM2M connection failed"); - return -ENOEXEC; - } - - return 0; -} - -static int cmd_lwm2m_update(const struct shell *shell, size_t argc, char **argv) -{ - cloud_lwm2m_update(); - - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_lwm2m, - SHELL_CMD_ARG(connect, NULL, "Establish LwM2M connection.", cmd_lwm2m_connect, - 1, 0), - SHELL_CMD_ARG(disconnect, NULL, "Disconnect LwM2M connection.", cmd_lwm2m_disconnect, 1, 0), - SHELL_CMD_ARG(suspend, NULL, "Suspend LwM2M engine.", cmd_lwm2m_suspend, 1, 0), - SHELL_CMD_ARG(resume, NULL, "Resume LwM2M engine.", cmd_lwm2m_resume, 1, 0), - SHELL_CMD_ARG(update, NULL, "Trigger a registration update.", cmd_lwm2m_update, 1, 0), - SHELL_SUBCMD_SET_END -); - -SHELL_CMD_REGISTER(cloud_lwm2m, &sub_lwm2m, "Cloud connection with LwM2M", mosh_print_help_shell); diff --git a/applications/modem_shell/src/cloud/cloud_mqtt_shell.c b/applications/modem_shell/src/cloud/cloud_mqtt_shell.c deleted file mode 100644 index 3ba726b..0000000 --- a/applications/modem_shell/src/cloud/cloud_mqtt_shell.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include -#include -#include "mosh_print.h" - -#define CLOUD_CMD_MAX_LENGTH 150 - -BUILD_ASSERT( - IS_ENABLED(CONFIG_NRF_CLOUD_MQTT) && - IS_ENABLED(CONFIG_NRF_CLOUD_CONNECTION_POLL_THREAD)); - -BUILD_ASSERT(!IS_ENABLED(CONFIG_MOSH_CLOUD_LWM2M)); - -extern struct k_work_q mosh_common_work_q; -extern const struct shell *mosh_shell; - -static struct k_work_delayable cloud_reconnect_work; -static struct k_work cloud_cmd_execute_work; - -static char shell_cmd[CLOUD_CMD_MAX_LENGTH + 1]; - -static void cloud_reconnect_work_fn(struct k_work *work) -{ - int err = nrf_cloud_connect(); - - if (err == NRF_CLOUD_CONNECT_RES_SUCCESS) { - mosh_print("Connecting to nRF Cloud..."); - } else if (err == NRF_CLOUD_CONNECT_RES_ERR_ALREADY_CONNECTED) { - mosh_print("nRF Cloud connection already established"); - } else { - mosh_error("nrf_cloud_connect, error: %d", err); - } -} - -static K_WORK_DELAYABLE_DEFINE(cloud_reconnect_work, cloud_reconnect_work_fn); - -static void cloud_cmd_execute_work_fn(struct k_work *work) -{ - shell_execute_cmd(mosh_shell, shell_cmd); - memset(shell_cmd, 0, CLOUD_CMD_MAX_LENGTH); -} - -static K_WORK_DEFINE(cloud_cmd_execute_work, cloud_cmd_execute_work_fn); - -static bool cloud_shell_parse_mosh_cmd(const char *buf_in) -{ - const cJSON *app_id = NULL; - const cJSON *mosh_cmd = NULL; - bool ret = false; - - cJSON *cloud_cmd_json = cJSON_Parse(buf_in); - - /* A format example expected from nrf cloud: - * {"appId":"MODEM_SHELL", "data":"location get"} - */ - if (cloud_cmd_json == NULL) { - const char *error_ptr = cJSON_GetErrorPtr(); - - if (error_ptr != NULL) { - mosh_error("JSON parsing error before: %s\n", error_ptr); - } - ret = false; - goto end; - } - - /* MoSh commands are identified by checking if appId equals "MODEM_SHELL" */ - app_id = cJSON_GetObjectItemCaseSensitive(cloud_cmd_json, NRF_CLOUD_JSON_APPID_KEY); - if (cJSON_IsString(app_id) && (app_id->valuestring != NULL)) { - if (strcmp(app_id->valuestring, "MODEM_SHELL") != 0) { - ret = false; - goto end; - } - } - - /* The value of attribute "data" contains the actual command */ - mosh_cmd = cJSON_GetObjectItemCaseSensitive(cloud_cmd_json, NRF_CLOUD_JSON_DATA_KEY); - if (cJSON_IsString(mosh_cmd) && (mosh_cmd->valuestring != NULL)) { - mosh_print("%s", mosh_cmd->valuestring); - if (strlen(mosh_cmd->valuestring) <= CLOUD_CMD_MAX_LENGTH) { - strcpy(shell_cmd, mosh_cmd->valuestring); - ret = true; - } else { - mosh_error("Received cloud command exceeds maximum permissible length %d", - CLOUD_CMD_MAX_LENGTH); - } - } -end: - cJSON_Delete(cloud_cmd_json); - return ret; -} - -static void nrf_cloud_event_handler(const struct nrf_cloud_evt *evt) -{ - const int reconnection_delay = 10; - - switch (evt->type) { - case NRF_CLOUD_EVT_TRANSPORT_CONNECTED: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_TRANSPORT_CONNECTED"); - break; - case NRF_CLOUD_EVT_TRANSPORT_CONNECTING: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_TRANSPORT_CONNECTING"); - break; - case NRF_CLOUD_EVT_USER_ASSOCIATION_REQUEST: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_USER_ASSOCIATION_REQUEST"); - mosh_warn("Add the device to nRF Cloud and reconnect"); - break; - case NRF_CLOUD_EVT_USER_ASSOCIATED: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_USER_ASSOCIATED"); - break; - case NRF_CLOUD_EVT_READY: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_READY"); - mosh_print("Connection to nRF Cloud established"); - break; - case NRF_CLOUD_EVT_RX_DATA_GENERAL: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_RX_DATA_GENERAL"); - if (((char *)evt->data.ptr)[0] == '{') { - /* Check if it's a MoSh command sent from the cloud */ - if (cloud_shell_parse_mosh_cmd(evt->data.ptr)) { - k_work_submit_to_queue(&mosh_common_work_q, - &cloud_cmd_execute_work); - } - } - break; - case NRF_CLOUD_EVT_RX_DATA_LOCATION: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_RX_DATA_LOCATION"); - break; - case NRF_CLOUD_EVT_RX_DATA_SHADOW: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_RX_DATA_SHADOW"); - break; - case NRF_CLOUD_EVT_PINGRESP: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_PINGRESP"); - break; - case NRF_CLOUD_EVT_SENSOR_DATA_ACK: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_SENSOR_DATA_ACK"); - break; - case NRF_CLOUD_EVT_TRANSPORT_DISCONNECTED: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_TRANSPORT_DISCONNECTED, status: %d", - evt->status); - mosh_print("Connection to nRF Cloud disconnected"); - if (!nfsm_get_disconnect_requested()) { - mosh_print("Reconnecting in %d seconds...", reconnection_delay); - k_work_reschedule_for_queue(&mosh_common_work_q, &cloud_reconnect_work, - K_SECONDS(reconnection_delay)); - } - break; - case NRF_CLOUD_EVT_FOTA_START: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_FOTA_START"); - break; - case NRF_CLOUD_EVT_FOTA_DONE: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_FOTA_DONE"); - break; - case NRF_CLOUD_EVT_FOTA_ERROR: - mosh_error("nRF Cloud event: NRF_CLOUD_EVT_FOTA_ERROR"); - break; - case NRF_CLOUD_EVT_TRANSPORT_CONNECT_ERROR: - mosh_error("nRF Cloud event: NRF_CLOUD_EVT_TRANSPORT_CONNECT_ERROR, status: %d", - evt->status); - mosh_error("Connecting to nRF Cloud failed"); - break; - case NRF_CLOUD_EVT_ERROR: - mosh_print("nRF Cloud event: NRF_CLOUD_EVT_ERROR, status: %d", evt->status); - break; - default: - mosh_error("Unknown nRF Cloud event type: %d", evt->type); - break; - } -} - -static void cmd_cloud_connect(const struct shell *shell, size_t argc, char **argv) -{ - int err; - static bool initialized; - - if (!initialized) { - struct nrf_cloud_init_param config = { - .event_handler = nrf_cloud_event_handler, - }; - - err = nrf_cloud_init(&config); - if (err == -EACCES) { - mosh_print("nRF Cloud module already initialized"); - } else if (err) { - mosh_error("nrf_cloud_init, error: %d", err); - return; - } - - initialized = true; - } - - k_work_reschedule_for_queue(&mosh_common_work_q, &cloud_reconnect_work, K_NO_WAIT); - - mosh_print("Endpoint: %s", CONFIG_NRF_CLOUD_HOST_NAME); -} - -static void cmd_cloud_disconnect(const struct shell *shell, size_t argc, char **argv) -{ - int err; - - /* Stop possibly pending reconnection attempt. */ - k_work_cancel_delayable(&cloud_reconnect_work); - - err = nrf_cloud_disconnect(); - if (err == -EACCES) { - mosh_print("Not connected to nRF Cloud"); - } else if (err) { - mosh_error("nrf_cloud_disconnect, error: %d", err); - } -} - -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_cloud, - SHELL_CMD_ARG(connect, NULL, "Establish MQTT connection to nRF Cloud.", cmd_cloud_connect, - 1, 0), - SHELL_CMD_ARG(disconnect, NULL, "Disconnect from nRF Cloud.", cmd_cloud_disconnect, 1, 0), - SHELL_SUBCMD_SET_END -); - -SHELL_CMD_REGISTER(cloud, &sub_cloud, "MQTT connection to nRF Cloud", mosh_print_help_shell); diff --git a/applications/modem_shell/src/cloud/cloud_rest_shell.c b/applications/modem_shell/src/cloud/cloud_rest_shell.c deleted file mode 100644 index e57cce6..0000000 --- a/applications/modem_shell/src/cloud/cloud_rest_shell.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include - -#include -#include - -#include "mosh_print.h" - -BUILD_ASSERT(IS_ENABLED(CONFIG_NRF_CLOUD_REST)); - -extern struct k_work_q mosh_common_work_q; - -static int cmd_cloud_rest_do_jitp(void) -{ - int ret = 0; - - mosh_print("Performing JITP..."); - - ret = nrf_cloud_rest_jitp(CONFIG_NRF_CLOUD_SEC_TAG); - if (ret == 0) { - char device_id[NRF_CLOUD_CLIENT_ID_MAX_LEN + 1]; - - ret = nrf_cloud_client_id_get(device_id, sizeof(device_id)); - if (ret) { - mosh_warn("Failed to get device ID, error: %d", ret); - return ret; - } - mosh_print("Waiting 30s for cloud provisioning to complete..."); - k_sleep(K_SECONDS(30)); - - mosh_print( - "You can now add the device to nRF Cloud as %s", - device_id); - k_sleep(K_SECONDS(5)); - } else if (ret == 1) { - mosh_warn("Device has been already provisioned to nRF Cloud"); - ret = 0; - } else { - mosh_error("JITP device provisioning failed: %d", ret); - } - - return ret; -} - -static int cmd_cloud_rest_jitp(const struct shell *shell, size_t argc, char **argv) -{ - int err = cmd_cloud_rest_do_jitp(); - - if (err) { - mosh_error("Failed to perform JITP, %d", err); - return err; - } - return 0; -} - -static int cmd_cloud_rest_shadow_device_status_update(const struct shell *shell, size_t argc, - char **argv) -{ - int err; - struct nrf_cloud_modem_info modem_info = { - .device = NRF_CLOUD_INFO_SET, - .network = NRF_CLOUD_INFO_SET, - .sim = NRF_CLOUD_INFO_SET, - .mpi = NULL - }; - struct nrf_cloud_device_status device_status = { - .modem = &modem_info, - /* Deprecated: The service info "ui" section is no longer used by nRF Cloud */ - .svc = NULL - }; - char device_id[NRF_CLOUD_CLIENT_ID_MAX_LEN + 1]; -#define REST_RX_BUF_SZ 300 /* No payload in response, "just" headers */ - static char rx_buf[REST_RX_BUF_SZ]; - struct nrf_cloud_rest_context rest_ctx = { .connect_socket = -1, - .keep_alive = false, - .rx_buf = rx_buf, - .rx_buf_len = sizeof(rx_buf), - .timeout_ms = NRF_CLOUD_REST_TIMEOUT_NONE, - .fragment_size = 0 }; - - err = nrf_cloud_client_id_get(device_id, sizeof(device_id)); - if (err) { - mosh_error("Failed to get device ID, error: %d", err); - return err; - } - - err = nrf_cloud_rest_shadow_device_status_update(&rest_ctx, device_id, &device_status); - if (err) { - mosh_error("REST: shadow update failed: %d", err); - return err; - } - mosh_print("Device status updated to cloud"); - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE(sub_cloud_rest, - SHELL_CMD(jitp, NULL, - "Perform Just-in-Time-Provisioning with nRF Cloud.", - cmd_cloud_rest_jitp), - SHELL_CMD(shadow_update, NULL, - "Send device capabilities to nRF Cloud.", - cmd_cloud_rest_shadow_device_status_update), - SHELL_SUBCMD_SET_END); - -SHELL_CMD_REGISTER( - cloud_rest, - &sub_cloud_rest, - "Send nRF Cloud command over REST", - mosh_print_help_shell); diff --git a/applications/modem_shell/src/drivers/CMakeLists.txt b/applications/modem_shell/src/drivers/CMakeLists.txt deleted file mode 100644 index b4c8c01..0000000 --- a/applications/modem_shell/src/drivers/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_include_directories(app PRIVATE .) - -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/nrf91_non_offloaded_dev.c) diff --git a/applications/modem_shell/src/drivers/nrf91_non_offloaded_dev.c b/applications/modem_shell/src/drivers/nrf91_non_offloaded_dev.c deleted file mode 100644 index 25a88cd..0000000 --- a/applications/modem_shell/src/drivers/nrf91_non_offloaded_dev.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2022 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - * - */ - -/* nRF91 usage without offloading TCP/IP stack to modem, - * i.e. using Zephyr native TCP/IP stack. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include "link_shell_pdn.h" -#include "net_utils.h" -#include "mosh_print.h" - -#define NO_MDM_SCKT -1 - -#define NRF91_MTU 1500 - -K_SEM_DEFINE(mdm_socket_sem, 0, 1); - -/* Work for creating modem data socket (uses system workq): */ -static struct k_work_delayable mdm_socket_work; - -struct nrf91_non_offload_dev_context { - uint8_t mac_addr[6]; - struct net_if *iface; - struct in_addr ipv4_addr; - bool default_pdp_active; - int mdm_skct_id; -}; - -static struct nrf91_non_offload_dev_context nrf91_non_offload_iface_data; - -/******************************************************************************/ - -static void util_get_ip_addr(int cid, char *addr4, char *addr6) -{ - int ret; - char cmd[128]; - char tmp[sizeof(struct in6_addr)]; - char addr1[NET_IPV6_ADDR_LEN] = { 0 }; - char addr2[NET_IPV6_ADDR_LEN] = { 0 }; - - sprintf(cmd, "AT+CGPADDR=%d", cid); - - /** parse +CGPADDR: ,, - * PDN type "IP": PDP_addr_1 is , max 16(INET_ADDRSTRLEN), '.' and digits - * PDN type "IPV6": PDP_addr_1 is , max 46(INET6_ADDRSTRLEN),':', digits, 'A'~'F' - * PDN type "IPV4V6": ,, or or - */ - ret = nrf_modem_at_scanf(cmd, "+CGPADDR: %*d,\"%46[.:0-9A-F]\",\"%46[:0-9A-F]\"", addr1, - addr2); - if (ret <= 0) { - return; - } - - /* parse 1st IP string */ - if (addr4 != NULL && inet_pton(AF_INET, addr1, tmp) == 1) { - strcpy(addr4, addr1); - } else if (addr6 != NULL && inet_pton(AF_INET6, addr1, tmp) == 1) { - strcpy(addr6, addr1); - return; - } - - /* parse second IP string (IPv6 only) */ - if (addr6 == NULL) { - return; - } - if (ret > 1 && inet_pton(AF_INET6, addr2, tmp) == 1) { - strcpy(addr6, addr2); - } -} - -/******************************************************************************/ - -struct pdn_conn_dyn_params { - struct in_addr dns_addr4_primary; - struct in_addr dns_addr4_secondary; - struct in6_addr dns_addr6_primary; - struct in6_addr dns_addr6_secondary; - uint32_t ipv4_mtu; - uint32_t ipv6_mtu; -}; -#define AT_CMD_PDP_CONTEXT_READ_DYN_INFO "AT+CGCONTRDP=%d" -#define AT_CMD_PDP_CONTEXT_READ_DYN_INFO_PARAM_COUNT 20 -#define AT_CMD_PDP_CONTEXT_READ_DYN_INFO_DNS_ADDR_PRIMARY_INDEX 6 -#define AT_CMD_PDP_CONTEXT_READ_DYN_INFO_DNS_ADDR_SECONDARY_INDEX 7 -#define AT_CMD_PDP_CONTEXT_READ_DYN_INFO_MTU_INDEX 12 - -static int util_get_pdn_conn_dyn_params(int cid, struct pdn_conn_dyn_params *ret_dyn_info) -{ - struct at_parser parser; - size_t param_str_len; - char at_cmd_response_str[512]; - char dns_addr_str[128]; - int ret, family, iterator; - struct in_addr *addr; - struct in6_addr *addr6; - bool resp_continues = true; - uint32_t mtu; - int family_for_mtu; - - ret = nrf_modem_at_cmd(at_cmd_response_str, sizeof(at_cmd_response_str), - AT_CMD_PDP_CONTEXT_READ_DYN_INFO, cid); - if (ret) { - mosh_error("Cannot get PDP conn dyn params, ret: %d", ret); - return false; - } - - /* Parse the response */ - ret = at_parser_init(&parser, at_cmd_response_str); - if (ret) { - mosh_error("Could not init AT parser, error: %d\n", ret); - return ret; - } - - iterator = 0; - ret_dyn_info->ipv4_mtu = NRF91_MTU; - ret_dyn_info->ipv6_mtu = NRF91_MTU; - while (resp_continues) { - /* Read primary DNS address */ - param_str_len = sizeof(dns_addr_str); - ret = at_parser_string_get(&parser, - AT_CMD_PDP_CONTEXT_READ_DYN_INFO_DNS_ADDR_PRIMARY_INDEX, - dns_addr_str, ¶m_str_len); - if (ret) { - mosh_error("Could not parse dns str for cid %d, err: %d", cid, ret); - goto clean_exit; - } - dns_addr_str[param_str_len] = '\0'; - - family = net_utils_sa_family_from_ip_string(dns_addr_str); - if (family == AF_INET) { - addr = &(ret_dyn_info->dns_addr4_primary); - (void)inet_pton(AF_INET, dns_addr_str, addr); - } else if (family == AF_INET6) { - addr6 = &(ret_dyn_info->dns_addr6_primary); - (void)inet_pton(AF_INET6, dns_addr_str, addr6); - } - /* Primary DNS address used for checking IP family for MTU */ - family_for_mtu = family; - - /* Read secondary DNS address */ - param_str_len = sizeof(dns_addr_str); - - ret = at_parser_string_get( - &parser, AT_CMD_PDP_CONTEXT_READ_DYN_INFO_DNS_ADDR_SECONDARY_INDEX, - dns_addr_str, ¶m_str_len); - if (ret) { - mosh_error("Could not parse dns str, err: %d", ret); - goto clean_exit; - } - dns_addr_str[param_str_len] = '\0'; - - family = net_utils_sa_family_from_ip_string(dns_addr_str); - if (family == AF_INET) { - addr = &(ret_dyn_info->dns_addr4_secondary); - (void)inet_pton(AF_INET, dns_addr_str, addr); - } else if (family == AF_INET6) { - addr6 = &(ret_dyn_info->dns_addr6_secondary); - (void)inet_pton(AF_INET6, dns_addr_str, addr6); - } - - /* Read link MTU if exists: */ - ret = at_parser_num_get(&parser, - AT_CMD_PDP_CONTEXT_READ_DYN_INFO_MTU_INDEX, - &mtu); - if (ret) { - /* Don't care if it fails and default MTUs have been set */ - ret = 0; - } else { - /* Note: if no primary DNS address in response, - * then family cannot be known for MTU from AT response and - * we use defaults for both families that have been set earlier. - */ - if (family_for_mtu == AF_INET) { - ret_dyn_info->ipv4_mtu = mtu; - } else if (family_for_mtu == AF_INET6) { - ret_dyn_info->ipv6_mtu = mtu; - } - } - - resp_continues = false; - if (at_parser_cmd_next(&parser) == 0) { - resp_continues = true; - iterator++; - } - } - -clean_exit: - return ret; -} - -/******************************************************************************/ - -static void nrf91_non_offload_pdn_event_handler(uint8_t cid, enum pdn_event event, int reason) -{ - /* Only default PDN context is supported */ - if (cid == 0) { - if (event == PDN_EVENT_ACTIVATED) { - nrf91_non_offload_iface_data.default_pdp_active = true; - k_work_schedule(&mdm_socket_work, K_SECONDS(2)); - } else if (event == PDN_EVENT_DEACTIVATED) { - nrf91_non_offload_iface_data.default_pdp_active = false; - k_work_schedule(&mdm_socket_work, K_NO_WAIT); - } - } -} - -/******************************************************************************/ - -static void nrf91_non_offload_socket_create(void) -{ - int ret; - - ret = nrf_socket(NRF_AF_PACKET, NRF_SOCK_RAW, 0); - if (ret < 0) { - mosh_error("nrf_socket failed %d\n", ret); - ret = NO_MDM_SCKT; - k_sem_reset(&mdm_socket_sem); - } else { - k_sem_give(&mdm_socket_sem); - } - nrf91_non_offload_iface_data.mdm_skct_id = ret; -} - -static void nrf91_non_offload_socket_close(void) -{ - int ret; - - k_sem_reset(&mdm_socket_sem); - nrf_close(nrf91_non_offload_iface_data.mdm_skct_id); - nrf91_non_offload_iface_data.mdm_skct_id = NO_MDM_SCKT; - ret = net_if_ipv4_addr_rm(nrf91_non_offload_iface_data.iface, - &nrf91_non_offload_iface_data.ipv4_addr); - if (!ret) { - mosh_error("Cannot remove IPv4 address from interface %d", - net_if_get_by_iface(nrf91_non_offload_iface_data.iface)); - } -} - -static void nrf91_non_offload_mdm_socket_worker(struct k_work *unused) -{ - ARG_UNUSED(unused); - if (nrf91_non_offload_iface_data.default_pdp_active) { - if (nrf91_non_offload_iface_data.mdm_skct_id == NO_MDM_SCKT) { - char ipv4_addr[NET_IPV4_ADDR_LEN] = { 0 }; - char ipv6_addr[NET_IPV6_ADDR_LEN] = { 0 }; - struct sockaddr addr; - struct net_if_addr *ifaddr; - struct pdn_conn_dyn_params pdn_dyn_info; - int len, ret; - - nrf91_non_offload_socket_create(); - util_get_ip_addr(0, ipv4_addr, ipv6_addr); - if (IS_ENABLED(CONFIG_NET_IPV4)) { - len = strlen(ipv4_addr); - if (len == 0) { - mosh_error("Unable to obtain local IPv4 address"); - return; - } - ret = net_ipaddr_parse(ipv4_addr, len, &addr); - if (!ret) { - mosh_error("Unable to parse IPv4 address"); - return; - } - ifaddr = net_if_ipv4_addr_add(nrf91_non_offload_iface_data.iface, - &net_sin(&addr)->sin_addr, - NET_ADDR_MANUAL, 0); - if (!ifaddr) { - mosh_error("Cannot add %s to interface", ipv4_addr); - return; - } - nrf91_non_offload_iface_data.ipv4_addr = net_sin(&addr)->sin_addr; - } - /* TODO: IPv6 */ - - ret = util_get_pdn_conn_dyn_params(0, &pdn_dyn_info); - if (ret) { - mosh_warn("Couldn't get PDN dyn info"); - } else { - /* Set LTE link MTU also to non-offloading net if */ - net_if_set_mtu(nrf91_non_offload_iface_data.iface, - pdn_dyn_info.ipv4_mtu); - -#if defined(CONFIG_DNS_RESOLVER) && !defined(CONFIG_DNS_SERVER_IP_ADDRESSES) - /* Dynamic DNS servers and set them on zephyr stack */ - struct dns_resolve_context *dnsctx; - struct sockaddr_in dns1 = { - .sin_family = AF_INET, - .sin_port = htons(53), - .sin_addr = pdn_dyn_info.dns_addr4_primary - }; - struct sockaddr_in dns2 = { - .sin_family = AF_INET, - .sin_port = htons(53), - .sin_addr = pdn_dyn_info.dns_addr4_secondary - }; - const struct sockaddr *dns_servers[] = { - (struct sockaddr *) &dns1, - (struct sockaddr *) &dns2, - NULL - }; - - dnsctx = dns_resolve_get_default(); - ret = dns_resolve_reconfigure(dnsctx, NULL, dns_servers); - if (ret < 0) { - mosh_error("Could not set DNS servers"); - } -#endif - } - - /* TODO: support for multiple net interfaces within non-offloading device, - * I.e. each for created PDN context - */ - } - } else { - nrf91_non_offload_socket_close(); - } -} - -/******************************************************************************/ - -static uint8_t *util_fake_dev_get_mac(struct nrf91_non_offload_dev_context *ctx) -{ - if (ctx->mac_addr[2] == 0x00) { - /* 00-00-5E-00-53-xx Documentation RFC 7042 */ - ctx->mac_addr[0] = 0x00; - ctx->mac_addr[1] = 0x00; - ctx->mac_addr[2] = 0x5E; - ctx->mac_addr[3] = 0x00; - ctx->mac_addr[4] = 0x53; - ctx->mac_addr[5] = sys_rand32_get(); - } - - return ctx->mac_addr; -} - -static void nrf91_non_offload_iface_init(struct net_if *iface) -{ - struct nrf91_non_offload_dev_context *ctx = net_if_get_device(iface)->data; - uint8_t *mac = util_fake_dev_get_mac(ctx); - - ctx->iface = iface; - ctx->default_pdp_active = false; - ctx->mdm_skct_id = NO_MDM_SCKT; - - /* The mac address is not really used but net if expects to find one. */ - net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET); -} - -static int nrf91_non_offload_init(const struct device *arg) -{ - int err = 0; - - ARG_UNUSED(arg); - - k_work_init_delayable(&mdm_socket_work, nrf91_non_offload_mdm_socket_worker); - - err = link_shell_pdn_event_forward_cb_set(nrf91_non_offload_pdn_event_handler); - if (err) { - mosh_error("link_shell_pdn_event_forward_cb_set() failed, err %d\n", err); - return -1; - } - return 0; -} - -/******************************************************************************/ - -static K_MUTEX_DEFINE(send_buf_lock); - -#define NRF91_MODEM_DATA_UL_BUFFER_SIZE 1500 -static char send_buffer[NRF91_MODEM_DATA_UL_BUFFER_SIZE]; - -static int nrf91_non_offload_iface_send(const struct device *dev, struct net_pkt *pkt) -{ - int ret, data_len; - - k_mutex_lock(&send_buf_lock, K_FOREVER); - data_len = net_pkt_get_len(pkt); - ret = net_pkt_read(pkt, send_buffer, data_len); - if (ret < 0) { - mosh_error("%s: cannot read packet: %d, from pkt %p\n", __func__, ret, pkt); - } else { - struct nrf91_non_offload_dev_context *ctx = dev->data; - - ret = nrf_send(ctx->mdm_skct_id, send_buffer, data_len, 0); - if (ret < 0) { - mosh_error("%s: send() failed: (%d), data len: %d\n", __func__, -errno, - data_len); - } else if (ret != data_len) { - mosh_error("%s: only partially sent, only %d of original %d was sent", - __func__, - ret, data_len); - } - } - net_pkt_unref(pkt); - k_mutex_unlock(&send_buf_lock); - - return ret; -} - -/******************************************************************************/ - -#define NRF91_MODEM_DATA_DL_BUFFER_SIZE 1500 - -static char receive_buffer[NRF91_MODEM_DATA_DL_BUFFER_SIZE]; - -static void nrf91_non_offload_modem_dl_data_thread_handler(void) -{ - struct net_pkt *rcv_pkt; - - int ret = 0; - int recv_data_len = 0; - - while (true) { - if (nrf91_non_offload_iface_data.mdm_skct_id < 0) { - /* Wait for sockets to be created */ - k_sem_take(&mdm_socket_sem, K_FOREVER); - continue; - } - - recv_data_len = nrf_recv(nrf91_non_offload_iface_data.mdm_skct_id, - receive_buffer, sizeof(receive_buffer), 0); - if (recv_data_len > 0) { - rcv_pkt = net_pkt_rx_alloc_with_buffer( - nrf91_non_offload_iface_data.iface, recv_data_len, - AF_UNSPEC, 0, K_NO_WAIT); - if (!rcv_pkt) { - mosh_error("%s: cannot allocate rcv packet\n", (__func__)); - k_sleep(K_MSEC(200)); - continue; - } - if (net_pkt_write(rcv_pkt, (uint8_t *)receive_buffer, - recv_data_len)) { - mosh_error("%s: cannot write pkt %p - dropped packet\n", - (__func__), rcv_pkt); - net_pkt_unref(rcv_pkt); - } else { - ret = net_recv_data( - nrf91_non_offload_iface_data.iface, - rcv_pkt); - if (ret < 0) { - mosh_error( - "%s: received packet dropped by NET stack, ret %d", - (__func__), ret); - net_pkt_unref(rcv_pkt); - } - } - } else { - /* nrf_recv() failed, LTE connection might have dropped. - * Let other threads run and to update possible mdm_socket_sem. - */ - k_sleep(K_MSEC(200)); - } - } -} - -#define NRF91_MODEM_DATA_DL_THREAD_STACK_SIZE 2048 -#define NRF91_MODEM_DATA_RCV_THREAD_PRIORITY K_PRIO_COOP(10) /* -6 */ - -K_THREAD_DEFINE(nrf91_modem_dl_data_thread, NRF91_MODEM_DATA_DL_THREAD_STACK_SIZE, - nrf91_non_offload_modem_dl_data_thread_handler, NULL, NULL, NULL, - NRF91_MODEM_DATA_RCV_THREAD_PRIORITY, 0, 0); - -/******************************************************************************/ - -static struct dummy_api nrf91_non_offload_if_api = { - .iface_api.init = nrf91_non_offload_iface_init, - .send = nrf91_non_offload_iface_send, -}; - -/* No L2 */ -#define NRF91_L2_LAYER DUMMY_L2 -#define NRF91_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2) - -NET_DEVICE_INIT(nrf91_non_offload, "nrf91_nrf_non_offloading_dev", - nrf91_non_offload_init, NULL, - &nrf91_non_offload_iface_data, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, - &nrf91_non_offload_if_api, NRF91_L2_LAYER, NRF91_L2_CTX_TYPE, NRF91_MTU); diff --git a/applications/modem_shell/src/fota/CMakeLists.txt b/applications/modem_shell/src/fota/CMakeLists.txt deleted file mode 100644 index 339daff..0000000 --- a/applications/modem_shell/src/fota/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_include_directories(app PRIVATE .) - -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/fota.c) -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/fota_shell.c) diff --git a/applications/modem_shell/src/fota/fota.c b/applications/modem_shell/src/fota/fota.c deleted file mode 100644 index 3944bb5..0000000 --- a/applications/modem_shell/src/fota/fota.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "fota.h" -#include "link.h" -#include "mosh_print.h" - -static void on_modem_lib_dfu(int dfu_res, void *ctx) -{ - switch (dfu_res) { - case NRF_MODEM_DFU_RESULT_OK: - break; - case NRF_MODEM_DFU_RESULT_UUID_ERROR: - case NRF_MODEM_DFU_RESULT_AUTH_ERROR: - mosh_error("FOTA: Modem firmware update failed, err: 0x%08x", dfu_res); - mosh_error("FOTA: Modem is running previous firmware"); - break; - case NRF_MODEM_DFU_RESULT_HARDWARE_ERROR: - case NRF_MODEM_DFU_RESULT_INTERNAL_ERROR: - mosh_error("FOTA: Fatal error, modem firmware update failed, err: 0x%08x", dfu_res); - __ASSERT(false, "Modem firmware update failed on fatal error"); - case NRF_MODEM_DFU_RESULT_VOLTAGE_LOW: - mosh_error("FOTA: Modem firmware update cancelled due to low voltage"); - mosh_error("FOTA: Please reboot once you have sufficient voltage for the DFU"); - __ASSERT(false, "Modem firmware update cancelled due to low voltage"); - default: - /* Modem library initialization failed. */ - mosh_error("FOTA: Fatal error, could not initialize nrf_modem_lib, err: %d", - dfu_res); - __ASSERT(false, "Could not initialize nrf_modem_lib"); - } -} - -NRF_MODEM_LIB_ON_DFU_RES(fota_dfu_hook, on_modem_lib_dfu, NULL); - -static void fota_update_apply(void) -{ - int err; - int target; - - link_func_mode_set(LTE_LC_FUNC_MODE_OFFLINE, true); - - target = fota_download_target(); - if (target == DFU_TARGET_IMAGE_TYPE_MCUBOOT) { - mosh_print("FOTA: Rebooting device to run new application firmware"); - - sys_reboot(SYS_REBOOT_COLD); - } else { - mosh_print("FOTA: Applying modem firmware update..."); - - err = fota_download_util_apply_update(target); - if (err) { - mosh_error("FOTA: Failed to apply modem firmware update, error: %d", err); - } else { - mosh_print("FOTA: Modem firmware update successful!"); - } - - link_func_mode_set(LTE_LC_FUNC_MODE_NORMAL, true); - } -} - -static const char *get_error_cause(enum fota_download_error_cause cause) -{ - switch (cause) { - case FOTA_DOWNLOAD_ERROR_CAUSE_DOWNLOAD_FAILED: - return "download failed"; - case FOTA_DOWNLOAD_ERROR_CAUSE_INVALID_UPDATE: - return "invalid update"; - default: - return "unknown cause value"; - } -} - -static void fota_download_callback(const struct fota_download_evt *evt) -{ - switch (evt->id) { - case FOTA_DOWNLOAD_EVT_PROGRESS: - mosh_print("FOTA: Progress %d%%", evt->progress); - break; - case FOTA_DOWNLOAD_EVT_FINISHED: - mosh_print("FOTA: Download finished"); - fota_update_apply(); - break; - case FOTA_DOWNLOAD_EVT_ERASE_TIMEOUT: - mosh_print("FOTA: Erasing reached timeout"); - /* Fall through, erasing continues. */ - case FOTA_DOWNLOAD_EVT_ERASE_PENDING: - mosh_print("FOTA: Still erasing..."); - break; - case FOTA_DOWNLOAD_EVT_ERASE_DONE: - mosh_print("FOTA: Erasing finished"); - break; - case FOTA_DOWNLOAD_EVT_ERROR: - mosh_error("FOTA: Error, %s", get_error_cause(evt->cause)); - break; - default: - mosh_error("FOTA: Unknown event %d", evt->id); - break; - } -} - -int fota_init(void) -{ - int err; - - err = fota_download_util_stream_init(); - if (err) { - return err; - } - - return fota_download_init(&fota_download_callback); -} - -int fota_start(const char *host, const char *file) -{ - return fota_download_start(host, file, CONFIG_NRF_CLOUD_SEC_TAG, 0, 0); -} diff --git a/applications/modem_shell/src/fota/fota.h b/applications/modem_shell/src/fota/fota.h deleted file mode 100644 index 98a23e4..0000000 --- a/applications/modem_shell/src/fota/fota.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOSH_FOTA_H -#define MOSH_FOTA_H - -#include - -int fota_init(void); - -int fota_start(const char *host, const char *file); - -#endif /* MOSH_FOTA_H */ diff --git a/applications/modem_shell/src/fota/fota_shell.c b/applications/modem_shell/src/fota/fota_shell.c deleted file mode 100644 index c118c89..0000000 --- a/applications/modem_shell/src/fota/fota_shell.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include - -#include "fota.h" -#include "mosh_print.h" - -static const char fota_server_eu[] = "nrf-test-eu.s3.amazonaws.com"; -static const char fota_server_usa[] = "nrf-test-us.s3.amazonaws.com"; -static const char fota_server_jpn[] = "nrf-test-jpn.s3.amazonaws.com"; -static const char fota_server_au[] = "nrf-test-au.s3.amazonaws.com"; - -static int cmd_fota_download(const struct shell *shell, size_t argc, - char **argv) -{ - int err; - const char *fota_server; - - if (strcmp(argv[1], "eu") == 0) { - fota_server = fota_server_eu; - } else if (strcmp(argv[1], "us") == 0) { - fota_server = fota_server_usa; - } else if (strcmp(argv[1], "jpn") == 0) { - fota_server = fota_server_jpn; - } else if (strcmp(argv[1], "au") == 0) { - fota_server = fota_server_au; - } else { - fota_server = argv[1]; - } - - mosh_print("FOTA: Starting download..."); - - err = fota_start(fota_server, argv[2]); - - if (err) { - mosh_error("Failed to start FOTA download, error %d", - err); - return err; - } - - mosh_print("FOTA: Download started"); - - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE( - sub_fota, - SHELL_CMD_ARG( - download, NULL, - " \nDownload and install a FOTA update. " - "Available servers are \"eu\", \"us\", \"jpn\" and \"au\"\n" - "You can also use the server address directly, e.g. http://example.com", - cmd_fota_download, 3, 0), - SHELL_SUBCMD_SET_END); - -SHELL_CMD_REGISTER(fota, &sub_fota, "Commands for FOTA update.", mosh_print_help_shell); diff --git a/applications/modem_shell/src/gnss/CMakeLists.txt b/applications/modem_shell/src/gnss/CMakeLists.txt deleted file mode 100644 index 1cf56c7..0000000 --- a/applications/modem_shell/src/gnss/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_include_directories(app PRIVATE .) - -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/gnss_shell.c) -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/gnss.c) -target_sources_ifdef(CONFIG_SUPL_CLIENT_LIB app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/gnss_supl_support.c) diff --git a/applications/modem_shell/src/gnss/gnss.c b/applications/modem_shell/src/gnss/gnss.c deleted file mode 100644 index 1327fbb..0000000 --- a/applications/modem_shell/src/gnss/gnss.c +++ /dev/null @@ -1,1801 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) || \ - defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS) -#include -#include "cloud_lwm2m.h" -#endif - -#if defined(CONFIG_LWM2M_CARRIER) -#include -#include -#endif - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_NRF_CLOUD_PGPS) -#include -#include -#include -#if defined(CONFIG_NRF_CLOUD_COAP) -#include -#endif -#if defined(CONFIG_NRF_CLOUD_AGNSS) -#include -#endif /* CONFIG_NRF_CLOUD_AGNSS */ -#if defined(CONFIG_NRF_CLOUD_PGPS) -#include -#endif /* CONFIG_NRF_CLOUD_PGPS */ -#endif /* CONFIG_NRF_CLOUD_AGNSS || CONFIG_NRF_CLOUD_PGPS */ - -#if defined(CONFIG_SUPL_CLIENT_LIB) -#include -#include -#include "gnss_supl_support.h" -#endif /* CONFIG_SUPL_CLIENT_LIB */ - -#include "mosh_print.h" -#include "str_utils.h" -#include "gnss.h" - -#if (defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_NRF_CLOUD_PGPS)) && \ - defined(CONFIG_SUPL_CLIENT_LIB) -BUILD_ASSERT(false, "nRF Cloud assistance and SUPL library cannot be enabled at the same time"); -#endif - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_NRF_CLOUD_PGPS) -/* Verify that MQTT, REST or COAP is enabled */ -BUILD_ASSERT(IS_ENABLED(CONFIG_NRF_CLOUD_MQTT) || - IS_ENABLED(CONFIG_NRF_CLOUD_REST) || - IS_ENABLED(CONFIG_NRF_CLOUD_COAP), - "CONFIG_NRF_CLOUD_MQTT, CONFIG_NRF_CLOUD_REST or CONFIG_NRF_CLOUD_COAP " - "transport must be enabled"); -#endif - -#define GNSS_DATA_HANDLER_THREAD_STACK_SIZE 1536 -#define GNSS_DATA_HANDLER_THREAD_PRIORITY 5 - -enum gnss_operation_mode { - GNSS_OP_MODE_CONTINUOUS, - GNSS_OP_MODE_SINGLE_FIX, - GNSS_OP_MODE_PERIODIC_FIX, - GNSS_OP_MODE_PERIODIC_FIX_GNSS -}; - -extern struct k_work_q mosh_common_work_q; - -static struct k_work gnss_stop_work; -static struct k_work_delayable gnss_start_work; -static struct k_work_delayable gnss_timeout_work; - -static enum gnss_operation_mode operation_mode = GNSS_OP_MODE_CONTINUOUS; -static uint32_t periodic_fix_interval; -static uint32_t periodic_fix_retry; -static bool nmea_mask_set; -static struct nrf_modem_gnss_agnss_data_frame agnss_need; -static uint8_t gnss_elevation = 5; /* init to modem default threshold angle */ - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) -static struct k_work get_agnss_data_work; -static bool agnss_automatic; -static bool agnss_inject_ephe = true; -static bool agnss_inject_alm = true; -static bool agnss_inject_utc = true; -static bool agnss_inject_klob = true; -static bool agnss_inject_neq = true; -static bool agnss_inject_time = true; -static bool agnss_inject_pos = true; -static bool agnss_inject_int = true; -#endif /* CONFIG_NRF_CLOUD_AGNSS || CONFIG_SUPL_CLIENT_LIB */ - -#if defined(CONFIG_NRF_CLOUD_AGNSS) && !defined(CONFIG_NRF_CLOUD_MQTT) && \ - !defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) -static char agnss_data_buf[NRF_CLOUD_AGNSS_MAX_DATA_SIZE]; -#endif - -#if defined(CONFIG_NRF_CLOUD_PGPS) -static bool pgps_enabled; -static struct nrf_cloud_pgps_prediction *prediction; -static struct k_work inject_pgps_data_work; -static struct k_work notify_pgps_prediction_work; -#if !defined(CONFIG_NRF_CLOUD_MQTT) -static struct gps_pgps_request pgps_request; -static struct k_work get_pgps_data_work; -#endif /* !CONFIG_NRF_CLOUD_MQTT */ -#endif /* CONFIG_NRF_CLOUD_PGPS */ - -#if defined(CONFIG_NRF_CLOUD_AGNSS) && defined(CONFIG_NRF_CLOUD_REST) && \ - !defined(CONFIG_NRF_CLOUD_MQTT) && !defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) -#define AGNSS_USES_REST -#endif - -#if defined(CONFIG_NRF_CLOUD_PGPS) && defined(CONFIG_NRF_CLOUD_REST) && \ - !defined(CONFIG_NRF_CLOUD_MQTT) && !defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS) -#define PGPS_USES_REST -#endif - -#if defined(AGNSS_USES_REST) || defined(PGPS_USES_REST) -/* JWT and receive buffers will be needed if either A-GNSS or P-GPS uses REST. */ -static char jwt_buf[600]; -static char rx_buf[2048]; -#endif - -#if defined(CONFIG_NRF_CLOUD_AGNSS_FILTERED_RUNTIME) -static bool gnss_filtered_ephemerides_enabled; -#endif /* CONFIG_NRF_CLOUD_AGNSS_FILTERED_RUNTIME */ - -/* Struct for an event item. The data is read in the event handler and passed as a part of the - * event item because an NMEA string would get overwritten by the next NMEA string before the - * consumer thread is able to read it. This is not a problem with PVT and A-GNSS request data, but - * all data is handled in the same way for simplicity. - */ -struct event_item { - uint8_t id; - void *data; -}; - -K_MSGQ_DEFINE(gnss_event_msgq, sizeof(struct event_item), 10, 4); - -/* Output configuration */ -static uint8_t pvt_output_level = 2; -static uint8_t nmea_output_level; -static uint8_t event_output_level; - -static const char *gnss_err_to_str(int err) -{ - switch (err) { - case -NRF_EPERM: - return "Modem library not initialized"; - case -NRF_ENOMEM: - return "not enough shared memory"; - case -NRF_EACCES: - return "GNSS not enabled in system or functional mode"; - case -NRF_EINVAL: - return "wrong state or invalid data"; - case -NRF_ENOMSG: - return "no data to read for selected data type"; - case -NRF_EOPNOTSUPP: - return "operation not supported by modem firmware"; - case -NRF_ESHUTDOWN: - return "modem was shut down"; - case -NRF_EMSGSIZE: - return "supplied buffer too small"; - default: - return "unknown err value"; - } -} - -static int get_event_data(void **dest, uint8_t type, size_t len) -{ - int err; - void *data; - - data = k_malloc(len); - if (data == NULL) { - return -1; - } - - err = nrf_modem_gnss_read(data, len, type); - if (err) { - printk("Failed to read event data, type: %d, error: %d (%s)\n", - type, err, gnss_err_to_str(err)); - k_free(data); - return -1; - } - - *dest = data; - - return 0; -} - -/* This handler is called in ISR, so need to avoid heavy processing */ -static void gnss_event_handler(int event_id) -{ - int err = 0; - struct event_item event; - - event.id = event_id; - event.data = NULL; - - /* Copy data for those events which have associated data */ - switch (event_id) { - case NRF_MODEM_GNSS_EVT_PVT: - err = get_event_data(&event.data, - NRF_MODEM_GNSS_DATA_PVT, - sizeof(struct nrf_modem_gnss_pvt_data_frame)); - break; - - case NRF_MODEM_GNSS_EVT_FIX: - /* Data is not read for the fix notification because we use the PVT notification - * and the data is the same. - */ - if (operation_mode == GNSS_OP_MODE_PERIODIC_FIX) { - k_work_cancel_delayable(&gnss_timeout_work); - k_work_submit(&gnss_stop_work); - } - break; - - case NRF_MODEM_GNSS_EVT_NMEA: - err = get_event_data(&event.data, - NRF_MODEM_GNSS_DATA_NMEA, - sizeof(struct nrf_modem_gnss_nmea_data_frame)); - break; - - case NRF_MODEM_GNSS_EVT_AGNSS_REQ: - err = get_event_data(&event.data, - NRF_MODEM_GNSS_DATA_AGNSS_REQ, - sizeof(struct nrf_modem_gnss_agnss_data_frame)); - break; - - default: - break; - } - - if (err) { - /* Failed to get event data */ - return; - } - - err = k_msgq_put(&gnss_event_msgq, &event, K_NO_WAIT); - if (err) { - /* Failed to put event into queue */ - k_free(event.data); - } -} - -#if defined(CONFIG_LWM2M_CARRIER) -static time_t gnss_mktime(struct nrf_modem_gnss_datetime *date) -{ - struct tm tm = { - .tm_sec = date->seconds, - .tm_min = date->minute, - .tm_hour = date->hour, - .tm_mday = date->day, - .tm_mon = date->month - 1, - .tm_year = date->year - 1900 - }; - - return mktime(&tm); -} - -static void gnss_carrier_location(struct nrf_modem_gnss_pvt_data_frame *pvt) -{ - if (pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { - lwm2m_carrier_location_set(pvt->latitude, - pvt->longitude, - pvt->altitude, - (uint32_t)gnss_mktime(&pvt->datetime), - pvt->accuracy); - lwm2m_carrier_velocity_set(pvt->heading, - pvt->speed, - pvt->vertical_speed, - pvt->speed_accuracy, - pvt->vertical_speed_accuracy); - } -} -#endif - -static void print_pvt_flags(struct nrf_modem_gnss_pvt_data_frame *pvt) -{ - mosh_print(""); - mosh_print( - "Fix valid: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID ? "true" : "false"); - mosh_print( - "Leap second valid: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_LEAP_SECOND_VALID ? "true" : "false"); - mosh_print( - "Sleep between PVT: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_SLEEP_BETWEEN_PVT ? "true" : "false"); - mosh_print( - "Deadline missed: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED ? "true" : "false"); - mosh_print( - "Insuf. time window: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_NOT_ENOUGH_WINDOW_TIME ? "true" : "false"); - mosh_print( - "Velocity valid: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_VELOCITY_VALID ? "true" : "false"); - mosh_print( - "Scheduled download: %s", - pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_SCHED_DOWNLOAD ? "true" : "false"); -} - -static void print_pvt(struct nrf_modem_gnss_pvt_data_frame *pvt) -{ - if (pvt_output_level == 0) { - return; - } - - print_pvt_flags(pvt); - - mosh_print("Execution time: %u ms", pvt->execution_time); - - if (pvt->flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) { - mosh_print( - "Time: %02d.%02d.%04d %02d:%02d:%02d.%03d", - pvt->datetime.day, - pvt->datetime.month, - pvt->datetime.year, - pvt->datetime.hour, - pvt->datetime.minute, - pvt->datetime.seconds, - pvt->datetime.ms); - - mosh_print("Latitude: %f", pvt->latitude); - mosh_print("Longitude: %f", pvt->longitude); - mosh_print("Accuracy: %.1f m", (double)pvt->accuracy); - mosh_print("Altitude: %.1f m", (double)pvt->altitude); - mosh_print("Altitude accuracy: %.1f m", (double)pvt->altitude_accuracy); - mosh_print("Speed: %.1f m/s", (double)pvt->speed); - mosh_print("Speed accuracy: %.1f m/s", (double)pvt->speed_accuracy); - mosh_print("V. speed: %.1f m/s", (double)pvt->vertical_speed); - mosh_print("V. speed accuracy: %.1f m/s", (double)pvt->vertical_speed_accuracy); - mosh_print("Heading: %.1f deg", (double)pvt->heading); - mosh_print("Heading accuracy: %.1f deg", (double)pvt->heading_accuracy); - mosh_print("PDOP: %.1f", (double)pvt->pdop); - mosh_print("HDOP: %.1f", (double)pvt->hdop); - mosh_print("VDOP: %.1f", (double)pvt->vdop); - mosh_print("TDOP: %.1f", (double)pvt->tdop); - - mosh_print( - "Google maps URL: https://maps.google.com/?q=%f,%f", - pvt->latitude, pvt->longitude); - } - - if (pvt_output_level < 2) { - return; - } - - /* SV data */ - for (int i = 0; i < NRF_MODEM_GNSS_MAX_SATELLITES; i++) { - if (pvt->sv[i].sv == 0) { - /* SV not valid, skip */ - continue; - } - - mosh_print( - "SV: %3d C/N0: %4.1f el: %2d az: %3d signal: %d in fix: %d unhealthy: %d", - pvt->sv[i].sv, - pvt->sv[i].cn0 * 0.1, - pvt->sv[i].elevation, - pvt->sv[i].azimuth, - pvt->sv[i].signal, - pvt->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_USED_IN_FIX ? 1 : 0, - pvt->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_UNHEALTHY ? 1 : 0); - } -} - -static void print_nmea(struct nrf_modem_gnss_nmea_data_frame *nmea) -{ - if (nmea_output_level == 0) { - return; - } - - for (int i = 0; i < NRF_MODEM_GNSS_NMEA_MAX_LEN; i++) { - if (nmea->nmea_str[i] == '\r' || nmea->nmea_str[i] == '\n') { - nmea->nmea_str[i] = '\0'; - break; - } - } - mosh_print("%s", nmea->nmea_str); -} - -static void data_handler_thread_fn(void) -{ - struct event_item event; - struct nrf_modem_gnss_agnss_data_frame *agnss_data_frame; - - while (true) { - k_msgq_get(&gnss_event_msgq, &event, K_FOREVER); - - switch (event.id) { - case NRF_MODEM_GNSS_EVT_PVT: - print_pvt((struct nrf_modem_gnss_pvt_data_frame *)event.data); -#if defined(CONFIG_LWM2M_CARRIER) - gnss_carrier_location((struct nrf_modem_gnss_pvt_data_frame *)event.data); -#endif - break; - - case NRF_MODEM_GNSS_EVT_FIX: - if (event_output_level > 0) { - mosh_print("GNSS: Got fix"); - } - break; - - case NRF_MODEM_GNSS_EVT_NMEA: - print_nmea((struct nrf_modem_gnss_nmea_data_frame *)event.data); - break; - - case NRF_MODEM_GNSS_EVT_AGNSS_REQ: - agnss_data_frame = (struct nrf_modem_gnss_agnss_data_frame *)event.data; - - /* GPS data need is always expected to be present and first in list. */ - __ASSERT(agnss_data_frame->system_count > 0, - "GNSS system data need not found"); - __ASSERT(agnss_data_frame->system[0].system_id == NRF_MODEM_GNSS_SYSTEM_GPS, - "GPS data need not found"); - - if (event_output_level > 0) { - char flags_string[48]; - - agnss_data_flags_str_get( - flags_string, - agnss_data_frame->data_flags); - - mosh_print("GNSS: A-GNSS data needed: Flags: %s", flags_string); - for (int i = 0; i < agnss_data_frame->system_count; i++) { - mosh_print( - "GNSS: A-GNSS data needed: " - "%s ephe: 0x%llx, alm: 0x%llx", - gnss_system_str_get( - agnss_data_frame->system[i].system_id), - agnss_data_frame->system[i].sv_mask_ephe, - agnss_data_frame->system[i].sv_mask_alm); - } - } - - memcpy(&agnss_need, event.data, sizeof(agnss_need)); - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) - if (agnss_automatic) { - k_work_submit_to_queue(&mosh_common_work_q, &get_agnss_data_work); - } -#endif - -#if defined(CONFIG_NRF_CLOUD_PGPS) - if (pgps_enabled && agnss_data_frame->system[0].sv_mask_ephe != 0x0) { - k_work_submit_to_queue(&mosh_common_work_q, - ¬ify_pgps_prediction_work); - } -#endif - break; - - case NRF_MODEM_GNSS_EVT_BLOCKED: - if (event_output_level > 0) { - mosh_print("GNSS: Blocked by LTE"); - } - break; - - case NRF_MODEM_GNSS_EVT_UNBLOCKED: - if (event_output_level > 0) { - mosh_print("GNSS: Unblocked by LTE"); - } - break; - - case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP: - if (event_output_level > 0) { - mosh_print("GNSS: Wakeup"); - } - break; - - case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_TIMEOUT: - if (event_output_level > 0) { - mosh_print("GNSS: Timeout, entering sleep"); - } - break; - - case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX: - if (event_output_level > 0) { - mosh_print("GNSS: Fix, entering sleep"); - } - break; - - case NRF_MODEM_GNSS_EVT_REF_ALT_EXPIRED: - if (event_output_level > 0) { - mosh_print("GNSS: Reference altitude for 3-satellite fix expired"); - } - break; - - default: - if (event_output_level > 0) { - mosh_warn("GNSS: Unknown event %d received", event.id); - } - break; - } - - k_free(event.data); - } -} - -K_THREAD_DEFINE(gnss_data_handler, GNSS_DATA_HANDLER_THREAD_STACK_SIZE, - data_handler_thread_fn, NULL, NULL, NULL, - K_PRIO_PREEMPT(GNSS_DATA_HANDLER_THREAD_PRIORITY), 0, 0); - -static int gnss_enable_all_nmeas(void) -{ - return nrf_modem_gnss_nmea_mask_set( - NRF_MODEM_GNSS_NMEA_GGA_MASK | - NRF_MODEM_GNSS_NMEA_GLL_MASK | - NRF_MODEM_GNSS_NMEA_GSA_MASK | - NRF_MODEM_GNSS_NMEA_GSV_MASK | - NRF_MODEM_GNSS_NMEA_RMC_MASK); -} - -#if defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) || \ - defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS) -static void assistance_result_cb(uint16_t object_id, int32_t result_code) -{ - if (object_id != GNSS_ASSIST_OBJECT_ID) { - return; - } - - switch (result_code) { - case LOCATION_ASSIST_RESULT_CODE_OK: - break; - - case LOCATION_ASSIST_RESULT_CODE_PERMANENT_ERR: - case LOCATION_ASSIST_RESULT_CODE_TEMP_ERR: - case LOCATION_ASSIST_RESULT_CODE_NO_RESP_ERR: - default: - mosh_error("GNSS: Getting assistance data using LwM2M failed, result: %d", - result_code); - break; - } -} -#endif - -#if defined(CONFIG_NRF_CLOUD_AGNSS) && !defined(CONFIG_NRF_CLOUD_MQTT) && \ - !defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) -static int serving_cell_info_get(struct lte_lc_cell *serving_cell) -{ - int err; - char resp_buf[MODEM_INFO_MAX_RESPONSE_SIZE]; - - err = modem_info_string_get(MODEM_INFO_CELLID, - resp_buf, - MODEM_INFO_MAX_RESPONSE_SIZE); - if (err < 0) { - return err; - } - - serving_cell->id = strtol(resp_buf, NULL, 16); - - err = modem_info_string_get(MODEM_INFO_AREA_CODE, - resp_buf, - MODEM_INFO_MAX_RESPONSE_SIZE); - if (err < 0) { - return err; - } - - serving_cell->tac = strtol(resp_buf, NULL, 16); - - err = modem_info_short_get(MODEM_INFO_RSRP, &serving_cell->rsrp); - if (err < 0) { - return err; - } - - if (serving_cell->rsrp == 255) { - /* No valid RSRP, modem is probably in PSM and the cell information might not be - * valid anymore. %NCELLMEAS could be used to wake up the modem and perform a cell - * search instead, but this is good enough for modem_shell. - */ - serving_cell->rsrp = 0; /* -140 dBm */ - } - - /* Request for MODEM_INFO_MNC returns both MNC and MCC in the same string. */ - err = modem_info_string_get(MODEM_INFO_OPERATOR, - resp_buf, - MODEM_INFO_MAX_RESPONSE_SIZE); - if (err < 0) { - return err; - } - - serving_cell->mnc = strtol(&resp_buf[3], NULL, 10); - /* Null-terminate MCC, read and store it. */ - resp_buf[3] = '\0'; - serving_cell->mcc = strtol(resp_buf, NULL, 10); - - return 0; -} -#endif - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) -static void get_filtered_agnss_request(struct nrf_modem_gnss_agnss_data_frame *agnss_request) -{ - memset(agnss_request, 0, sizeof(*agnss_request)); - - agnss_request->system_count = agnss_need.system_count; - - for (int i = 0; i < agnss_need.system_count; i++) { - const struct nrf_modem_gnss_agnss_system_data_need *src = &agnss_need.system[i]; - struct nrf_modem_gnss_agnss_system_data_need *dst = &agnss_request->system[i]; - - dst->system_id = src->system_id; - - if (agnss_inject_ephe) { - dst->sv_mask_ephe = src->sv_mask_ephe; - } - if (agnss_inject_alm) { - dst->sv_mask_alm = src->sv_mask_alm; - } - } - - if (agnss_inject_utc) { - agnss_request->data_flags |= - agnss_need.data_flags & NRF_MODEM_GNSS_AGNSS_GPS_UTC_REQUEST; - } - if (agnss_inject_klob) { - agnss_request->data_flags |= - agnss_need.data_flags & NRF_MODEM_GNSS_AGNSS_KLOBUCHAR_REQUEST; - } - if (agnss_inject_neq) { - agnss_request->data_flags |= - agnss_need.data_flags & NRF_MODEM_GNSS_AGNSS_NEQUICK_REQUEST; - } - if (agnss_inject_time) { - agnss_request->data_flags |= - agnss_need.data_flags & - NRF_MODEM_GNSS_AGNSS_GPS_SYS_TIME_AND_SV_TOW_REQUEST; - } - if (agnss_inject_pos) { - agnss_request->data_flags |= - agnss_need.data_flags & NRF_MODEM_GNSS_AGNSS_POSITION_REQUEST; - } - if (agnss_inject_int) { - agnss_request->data_flags |= - agnss_need.data_flags & NRF_MODEM_GNSS_AGNSS_INTEGRITY_REQUEST; - } -} - -static void get_agnss_data(struct k_work *item) -{ - ARG_UNUSED(item); - - int err; - char flags_string[48]; - struct nrf_modem_gnss_agnss_data_frame agnss_request; - - get_filtered_agnss_request(&agnss_request); - - agnss_data_flags_str_get(flags_string, agnss_request.data_flags); - - mosh_print( - "GNSS: Getting A-GNSS data from %s...", -#if defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) - "LwM2M" -#elif defined(CONFIG_NRF_CLOUD_AGNSS) - "nRF Cloud" -#else - "SUPL" -#endif - ); - mosh_print("GNSS: A-GNSS request: flags: %s", flags_string); - for (int i = 0; i < agnss_request.system_count; i++) { - mosh_print("GNSS: A-GNSS request: %s sv_mask_ephe: 0x%llx, sv_mask_alm: 0x%llx", - gnss_system_str_get(agnss_request.system[i].system_id), - agnss_request.system[i].sv_mask_ephe, - agnss_request.system[i].sv_mask_alm); - } - -#if defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS) - if (!cloud_lwm2m_is_connected()) { - mosh_error("GNSS: LwM2M not connected, can't request A-GNSS data"); - return; - } - location_assistance_set_result_code_cb(assistance_result_cb); - location_assistance_agnss_set_mask(&agnss_request); - err = location_assistance_agnss_request_send(cloud_lwm2m_client_ctx_get()); - if (err) { - mosh_error("GNSS: Failed to request A-GNSS data, error: %d", err); - } -#elif defined(CONFIG_NRF_CLOUD_AGNSS) -#if defined(CONFIG_NRF_CLOUD_MQTT) - err = nrf_cloud_agnss_request(&agnss_request); - if (err == -EACCES) { - mosh_error("GNSS: Not connected to nRF Cloud"); - } else if (err) { - mosh_error("GNSS: Failed to request A-GNSS data, error: %d", err); - } -#else /* REST and CoAP */ -#if defined(CONFIG_NRF_CLOUD_REST) - err = nrf_cloud_jwt_generate(0, jwt_buf, sizeof(jwt_buf)); - if (err) { - mosh_error("GNSS: Failed to generate JWT, error: %d", err); - return; - } - - struct nrf_cloud_rest_context rest_ctx = { - .connect_socket = -1, - .keep_alive = false, - .timeout_ms = NRF_CLOUD_REST_TIMEOUT_NONE, - .auth = jwt_buf, - .rx_buf = rx_buf, - .rx_buf_len = sizeof(rx_buf), - }; -#endif - - struct nrf_cloud_rest_agnss_request request = { - .type = NRF_CLOUD_REST_AGNSS_REQ_CUSTOM, - .agnss_req = &agnss_request, - }; - - struct nrf_cloud_rest_agnss_result result = { - .buf = agnss_data_buf, - .buf_sz = sizeof(agnss_data_buf), - }; - - struct lte_lc_cells_info net_info = { 0 }; - -#if defined(CONFIG_NRF_CLOUD_AGNSS_FILTERED_RUNTIME) - if (gnss_filtered_ephemerides_enabled) { - request.mask_angle = gnss_elevation; - mosh_print("GNSS: Requesting filtered ephemeris; elevation = %u", gnss_elevation); - } - request.filtered = gnss_filtered_ephemerides_enabled; -#endif /* CONFIG_NRF_CLOUD_AGNSS_FILTERED_RUNTIME */ - - err = serving_cell_info_get(&net_info.current_cell); - if (err) { - mosh_warn("GNSS: Could not get cell info, error: %d", err); - } else { - /* Network info for the location request. */ - request.net_info = &net_info; - } - -#if defined(CONFIG_NRF_CLOUD_REST) - err = nrf_cloud_rest_agnss_data_get(&rest_ctx, &request, &result); -#elif defined(CONFIG_NRF_CLOUD_COAP) - err = nrf_cloud_coap_agnss_data_get(&request, &result); -#endif - if (err) { - mosh_error("GNSS: Failed to get A-GNSS data, error: %d", err); - return; - } - - mosh_print("GNSS: Processing A-GNSS data"); - - err = nrf_cloud_agnss_process(result.buf, result.agnss_sz); - if (err) { - mosh_error("GNSS: Failed to process A-GNSS data, error: %d", err); - return; - } - - mosh_print("GNSS: A-GNSS data injected to the modem"); -#endif -#else /* CONFIG_SUPL_CLIENT_LIB */ - if (open_supl_socket() == 0) { - err = supl_session((void *)&agnss_request); - if (err) { - mosh_error("GNSS: Failed to get A-GNSS data, error: %d", err); - } - close_supl_socket(); - } -#endif -} -#endif /* CONFIG_NRF_CLOUD_AGNSS || CONFIG_SUPL_CLIENT_LIB */ - -#if defined(CONFIG_SUPL_CLIENT_LIB) -static void get_agnss_data_type_string(char *type_string, uint16_t type) -{ - switch (type) { - case NRF_MODEM_GNSS_AGNSS_GPS_UTC_PARAMETERS: - (void)strcpy(type_string, "utc"); - break; - case NRF_MODEM_GNSS_AGNSS_GPS_EPHEMERIDES: - (void)strcpy(type_string, "ephe"); - break; - case NRF_MODEM_GNSS_AGNSS_GPS_ALMANAC: - (void)strcpy(type_string, "alm"); - break; - case NRF_MODEM_GNSS_AGNSS_KLOBUCHAR_IONOSPHERIC_CORRECTION: - (void)strcpy(type_string, "klob"); - break; - case NRF_MODEM_GNSS_AGNSS_NEQUICK_IONOSPHERIC_CORRECTION: - (void)strcpy(type_string, "neq"); - break; - case NRF_MODEM_GNSS_AGNSS_GPS_SYSTEM_CLOCK_AND_TOWS: - (void)strcpy(type_string, "time"); - break; - case NRF_MODEM_GNSS_AGNSS_LOCATION: - (void)strcpy(type_string, "pos"); - break; - case NRF_MODEM_GNSS_AGPS_INTEGRITY: - (void)strcpy(type_string, "int"); - break; - default: - (void)strcpy(type_string, "UNKNOWN"); - break; - } -} - -static int inject_agnss_data(void *agnss, - size_t agnss_size, - uint16_t type, - void *user_data) -{ - ARG_UNUSED(user_data); - - int err; - char type_string[16]; - - err = nrf_modem_gnss_agnss_write(agnss, agnss_size, type); - - get_agnss_data_type_string(type_string, type); - - if (err) { - mosh_error("GNSS: Failed to inject A-GNSS data, type: %s, error: %d (%s)", - type_string, err, gnss_err_to_str(err)); - return err; - } - - mosh_print("GNSS: Injected A-GNSS data, type: %s, size: %d", type_string, agnss_size); - - return 0; -} -#endif /* CONFIG_SUPL_CLIENT_LIB */ - -static void start_gnss_work_fn(struct k_work *item) -{ - ARG_UNUSED(item); - - int err; - - err = nrf_modem_gnss_start(); - - if (err) { - mosh_error("GNSS: Failed to start GNSS, error: %d (%s)", err, gnss_err_to_str(err)); - } else { - if (event_output_level > 0) { - mosh_print("GNSS: Search started"); - } - } - - k_work_schedule(&gnss_start_work, K_SECONDS(periodic_fix_interval)); - - if (periodic_fix_retry > 0 && periodic_fix_retry < periodic_fix_interval) { - k_work_schedule(&gnss_timeout_work, K_SECONDS(periodic_fix_retry)); - } -} - -static void stop_gnss_work_fn(struct k_work *item) -{ - ARG_UNUSED(item); - - int err; - - err = nrf_modem_gnss_stop(); - if (err) { - mosh_error("GNSS: Failed to stop GNSS, error: %d (%s)", err, gnss_err_to_str(err)); - } -} - -static void handle_timeout_work_fn(struct k_work *item) -{ - ARG_UNUSED(item); - - int err; - - if (event_output_level > 0) { - mosh_print("GNSS: Search timeout"); - } - - err = nrf_modem_gnss_stop(); - if (err) { - mosh_error("GNSS: Failed to stop GNSS, error: %d (%s)", err, gnss_err_to_str(err)); - } -} - -#if defined(CONFIG_NRF_CLOUD_PGPS) -#if !defined(CONFIG_NRF_CLOUD_MQTT) -static void get_pgps_data_work_fn(struct k_work *work) -{ - ARG_UNUSED(work); - - int err; - -#if defined(CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS) - mosh_print("GNSS: Getting P-GPS predictions from LwM2M..."); - - location_assistance_set_result_code_cb(assistance_result_cb); - err = location_assist_pgps_set_prediction_count(pgps_request.prediction_count); - err |= location_assist_pgps_set_prediction_interval(pgps_request.prediction_period_min); - location_assist_pgps_set_start_gps_day(pgps_request.gps_day); - err |= location_assist_pgps_set_start_time(pgps_request.gps_time_of_day); - if (err) { - mosh_error("GNSS: Failed to set P-GPS request parameters"); - return; - } - - err = location_assistance_pgps_request_send(cloud_lwm2m_client_ctx_get()); - if (err) { - mosh_error("GNSS: Failed to request P-GPS data, err: %d", err); - } else { - mosh_print("GNSS: P-GPS predictions requested"); - } -#else /* !CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS */ - mosh_print("GNSS: Getting P-GPS predictions from nRF Cloud..."); - - struct nrf_cloud_rest_pgps_request request = { - .pgps_req = &pgps_request - }; - -#if defined(CONFIG_NRF_CLOUD_REST) - err = nrf_cloud_jwt_generate(0, jwt_buf, sizeof(jwt_buf)); - if (err) { - mosh_error("GNSS: Failed to generate JWT, error: %d", err); - return; - } - - struct nrf_cloud_rest_context rest_ctx = { - .connect_socket = -1, - .keep_alive = false, - .timeout_ms = NRF_CLOUD_REST_TIMEOUT_NONE, - .auth = jwt_buf, - .rx_buf = rx_buf, - .rx_buf_len = sizeof(rx_buf), - }; - - err = nrf_cloud_rest_pgps_data_get(&rest_ctx, &request); -#elif defined(CONFIG_NRF_CLOUD_COAP) - struct nrf_cloud_pgps_result file_location = {0}; - - static char host[64]; - static char path[128]; - - memset(host, 0, sizeof(host)); - memset(path, 0, sizeof(path)); - - file_location.host = host; - file_location.host_sz = sizeof(host); - file_location.path = path; - file_location.path_sz = sizeof(path); - - err = nrf_cloud_coap_pgps_url_get(&request, &file_location); - -#endif - if (err) { - mosh_error("GNSS: Failed to get P-GPS data, error: %d", err); - - nrf_cloud_pgps_request_reset(); - - return; - } - - mosh_print("GNSS: Processing P-GPS response"); - -#if defined(CONFIG_NRF_CLOUD_REST) - err = nrf_cloud_pgps_process(rest_ctx.response, rest_ctx.response_len); -#elif defined(CONFIG_NRF_CLOUD_COAP) - err = nrf_cloud_pgps_update(&file_location); -#endif - if (err) { - mosh_error("GNSS: Failed to process P-GPS response, error: %d", err); - - nrf_cloud_pgps_request_reset(); - - return; - } - - mosh_print("GNSS: P-GPS response processed"); - - err = nrf_cloud_pgps_notify_prediction(); - if (err) { - mosh_error("GNSS: Failed to request current prediction, error: %d", err); - - return; - } - - mosh_print("GNSS: P-GPS predictions requested"); -#endif /* CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS */ -} -#endif /* !CONFIG_NRF_CLOUD_MQTT */ - -static void inject_pgps_data_work_fn(struct k_work *work) -{ - ARG_UNUSED(work); - - int err; - - mosh_print("GNSS: Injecting ephemerides to modem..."); - - err = nrf_cloud_pgps_inject(prediction, &agnss_need); - if (err) { - mosh_error("GNSS: Failed to inject ephemerides to modem"); - } - - err = nrf_cloud_pgps_preemptive_updates(); - if (err) { - mosh_error("GNSS: Failed to request preduction updates"); - } -} - -static void notify_pgps_prediction_work_fn(struct k_work *work) -{ - ARG_UNUSED(work); - - int err; - - err = nrf_cloud_pgps_notify_prediction(); - if (err) { - mosh_error("GNSS: Failed to notify P-GPS predictions"); - } -} - -static void pgps_event_handler(struct nrf_cloud_pgps_event *event) -{ - switch (event->type) { - case PGPS_EVT_READY: - case PGPS_EVT_AVAILABLE: - if (event->prediction != NULL) { - prediction = event->prediction; - - k_work_submit_to_queue(&mosh_common_work_q, &inject_pgps_data_work); - } - break; - -#if !defined(CONFIG_NRF_CLOUD_MQTT) - case PGPS_EVT_REQUEST: - memcpy(&pgps_request, event->request, sizeof(pgps_request)); - - k_work_submit_to_queue(&mosh_common_work_q, &get_pgps_data_work); - break; -#endif - - default: - /* No action needed */ - break; - } -} -#endif /* CONFIG_NRF_CLOUD_PGPS */ - -static void gnss_api_init(void) -{ - int err; - static bool gnss_api_initialized; - - /* Reset event handler in case some other handler was set in the meantime. */ - (void)nrf_modem_gnss_event_handler_set(gnss_event_handler); - - if (gnss_api_initialized) { - return; - } - - /* Make QZSS satellites visible in the NMEA output. */ - err = nrf_modem_gnss_qzss_nmea_mode_set(NRF_MODEM_GNSS_QZSS_NMEA_MODE_CUSTOM); - if (err) { - mosh_warn("GNSS: Failed to enable custom QZSS NMEA mode, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - gnss_api_initialized = true; - - k_work_init(&gnss_stop_work, stop_gnss_work_fn); - k_work_init_delayable(&gnss_start_work, start_gnss_work_fn); - k_work_init_delayable(&gnss_timeout_work, handle_timeout_work_fn); - -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) - k_work_init(&get_agnss_data_work, get_agnss_data); -#endif /* CONFIG_NRF_CLOUD_AGNSS || CONFIG_SUPL_CLIENT_LIB */ - -#if defined(CONFIG_SUPL_CLIENT_LIB) - static struct supl_api supl_api = { - .read = supl_read, - .write = supl_write, - .handler = inject_agnss_data, - .logger = supl_logger, - .counter_ms = k_uptime_get - }; - - (void)supl_init(&supl_api); -#endif /* CONFIG_SUPL_CLIENT_LIB */ -} - -int gnss_start(void) -{ - int err; - - gnss_api_init(); - - if (!nmea_mask_set) { - /* Enable all NMEAs by default */ - if (gnss_enable_all_nmeas() == 0) { - nmea_mask_set = true; - } - } - - if (operation_mode == GNSS_OP_MODE_PERIODIC_FIX) { - k_work_schedule(&gnss_start_work, K_NO_WAIT); - return 0; - } - - err = nrf_modem_gnss_start(); - if (err) { - mosh_error("GNSS: Failed to start GNSS, error: %d (%s)", err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_stop(void) -{ - int err; - - gnss_api_init(); - - if (operation_mode == GNSS_OP_MODE_PERIODIC_FIX) { - k_work_cancel_delayable(&gnss_timeout_work); - k_work_cancel_delayable(&gnss_start_work); - nrf_modem_gnss_stop(); - return 0; - } - - err = nrf_modem_gnss_stop(); - if (err) { - mosh_error("GNSS: Failed to stop GNSS, error: %d (%s)", err, gnss_err_to_str(err)); - } - - return err; -} - - -int gnss_delete_data(enum gnss_data_delete data) -{ - int err; - uint32_t delete_mask; - - gnss_api_init(); - - switch (data) { - case GNSS_DATA_DELETE_EPHEMERIDES: - delete_mask = NRF_MODEM_GNSS_DELETE_EPHEMERIDES; - break; - - case GNSS_DATA_DELETE_EKF: - delete_mask = NRF_MODEM_GNSS_DELETE_EKF; - break; - - case GNSS_DATA_DELETE_ALL: - /* Delete everything else but TCXO frequency offset data. Deleting EKF state is not - * supported by older MFWs and returns an error. Because of this EKF state is - * deleted separately and the return value is ignored. - */ - (void)nrf_modem_gnss_nv_data_delete(NRF_MODEM_GNSS_DELETE_EKF); - - delete_mask = NRF_MODEM_GNSS_DELETE_EPHEMERIDES | - NRF_MODEM_GNSS_DELETE_ALMANACS | - NRF_MODEM_GNSS_DELETE_IONO_CORRECTION_DATA | - NRF_MODEM_GNSS_DELETE_LAST_GOOD_FIX | - NRF_MODEM_GNSS_DELETE_GPS_TOW | - NRF_MODEM_GNSS_DELETE_GPS_WEEK | - NRF_MODEM_GNSS_DELETE_UTC_DATA | - NRF_MODEM_GNSS_DELETE_GPS_TOW_PRECISION; - break; - - case GNSS_DATA_DELETE_TCXO: - delete_mask = NRF_MODEM_GNSS_DELETE_TCXO_OFFSET; - break; - - default: - mosh_error("GNSS: Invalid erase data value"); - return -1; - } - - err = nrf_modem_gnss_nv_data_delete(delete_mask); - if (err) { - mosh_error("GNSS: Failed to delete NV data, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_delete_data_custom(uint32_t mask) -{ - int err; - - err = nrf_modem_gnss_nv_data_delete(mask); - if (err) { - mosh_error("GNSS: Failed to delete NV data, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_continuous_mode(void) -{ - int err; - - gnss_api_init(); - - operation_mode = GNSS_OP_MODE_CONTINUOUS; - - err = nrf_modem_gnss_fix_interval_set(1); - if (err) { - mosh_error("GNSS: Failed to set fix interval, error: %d (%s)", - err, gnss_err_to_str(err)); - return err; - } - - err = nrf_modem_gnss_fix_retry_set(0); - if (err) { - mosh_error("GNSS: Failed to set fix retry, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_single_fix_mode(uint16_t fix_retry) -{ - int err; - - gnss_api_init(); - - operation_mode = GNSS_OP_MODE_SINGLE_FIX; - - err = nrf_modem_gnss_fix_interval_set(0); - if (err) { - mosh_error("GNSS: Failed to set fix interval, error: %d (%s)", - err, gnss_err_to_str(err)); - return err; - } - - err = nrf_modem_gnss_fix_retry_set(fix_retry); - if (err) { - mosh_error("GNSS: Failed to set fix retry, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_periodic_fix_mode(uint32_t fix_interval, uint16_t fix_retry) -{ - int err; - - gnss_api_init(); - - operation_mode = GNSS_OP_MODE_PERIODIC_FIX; - periodic_fix_interval = fix_interval; - periodic_fix_retry = fix_retry; - - /* Periodic fix mode controlled by the application, GNSS is used in continuous tracking - * mode and it's started and stopped as needed. - */ - err = nrf_modem_gnss_fix_interval_set(1); - if (err) { - mosh_error("GNSS: Failed to set fix interval, error: %d (%s)", - err, gnss_err_to_str(err)); - return err; - } - - err = nrf_modem_gnss_fix_retry_set(0); - if (err) { - mosh_error("GNSS: Failed to set fix retry, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_periodic_fix_mode_gnss(uint16_t fix_interval, uint16_t fix_retry) -{ - int err; - - gnss_api_init(); - - operation_mode = GNSS_OP_MODE_PERIODIC_FIX_GNSS; - - err = nrf_modem_gnss_fix_interval_set(fix_interval); - if (err) { - mosh_error("GNSS: Failed to set fix interval, error: %d (%s)", - err, gnss_err_to_str(err)); - return err; - } - - err = nrf_modem_gnss_fix_retry_set(fix_retry); - if (err) { - mosh_error("GNSS: Failed to set fix retry, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_system_mask(uint8_t system_mask) -{ - int err; - - err = nrf_modem_gnss_signal_mask_set(system_mask); - if (err) { - mosh_error("GNSS: Failed to set system mask, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_duty_cycling_policy(enum gnss_duty_cycling_policy policy) -{ - int err; - uint8_t power_mode; - - gnss_api_init(); - - switch (policy) { - case GNSS_DUTY_CYCLING_DISABLED: - power_mode = NRF_MODEM_GNSS_PSM_DISABLED; - break; - - case GNSS_DUTY_CYCLING_PERFORMANCE: - power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_PERFORMANCE; - break; - - case GNSS_DUTY_CYCLING_POWER: - power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_POWER; - break; - - default: - mosh_error("GNSS: Invalid duty cycling policy value %d", policy); - return -1; - } - - err = nrf_modem_gnss_power_mode_set(power_mode); - if (err) { - mosh_error("GNSS: Failed to set duty cycling policy, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_elevation_threshold(uint8_t elevation) -{ - int err; - - gnss_api_init(); - - err = nrf_modem_gnss_elevation_threshold_set(elevation); - if (err) { - mosh_error("GNSS: Failed to set elevation threshold, error: %d (%s)", - err, gnss_err_to_str(err)); - } else { - gnss_elevation = elevation; - } - - return err; -} - -int gnss_set_agnss_filtered_ephemerides(bool enable) -{ -#if defined(CONFIG_NRF_CLOUD_AGNSS_FILTERED_RUNTIME) - gnss_filtered_ephemerides_enabled = enable; - return 0; -#else - mosh_error("GNSS: A-GNSS filtered ephemerides are only supported with nRF Cloud REST-only " - "configuration."); - return -EOPNOTSUPP; -#endif -} - -int gnss_set_use_case(bool low_accuracy_enabled, bool scheduled_downloads_disabled) -{ - int err; - uint8_t use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START; - - gnss_api_init(); - - if (low_accuracy_enabled) { - use_case |= NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY; - } - if (scheduled_downloads_disabled) { - use_case |= NRF_MODEM_GNSS_USE_CASE_SCHED_DOWNLOAD_DISABLE; - } - - err = nrf_modem_gnss_use_case_set(use_case); - if (err) { - mosh_error("GNSS: Failed to set use case, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_nmea_mask(uint16_t nmea_mask) -{ - int err; - - gnss_api_init(); - - err = nrf_modem_gnss_nmea_mask_set(nmea_mask); - if (err) { - mosh_error("GNSS: Failed to set NMEA mask, error: %d (%s)", - err, gnss_err_to_str(err)); - } else { - nmea_mask_set = true; - } - - return err; -} - -int gnss_set_priority_time_windows(bool value) -{ - int err; - - gnss_api_init(); - - if (value) { - err = nrf_modem_gnss_prio_mode_enable(); - } else { - err = nrf_modem_gnss_prio_mode_disable(); - } - - if (err) { - mosh_error("GNSS: Failed to set priority time windows, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_dynamics_mode(enum gnss_dynamics_mode mode) -{ - int err; - uint32_t dynamics_mode; - - gnss_api_init(); - - switch (mode) { - case GNSS_DYNAMICS_MODE_GENERAL: - dynamics_mode = NRF_MODEM_GNSS_DYNAMICS_GENERAL_PURPOSE; - break; - case GNSS_DYNAMICS_MODE_STATIONARY: - dynamics_mode = NRF_MODEM_GNSS_DYNAMICS_STATIONARY; - break; - case GNSS_DYNAMICS_MODE_PEDESTRIAN: - dynamics_mode = NRF_MODEM_GNSS_DYNAMICS_PEDESTRIAN; - break; - case GNSS_DYNAMICS_MODE_AUTOMOTIVE: - dynamics_mode = NRF_MODEM_GNSS_DYNAMICS_AUTOMOTIVE; - break; - default: - mosh_error("GNSS: Invalid dynamics mode value %d", mode); - return -EINVAL; - } - - err = nrf_modem_gnss_dyn_mode_change(dynamics_mode); - if (err) { - mosh_error("GNSS: Failed to change dynamics mode, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_qzss_nmea_mode(enum gnss_qzss_nmea_mode mode) -{ - int err; - uint8_t nmea_mode; - - gnss_api_init(); - - switch (mode) { - case GNSS_QZSS_NMEA_MODE_STANDARD: - nmea_mode = NRF_MODEM_GNSS_QZSS_NMEA_MODE_STANDARD; - break; - - case GNSS_QZSS_NMEA_MODE_CUSTOM: - nmea_mode = NRF_MODEM_GNSS_QZSS_NMEA_MODE_CUSTOM; - break; - - default: - mosh_error("GNSS: Invalid QZSS NMEA mode value %d", mode); - return -EINVAL; - } - - err = nrf_modem_gnss_qzss_nmea_mode_set(nmea_mode); - if (err) { - mosh_error("GNSS: Failed to set QZSS NMEA mode, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_qzss_mask(uint16_t mask) -{ - int err; - - gnss_api_init(); - - err = nrf_modem_gnss_qzss_prn_mask_set(mask); - if (err) { - mosh_error("GNSS: Failed to set QZSS PRN mask, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_1pps_mode(const struct gnss_1pps_mode *config) -{ - int err; - struct nrf_modem_gnss_1pps_config pps_config; - - gnss_api_init(); - - if (config->enable) { - pps_config.pulse_interval = config->pulse_interval; - pps_config.pulse_width = config->pulse_width; - pps_config.apply_start_time = config->apply_start_time; - pps_config.year = config->year; - pps_config.month = config->month; - pps_config.day = config->day; - pps_config.hour = config->hour; - pps_config.minute = config->minute; - pps_config.second = config->second; - - err = nrf_modem_gnss_1pps_enable(&pps_config); - } else { - err = nrf_modem_gnss_1pps_disable(); - } - - if (err) { - mosh_error("GNSS: Failed to set 1PPS mode, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_timing_source(enum gnss_timing_source source) -{ - int err; - uint8_t timing_source; - - gnss_api_init(); - - switch (source) { - case GNSS_TIMING_SOURCE_RTC: - timing_source = NRF_MODEM_GNSS_TIMING_SOURCE_RTC; - break; - - case GNSS_TIMING_SOURCE_TCXO: - timing_source = NRF_MODEM_GNSS_TIMING_SOURCE_TCXO; - break; - - default: - mosh_error("GNSS: Invalid timing source"); - return -EINVAL; - } - - err = nrf_modem_gnss_timing_source_set(timing_source); - if (err) { - mosh_error("GNSS: Failed to set timing source, error: %d (%s)", - err, gnss_err_to_str(err)); - } - - return err; -} - -int gnss_set_agnss_data_enabled(bool ephe, bool alm, bool utc, bool klob, - bool neq, bool time, bool pos, bool integrity) -{ -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) - agnss_inject_ephe = ephe; - agnss_inject_alm = alm; - agnss_inject_utc = utc; - agnss_inject_klob = klob; - agnss_inject_neq = neq; - agnss_inject_time = time; - agnss_inject_pos = pos; - agnss_inject_int = integrity; - - return 0; -#else - mosh_error("GNSS: Enable CONFIG_NRF_CLOUD_AGNSS or CONFIG_SUPL_CLIENT_LIB for " - "A-GNSS support"); - return -EOPNOTSUPP; -#endif -} - -int gnss_set_agnss_automatic(bool value) -{ -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) - agnss_automatic = value; - - return 0; -#else - mosh_error("GNSS: Enable CONFIG_NRF_CLOUD_AGNSS or CONFIG_SUPL_CLIENT_LIB for " - "A-GNSS support"); - return -EOPNOTSUPP; -#endif -} - -#if defined(CONFIG_NRF_CLOUD_AGNSS) -static bool qzss_assistance_is_supported(void) -{ - char resp[32]; - - if (nrf_modem_at_cmd(resp, sizeof(resp), "AT+CGMM") == 0) { - /* nRF9160 does not support QZSS assistance, while nRF91x1 do. */ - if (strstr(resp, "nRF9160") != NULL) { - return false; - } - } - - return true; -} -#endif /* CONFIG_NRF_CLOUD_AGNSS */ - -int gnss_inject_agnss_data(void) -{ -#if defined(CONFIG_NRF_CLOUD_AGNSS) || defined(CONFIG_SUPL_CLIENT_LIB) - gnss_api_init(); - - /* Pretend modem requested all A-GNSS data */ - agnss_need.data_flags = - NRF_MODEM_GNSS_AGNSS_GPS_UTC_REQUEST | - NRF_MODEM_GNSS_AGNSS_KLOBUCHAR_REQUEST | - NRF_MODEM_GNSS_AGNSS_NEQUICK_REQUEST | - NRF_MODEM_GNSS_AGNSS_GPS_SYS_TIME_AND_SV_TOW_REQUEST | - NRF_MODEM_GNSS_AGNSS_POSITION_REQUEST | - NRF_MODEM_GNSS_AGNSS_INTEGRITY_REQUEST; - agnss_need.system_count = 1; - agnss_need.system[0].system_id = NRF_MODEM_GNSS_SYSTEM_GPS; - agnss_need.system[0].sv_mask_ephe = 0xffffffff; - agnss_need.system[0].sv_mask_alm = 0xffffffff; -#if defined(CONFIG_NRF_CLOUD_AGNSS) - if (qzss_assistance_is_supported()) { - agnss_need.system_count = 2; - agnss_need.system[1].system_id = NRF_MODEM_GNSS_SYSTEM_QZSS; - agnss_need.system[1].sv_mask_ephe = 0x3ff; - agnss_need.system[1].sv_mask_alm = 0x3ff; - } -#endif - - k_work_submit_to_queue(&mosh_common_work_q, &get_agnss_data_work); - - return 0; -#else - mosh_error("GNSS: Enable CONFIG_NRF_CLOUD_AGNSS or CONFIG_SUPL_CLIENT_LIB for " - "A-GNSS support"); - return -EOPNOTSUPP; -#endif -} - -int gnss_enable_pgps(void) -{ -#if defined(CONFIG_NRF_CLOUD_PGPS) - int err; - - if (pgps_enabled) { - mosh_error("GNSS: P-GPS already enabled"); - return -EPERM; - } - - gnss_api_init(); - -#if !defined(CONFIG_NRF_CLOUD_MQTT) - k_work_init(&get_pgps_data_work, get_pgps_data_work_fn); -#endif - k_work_init(&inject_pgps_data_work, inject_pgps_data_work_fn); - k_work_init(¬ify_pgps_prediction_work, notify_pgps_prediction_work_fn); - - struct nrf_cloud_pgps_init_param pgps_param = { - .event_handler = pgps_event_handler, - /* storage is defined by CONFIG_NRF_CLOUD_PGPS_STORAGE */ - .storage_base = 0u, - .storage_size = 0u - }; - - err = nrf_cloud_pgps_init(&pgps_param); - if (err == -EACCES) { - mosh_error("GNSS: Not connected to nRF Cloud"); - return err; - } else if (err) { - mosh_error("GNSS: Failed to initialize P-GPS, error: %d", err); - return err; - } - - pgps_enabled = true; - - return 0; -#else - mosh_error("GNSS: Enable CONFIG_NRF_CLOUD_PGPS for P-GPS support"); - return -EOPNOTSUPP; -#endif -} - -static void get_expiry_string(char *string, uint32_t string_len, uint16_t expiry) -{ - if (expiry == UINT16_MAX) { - strncpy(string, "not used", string_len); - } else if (expiry == 0) { - strncpy(string, "expired", string_len); - } else { - snprintf(string, string_len, "%u", expiry); - } -} - -int gnss_get_agnss_expiry(void) -{ - int err; - struct nrf_modem_gnss_agnss_expiry agnss_expiry; - const char *system_string; - char expiry_string[16]; - char expiry_string2[16]; - - err = nrf_modem_gnss_agnss_expiry_get(&agnss_expiry); - if (err) { - mosh_error("GNSS: Failed to query A-GNSS data expiry, error: %d (%s)", - err, gnss_err_to_str(err)); - return err; - } - - mosh_print("Data flags: 0x%x", agnss_expiry.data_flags); - mosh_print("Time valid: %s", - agnss_expiry.data_flags & NRF_MODEM_GNSS_AGNSS_GPS_SYS_TIME_AND_SV_TOW_REQUEST ? - "false" : "true"); - get_expiry_string(expiry_string, sizeof(expiry_string), agnss_expiry.utc_expiry); - mosh_print("UTC: %s", expiry_string); - get_expiry_string(expiry_string, sizeof(expiry_string), agnss_expiry.klob_expiry); - mosh_print("Klobuchar: %s", expiry_string); - get_expiry_string(expiry_string, sizeof(expiry_string), agnss_expiry.neq_expiry); - mosh_print("NeQuick: %s", expiry_string); - get_expiry_string(expiry_string, sizeof(expiry_string), agnss_expiry.integrity_expiry); - mosh_print("Integrity: %s", expiry_string); - get_expiry_string(expiry_string, sizeof(expiry_string), agnss_expiry.position_expiry); - mosh_print("Position: %s", expiry_string); - - for (int i = 0; i < agnss_expiry.sv_count; i++) { - system_string = gnss_system_str_get(agnss_expiry.sv[i].system_id); - get_expiry_string(expiry_string, sizeof(expiry_string), - agnss_expiry.sv[i].ephe_expiry); - get_expiry_string(expiry_string2, sizeof(expiry_string2), - agnss_expiry.sv[i].alm_expiry); - - mosh_print("ID %3u (%s): ephe: %-10s alm: %-10s", - agnss_expiry.sv[i].sv_id, system_string, - expiry_string, expiry_string2); - } - - return 0; -} - -int gnss_set_pvt_output_level(uint8_t level) -{ - if (level < 0 || level > 2) { - return -EINVAL; - } - - pvt_output_level = level; - - return 0; -} - -int gnss_set_nmea_output_level(uint8_t level) -{ - if (level < 0 || level > 1) { - return -EINVAL; - } - - nmea_output_level = level; - - return 0; -} - -int gnss_set_event_output_level(uint8_t level) -{ - if (level < 0 || level > 1) { - return -EINVAL; - } - - event_output_level = level; - - return 0; -} diff --git a/applications/modem_shell/src/gnss/gnss.h b/applications/modem_shell/src/gnss/gnss.h deleted file mode 100644 index 5835391..0000000 --- a/applications/modem_shell/src/gnss/gnss.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOSH_GNSS_H -#define MOSH_GNSS_H - -#include - -enum gnss_duty_cycling_policy { - GNSS_DUTY_CYCLING_DISABLED, - GNSS_DUTY_CYCLING_PERFORMANCE, - GNSS_DUTY_CYCLING_POWER -}; - -enum gnss_data_delete { - GNSS_DATA_DELETE_EPHEMERIDES, - GNSS_DATA_DELETE_EKF, - GNSS_DATA_DELETE_ALL, - GNSS_DATA_DELETE_TCXO -}; - -enum gnss_dynamics_mode { - GNSS_DYNAMICS_MODE_GENERAL, - GNSS_DYNAMICS_MODE_STATIONARY, - GNSS_DYNAMICS_MODE_PEDESTRIAN, - GNSS_DYNAMICS_MODE_AUTOMOTIVE -}; - -enum gnss_timing_source { - GNSS_TIMING_SOURCE_RTC, - GNSS_TIMING_SOURCE_TCXO -}; - -enum gnss_qzss_nmea_mode { - /** Standard NMEA PRN reporting. */ - GNSS_QZSS_NMEA_MODE_STANDARD, - /** Custom NMEA PRN reporting (PRN IDs 193...202 used for QZSS satellites). */ - GNSS_QZSS_NMEA_MODE_CUSTOM -}; - -struct gnss_1pps_mode { - /** True if 1PPS is enabled, false if disabled. */ - bool enable; - /** Pulse interval (s) 0...1800s. 0 denotes one-time pulse mode. */ - uint16_t pulse_interval; - /** Pulse width (ms) 1...500ms. */ - uint16_t pulse_width; - /** True if start time is applied, false if not. */ - bool apply_start_time; - /** Gregorian year. */ - uint16_t year; - /** Month of the year. */ - uint8_t month; - /** Day of the month. */ - uint8_t day; - /** Hour of the day. */ - uint8_t hour; - /** Minute of the hour. */ - uint8_t minute; - /** Second of the minute. */ - uint8_t second; -}; - -/** - * @brief Starts GNSS. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_start(void); - -/** - * @brief Stops GNSS. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_stop(void); - -/** - * @brief Deletes GNSS data from NV memory. - * - * @param data Value indicating which data is deleted. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_delete_data(enum gnss_data_delete data); - -/** - * @brief Deletes GNSS data from NV memory using custom bitmask. - * - * @param mask Bitmask indicating which is deleted. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_delete_data_custom(uint32_t mask); - -/** - * @brief Sets continuous tracking mode. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_continuous_mode(void); - -/** - * @brief Sets single fix mode. - * - * @param fix_retry Fix retry period (in seconds). Indicates how long - * GNSS tries to get a fix before giving up. Value 0 - * denotes unlimited retry period. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_single_fix_mode(uint16_t fix_retry); - -/** - * @brief Sets periodic fix mode controlled by application. - * - * @param fix_interval Delay between fixes (in seconds). - * @param fix_retry Fix retry period (in seconds). Indicates how long - * GNSS tries to get a fix before giving up. Value 0 - * denotes unlimited retry period. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_periodic_fix_mode(uint32_t fix_interval, uint16_t fix_retry); - -/** - * @brief Sets periodic fix mode controlled by GNSS. - * - * @param fix_interval Delay between fixes (in seconds). Allowed values are - * 10...1800. - * @param fix_retry Fix retry period (in seconds). Indicates how long - * GNSS tries to get a fix before giving up. Value 0 - * denotes unlimited retry period. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_periodic_fix_mode_gnss(uint16_t fix_interval, uint16_t fix_retry); - -/** - * @brief Sets the system mask. - * - * Bit 0: GPS - * Bit 1: reserved - * Bit 2: QZSS - * Bit 3..7: reserved - * - * @param system_mask System bitmask. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_system_mask(uint8_t system_mask); - -/** - * @brief Sets duty cycling policy for continuous tracking mode. - * - * Duty cycled tracking saves power by operating the GNSS receiver in on/off - * cycles. Two different duty cycling modes are supported, one which saves - * power without significant performance degradation and one which saves even - * more power with an acceptable performance degradation. - * - * @param policy Duty cycling policy value. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_duty_cycling_policy(enum gnss_duty_cycling_policy policy); - -/** - * @brief Sets satellite elevation threshold angle. - * - * Satellites with elevation angle less than the threshold are excluded from - * the PVT estimation. - * - * @param elevation Satellite elevation in degrees. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_elevation_threshold(uint8_t elevation); - -/** - * @brief Enables/disabled A-GNSS filtered ephemerides. - * - * When enabled, the nRF Cloud A-GNSS service will be requested to reduce - * the set of ephemerides returned to only include those satellites which - * are at or above the most recently set elevation threshold angle. - * - * @param enable True to enable, false to disable. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_agnss_filtered_ephemerides(bool enable); - -/** - * @brief Sets the GNSS use case configuration. - * - * @param low_accuracy_enabled True if low accuracy fixes are allowed, false if not. - * @param scheduled_downloads_disabled True if scheduled downloads are disabled, false if not. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_use_case(bool low_accuracy_enabled, bool scheduled_downloads_disabled); - -/** - * @brief Sets the NMEA mask. - * - * Bit 0: GGA - * Bit 1: GLL - * Bit 2: GSA - * Bit 3: GSV - * Bit 4: RMC - * Bit 5..15: reserved - * - * @param nmea_mask NMEA bitmask. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_nmea_mask(uint16_t nmea_mask); - -/** - * @brief Enables/disables priority time window requests. - * - * When priority time windows are enabled, GNSS requests longer RF time windows - * from the modem. This may interfere with LTE operations. - * - * Once a single valid PVT estimate has been produced, priority time window - * requests are automatically disabled. - * - * @param value True to enable priority time windows, false the disable. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_priority_time_windows(bool value); - -/** - * @brief Sets the dynamics mode. - * - * @param mode Dynamics mode. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_dynamics_mode(enum gnss_dynamics_mode mode); - -/** - * @brief Sets the QZSS NMEA mode. In standard NMEA mode QZSS satellites are not reported. - * In custom NMEA mode QZSS satellites are reported using PRN IDs 193...202. - * - * @param nmea_mode QZSS NMEA mode. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_qzss_nmea_mode(enum gnss_qzss_nmea_mode nmea_mode); - -/** - * @brief Sets the QZSS PRN mask. - * - * @param mask Bits 0 to 9 when set correspond to PRNs 193...202 being enabled. - * Bits 10...15 are reserved. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_qzss_mask(uint16_t mask); - -/** - * @brief Sets the 1PPS mode configuration. - * - * @param config 1PPS mode configuration. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_1pps_mode(const struct gnss_1pps_mode *config); - -/** - * @brief Sets the timing source during sleep. - * - * @param source Timing source. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_timing_source(enum gnss_timing_source source); - -/** - * @brief Sets which A-GNSS data is allowed to be injected to the modem (either - * automatically or manually). By default all types are enabled. - * - * @param ephe True if ephemerides are enabled, false if not. - * @param alm True if almanacs are enabled, false if not. - * @param utc True if UTC assistance is enabled, false if not. - * @param klob True if Klobuchar is enabled, false if not. - * @param neq True if NeQuick is enabled, false if not. - * @param time True if system time is enabled, false if not. - * @param pos True if position is enabled, false if not. - * @param integrity True if integrity data is enabled, false if not. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_agnss_data_enabled(bool ephe, bool alm, bool utc, bool klob, - bool neq, bool time, bool pos, bool integrity); - -/** - * @brief Sets whether A-GNSS data is automatically fetched whenever requested - * by GNSS. - * - * @param value True if A-GNSS data is fetched automatically, false if not. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_agnss_automatic(bool value); - -/** - * @brief Fetches and injects A-GNSS data to GNSS. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_inject_agnss_data(void); - -/** - * @brief Enables P-GPS. Once enabled, P-GPS remains enabled until reboot. - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_enable_pgps(void); - -/** - * @brief Queries A-GNSS data expiry information from GNSS. - * - * @return 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_get_agnss_expiry(void); - -/** - * @brief Configures how much PVT information is printed out. - * - * @param level 0 = PVT output disabled - * 1 = fix information enabled - * 2 = fix and SV information enabled - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_pvt_output_level(uint8_t level); - -/** - * @brief Configures whether NMEA strings are printed out. - * - * @param level 0 = NMEA output disabled - * 1 = NMEA output enabled - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_nmea_output_level(uint8_t level); - -/** - * @brief Configures whether GNSS API event information is printed out. - * - * @param level 0 = event output disabled - * 1 = event output enabled - * - * @retval 0 if the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int gnss_set_event_output_level(uint8_t level); - -#endif /* MOSH_GNSS_H */ diff --git a/applications/modem_shell/src/gnss/gnss_shell.c b/applications/modem_shell/src/gnss/gnss_shell.c deleted file mode 100644 index 77e6a8c..0000000 --- a/applications/modem_shell/src/gnss/gnss_shell.c +++ /dev/null @@ -1,889 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include - -#include "mosh_print.h" -#include "gnss.h" - -#define AGNSS_CMD_LINE_INJECT_MAX_LENGTH MIN(NRF_CLOUD_AGNSS_MAX_DATA_SIZE, \ - CONFIG_SHELL_CMD_BUFF_SIZE) - -static int cmd_gnss_start(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_start() == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_stop(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_stop() == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_delete_ephe(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_delete_data(GNSS_DATA_DELETE_EPHEMERIDES) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_delete_ekf(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_delete_data(GNSS_DATA_DELETE_EKF) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_delete_all(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_delete_data(GNSS_DATA_DELETE_ALL) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_delete_tcxo(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_delete_data(GNSS_DATA_DELETE_TCXO) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_delete_mask(const struct shell *shell, size_t argc, char **argv) -{ - int err = 0; - uint32_t mask; - - mask = shell_strtoul(argv[1], 16, &err); - - if (err) { - mosh_error("mask: invalid mask value %s", argv[1]); - - return -ENOEXEC; - } - - return gnss_delete_data_custom(mask) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_mode_cont(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_continuous_mode() == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_mode_single(const struct shell *shell, size_t argc, char **argv) -{ - int timeout; - - timeout = atoi(argv[1]); - if (timeout < 0 || timeout > UINT16_MAX) { - mosh_error("single: invalid timeout value %d", timeout); - return -EINVAL; - } - - return gnss_set_single_fix_mode(timeout) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_mode_periodic(const struct shell *shell, size_t argc, char **argv) -{ - int interval; - int timeout; - - interval = atoi(argv[1]); - if (interval <= 0) { - mosh_error( - "periodic: invalid interval value %d, the value must be greater than 0", - interval); - return -EINVAL; - } - - timeout = atoi(argv[2]); - if (timeout < 0 || timeout > UINT16_MAX) { - mosh_error( - "periodic: invalid timeout value %d, the value must be 0...65535", - timeout); - return -EINVAL; - } - - return gnss_set_periodic_fix_mode(interval, timeout) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_mode_periodic_gnss(const struct shell *shell, size_t argc, char **argv) -{ - int interval; - int timeout; - - interval = atoi(argv[1]); - if (interval < 10 || interval > UINT16_MAX) { - mosh_error( - "periodic_gnss: invalid interval value %d, the value must be 10...65535", - interval); - return -EINVAL; - } - - timeout = atoi(argv[2]); - if (timeout < 0 || timeout > UINT16_MAX) { - mosh_error( - "periodic_gnss: invalid timeout value %d, the value must be 0...65535", - timeout); - return -EINVAL; - } - - return gnss_set_periodic_fix_mode_gnss(interval, timeout) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_dynamics_general(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_dynamics_mode(GNSS_DYNAMICS_MODE_GENERAL) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_dynamics_stationary(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_dynamics_mode(GNSS_DYNAMICS_MODE_STATIONARY) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_dynamics_pedestrian(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_dynamics_mode(GNSS_DYNAMICS_MODE_PEDESTRIAN) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_dynamics_automotive(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_dynamics_mode(GNSS_DYNAMICS_MODE_AUTOMOTIVE) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_system(const struct shell *shell, size_t argc, char **argv) -{ - int value; - uint8_t system_mask; - - system_mask = 0x1; /* GPS bit always enabled */ - - /* QZSS */ - value = atoi(argv[1]); - if (value == 1) { - system_mask |= 0x4; - } - - return gnss_set_system_mask(system_mask) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_elevation(const struct shell *shell, size_t argc, char **argv) -{ - int elevation; - - if (argc != 2) { - mosh_error("elevation: wrong parameter count"); - mosh_print("elevation: "); - mosh_print( - "angle:\tElevation threshold angle (in degrees, default 5). " - "Satellites with elevation angle less than the threshold are excluded."); - return -EINVAL; - } - - elevation = atoi(argv[1]); - - if (elevation < 0 || elevation > UINT8_MAX) { - mosh_error("elevation: invalid elevation value %d", elevation); - return -EINVAL; - } - - return gnss_set_elevation_threshold(elevation) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_use_case(const struct shell *shell, size_t argc, char **argv) -{ - uint8_t value; - bool low_accuracy_enabled = false; - bool scheduled_downloads_disabled = false; - - value = atoi(argv[1]); - if (value == 1) { - low_accuracy_enabled = true; - } - - value = atoi(argv[2]); - if (value == 1) { - scheduled_downloads_disabled = true; - } - - return gnss_set_use_case(low_accuracy_enabled, scheduled_downloads_disabled) == 0 ? - 0 : -ENOEXEC; -} - -static int cmd_gnss_config_nmea(const struct shell *shell, size_t argc, char **argv) -{ - uint8_t value; - uint16_t nmea_mask; - uint16_t nmea_mask_bit; - - nmea_mask = 0; - nmea_mask_bit = 1; - for (int i = 0; i < 5; i++) { - value = atoi(argv[i + 1]); - if (value == 1) { - nmea_mask |= nmea_mask_bit; - } - nmea_mask_bit = nmea_mask_bit << 1; - } - - return gnss_set_nmea_mask(nmea_mask) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_powersave_off(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_duty_cycling_policy(GNSS_DUTY_CYCLING_DISABLED) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_powersave_perf(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_duty_cycling_policy(GNSS_DUTY_CYCLING_PERFORMANCE) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_powersave_power(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_duty_cycling_policy(GNSS_DUTY_CYCLING_POWER) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_qzss_nmea_standard(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_qzss_nmea_mode(GNSS_QZSS_NMEA_MODE_STANDARD) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_qzss_nmea_custom(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_qzss_nmea_mode(GNSS_QZSS_NMEA_MODE_CUSTOM) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_qzss_mask(const struct shell *shell, size_t argc, char **argv) -{ - int value; - uint16_t qzss_mask; - uint16_t qzss_mask_bit; - - qzss_mask = 0; - qzss_mask_bit = 1; - for (int i = 0; i < 10; i++) { - value = atoi(argv[i + 1]); - if (value == 1) { - qzss_mask |= qzss_mask_bit; - } - qzss_mask_bit = qzss_mask_bit << 1; - } - - return gnss_set_qzss_mask(qzss_mask) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_timing_rtc(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_timing_source(GNSS_TIMING_SOURCE_RTC) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_config_timing_tcxo(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_timing_source(GNSS_TIMING_SOURCE_TCXO) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_priority_enable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_priority_time_windows(true) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_priority_disable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_priority_time_windows(false) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_automatic_enable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_agnss_automatic(true) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_automatic_disable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_agnss_automatic(false) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_filtered_enable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_agnss_filtered_ephemerides(true) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_filtered_disable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_set_agnss_filtered_ephemerides(false) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_inject(const struct shell *shell, size_t argc, char **argv) -{ - int ret = 0; - - if (argc == 1) { - /* Fetch assistance data from nRF cloud or from SUPL server and inject */ - if (gnss_inject_agnss_data() != 0) { - ret = -ENOEXEC; - } - } else if (argc == 2) { - /* Assistance data provided as command line argument */ -#if defined(CONFIG_NRF_CLOUD_AGNSS) - size_t bin_array_length = 0; - - if (strlen(argv[1]) <= AGNSS_CMD_LINE_INJECT_MAX_LENGTH) { - char *buf = k_malloc(sizeof(char) * AGNSS_CMD_LINE_INJECT_MAX_LENGTH); - - if (buf == NULL) { - mosh_error("Cannot allocate memory for the assistance data"); - return -ENOEXEC; - } - bin_array_length = hex2bin(argv[1], - strlen(argv[1]), - buf, - AGNSS_CMD_LINE_INJECT_MAX_LENGTH); - - if (bin_array_length) { - mosh_print("Injecting %d bytes", bin_array_length); - if (nrf_cloud_agnss_process(buf, bin_array_length) != 0) { - ret = -EINVAL; - } - } else { - mosh_error("Assistance data not in valid hexadecimal format"); - ret = -EINVAL; - } - k_free(buf); - } else { - mosh_error("Assistance data length %d exceeds the maximum length of %d", - strlen(argv[1]), - AGNSS_CMD_LINE_INJECT_MAX_LENGTH); - ret = -EINVAL; - } -#else - mosh_error("GNSS: Enable CONFIG_NRF_CLOUD_AGNSS to enable the processing of " - "A-GNSS data"); - ret = -ENOEXEC; -#endif - } - return ret; -} - -static int cmd_gnss_agnss_expiry(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_get_agnss_expiry() == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_ref_altitude(const struct shell *shell, size_t argc, char **argv) -{ - int altitude = 0; - struct nrf_modem_gnss_agnss_data_location location = { 0 }; - - if (argc != 2) { - mosh_error("ref_altitude: wrong parameter count"); - mosh_print("ref_altitude: "); - mosh_print( - "altitude:\tReference altitude [m] with regard to the reference ellipsoid " - "surface"); - return -EINVAL; - } - - altitude = atoi(argv[1]); - - if (altitude < INT16_MIN || altitude > INT16_MAX) { - mosh_error("ref_altitude: invalid altitude value %d", altitude); - return -EINVAL; - } - - /* Only inject altitude, thus set unc_semimajor and unc_semiminor to 255 which indicates - * that latitude and longitude are not to be used. Set confidence to 100 for maximum - * confidence. - */ - location.unc_semimajor = 255; - location.unc_semiminor = 255; - location.confidence = 100; - location.altitude = altitude; - /* The altitude uncertainty has to be less than 100 meters (coded number K has to - * be less than 48) for the altitude to be used for a 3-sat fix. GNSS increases - * the uncertainty depending on the age of the altitude and whether the device is - * stationary or moving. The uncertainty is set to 0 (meaning 0 meters), so that - * it remains usable for a 3-sat fix for as long as possible. - */ - location.unc_altitude = 0; - - return nrf_modem_gnss_agnss_write( - &location, - sizeof(location), - NRF_MODEM_GNSS_AGNSS_LOCATION) == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_pgps_enable(const struct shell *shell, size_t argc, char **argv) -{ - return gnss_enable_pgps() == 0 ? 0 : -ENOEXEC; -} - -static int cmd_gnss_agnss_filter(const struct shell *shell, size_t argc, char **argv) -{ - bool ephe_enabled; - bool alm_enabled; - bool utc_enabled; - bool klob_enabled; - bool neq_enabled; - bool time_enabled; - bool pos_enabled; - bool int_enabled; - - if (argc != 9) { - mosh_error("filter: wrong parameter count"); - mosh_print("filter: