├── .editorconfig ├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json └── tasks.json ├── LICENSE ├── Makefile ├── README.md ├── cfg ├── STM32L072CZEx_FLASH.ld └── stm32l0xx_hal_conf.h ├── lib ├── LoRaWAN │ └── Utilities │ │ ├── systime.c │ │ ├── systime.h │ │ ├── timeServer.c │ │ ├── timeServer.h │ │ ├── timer.h │ │ ├── utilities.c │ │ └── utilities.h ├── rtt │ ├── segger_rtt.c │ ├── segger_rtt.h │ └── segger_rtt_conf.h └── stm │ ├── STM32L0xx_HAL_Driver │ ├── Inc │ │ ├── Legacy │ │ │ └── stm32_hal_legacy.h │ │ ├── stm32_assert_template.h │ │ ├── stm32l0xx_hal.h │ │ ├── stm32l0xx_hal_adc.h │ │ ├── stm32l0xx_hal_adc_ex.h │ │ ├── stm32l0xx_hal_comp.h │ │ ├── stm32l0xx_hal_comp_ex.h │ │ ├── stm32l0xx_hal_conf_template.h │ │ ├── stm32l0xx_hal_cortex.h │ │ ├── stm32l0xx_hal_crc.h │ │ ├── stm32l0xx_hal_crc_ex.h │ │ ├── stm32l0xx_hal_cryp.h │ │ ├── stm32l0xx_hal_cryp_ex.h │ │ ├── stm32l0xx_hal_dac.h │ │ ├── stm32l0xx_hal_dac_ex.h │ │ ├── stm32l0xx_hal_def.h │ │ ├── stm32l0xx_hal_dma.h │ │ ├── stm32l0xx_hal_firewall.h │ │ ├── stm32l0xx_hal_flash.h │ │ ├── stm32l0xx_hal_flash_ex.h │ │ ├── stm32l0xx_hal_flash_ramfunc.h │ │ ├── stm32l0xx_hal_gpio.h │ │ ├── stm32l0xx_hal_gpio_ex.h │ │ ├── stm32l0xx_hal_i2c.h │ │ ├── stm32l0xx_hal_i2c_ex.h │ │ ├── stm32l0xx_hal_i2s.h │ │ ├── stm32l0xx_hal_irda.h │ │ ├── stm32l0xx_hal_irda_ex.h │ │ ├── stm32l0xx_hal_iwdg.h │ │ ├── stm32l0xx_hal_lcd.h │ │ ├── stm32l0xx_hal_lptim.h │ │ ├── stm32l0xx_hal_lptim_ex.h │ │ ├── stm32l0xx_hal_pcd.h │ │ ├── stm32l0xx_hal_pcd_ex.h │ │ ├── stm32l0xx_hal_pwr.h │ │ ├── stm32l0xx_hal_pwr_ex.h │ │ ├── stm32l0xx_hal_rcc.h │ │ ├── stm32l0xx_hal_rcc_ex.h │ │ ├── stm32l0xx_hal_rng.h │ │ ├── stm32l0xx_hal_rtc.h │ │ ├── stm32l0xx_hal_rtc_ex.h │ │ ├── stm32l0xx_hal_smartcard.h │ │ ├── stm32l0xx_hal_smartcard_ex.h │ │ ├── stm32l0xx_hal_smbus.h │ │ ├── stm32l0xx_hal_spi.h │ │ ├── stm32l0xx_hal_tim.h │ │ ├── stm32l0xx_hal_tim_ex.h │ │ ├── stm32l0xx_hal_tsc.h │ │ ├── stm32l0xx_hal_uart.h │ │ ├── stm32l0xx_hal_uart_ex.h │ │ ├── stm32l0xx_hal_usart.h │ │ ├── stm32l0xx_hal_usart_ex.h │ │ ├── stm32l0xx_hal_wwdg.h │ │ ├── stm32l0xx_ll_adc.h │ │ ├── stm32l0xx_ll_bus.h │ │ ├── stm32l0xx_ll_comp.h │ │ ├── stm32l0xx_ll_cortex.h │ │ ├── stm32l0xx_ll_crc.h │ │ ├── stm32l0xx_ll_crs.h │ │ ├── stm32l0xx_ll_dac.h │ │ ├── stm32l0xx_ll_dma.h │ │ ├── stm32l0xx_ll_exti.h │ │ ├── stm32l0xx_ll_gpio.h │ │ ├── stm32l0xx_ll_i2c.h │ │ ├── stm32l0xx_ll_iwdg.h │ │ ├── stm32l0xx_ll_lptim.h │ │ ├── stm32l0xx_ll_lpuart.h │ │ ├── stm32l0xx_ll_pwr.h │ │ ├── stm32l0xx_ll_rcc.h │ │ ├── stm32l0xx_ll_rng.h │ │ ├── stm32l0xx_ll_rtc.h │ │ ├── stm32l0xx_ll_spi.h │ │ ├── stm32l0xx_ll_system.h │ │ ├── stm32l0xx_ll_tim.h │ │ ├── stm32l0xx_ll_usart.h │ │ ├── stm32l0xx_ll_usb.h │ │ ├── stm32l0xx_ll_utils.h │ │ └── stm32l0xx_ll_wwdg.h │ └── Src │ │ ├── stm32l0xx_hal.c │ │ ├── stm32l0xx_hal_adc.c │ │ ├── stm32l0xx_hal_adc_ex.c │ │ ├── stm32l0xx_hal_comp.c │ │ ├── stm32l0xx_hal_comp_ex.c │ │ ├── stm32l0xx_hal_cortex.c │ │ ├── stm32l0xx_hal_crc.c │ │ ├── stm32l0xx_hal_crc_ex.c │ │ ├── stm32l0xx_hal_cryp.c │ │ ├── stm32l0xx_hal_cryp_ex.c │ │ ├── stm32l0xx_hal_dac.c │ │ ├── stm32l0xx_hal_dac_ex.c │ │ ├── stm32l0xx_hal_dma.c │ │ ├── stm32l0xx_hal_firewall.c │ │ ├── stm32l0xx_hal_flash.c │ │ ├── stm32l0xx_hal_flash_ex.c │ │ ├── stm32l0xx_hal_flash_ramfunc.c │ │ ├── stm32l0xx_hal_gpio.c │ │ ├── stm32l0xx_hal_i2c.c │ │ ├── stm32l0xx_hal_i2c_ex.c │ │ ├── stm32l0xx_hal_i2s.c │ │ ├── stm32l0xx_hal_irda.c │ │ ├── stm32l0xx_hal_iwdg.c │ │ ├── stm32l0xx_hal_lcd.c │ │ ├── stm32l0xx_hal_lptim.c │ │ ├── stm32l0xx_hal_msp_template.c │ │ ├── stm32l0xx_hal_pcd.c │ │ ├── stm32l0xx_hal_pcd_ex.c │ │ ├── stm32l0xx_hal_pwr.c │ │ ├── stm32l0xx_hal_pwr_ex.c │ │ ├── stm32l0xx_hal_rcc.c │ │ ├── stm32l0xx_hal_rcc_ex.c │ │ ├── stm32l0xx_hal_rng.c │ │ ├── stm32l0xx_hal_rtc.c │ │ ├── stm32l0xx_hal_rtc_ex.c │ │ ├── stm32l0xx_hal_smartcard.c │ │ ├── stm32l0xx_hal_smartcard_ex.c │ │ ├── stm32l0xx_hal_smbus.c │ │ ├── stm32l0xx_hal_spi.c │ │ ├── stm32l0xx_hal_tim.c │ │ ├── stm32l0xx_hal_tim_ex.c │ │ ├── stm32l0xx_hal_tsc.c │ │ ├── stm32l0xx_hal_uart.c │ │ ├── stm32l0xx_hal_uart_ex.c │ │ ├── stm32l0xx_hal_usart.c │ │ ├── stm32l0xx_hal_wwdg.c │ │ ├── stm32l0xx_ll_adc.c │ │ ├── stm32l0xx_ll_comp.c │ │ ├── stm32l0xx_ll_crc.c │ │ ├── stm32l0xx_ll_crs.c │ │ ├── stm32l0xx_ll_dac.c │ │ ├── stm32l0xx_ll_dma.c │ │ ├── stm32l0xx_ll_exti.c │ │ ├── stm32l0xx_ll_gpio.c │ │ ├── stm32l0xx_ll_i2c.c │ │ ├── stm32l0xx_ll_lptim.c │ │ ├── stm32l0xx_ll_lpuart.c │ │ ├── stm32l0xx_ll_pwr.c │ │ ├── stm32l0xx_ll_rcc.c │ │ ├── stm32l0xx_ll_rng.c │ │ ├── stm32l0xx_ll_rtc.c │ │ ├── stm32l0xx_ll_spi.c │ │ ├── stm32l0xx_ll_tim.c │ │ ├── stm32l0xx_ll_usart.c │ │ ├── stm32l0xx_ll_usb.c │ │ └── stm32l0xx_ll_utils.c │ ├── include │ ├── cmsis_compiler.h │ ├── cmsis_gcc.h │ ├── cmsis_version.h │ ├── core_cm0plus.h │ ├── mpu_armv7.h │ ├── stm32l072xx.h │ ├── stm32l0xx.h │ └── system_stm32l0xx.h │ └── src │ ├── startup_stm32l072xx.s │ └── system_stm32l0xx.c ├── python ├── .gitignore ├── LICENSE ├── README.md ├── lora.py └── pyproject.toml ├── src ├── adc.c ├── adc.h ├── atci.c ├── atci.h ├── board.c ├── board.h ├── cbuf.c ├── cbuf.h ├── cmd.c ├── cmd.h ├── debug │ ├── log.c │ ├── log.h │ ├── usart.c │ └── usart.h ├── delay.h ├── eeprom.c ├── eeprom.h ├── gpio.c ├── gpio.h ├── halt.c ├── halt.h ├── irq.h ├── lpuart.c ├── lpuart.h ├── lrw.c ├── lrw.h ├── main.c ├── mlm32l0xx_hal_msp.c ├── nvm.c ├── nvm.h ├── part.c ├── part.h ├── radio.c ├── rtc.c ├── rtc.h ├── spi.c ├── spi.h ├── sx1276-board.c ├── sx1276-board.h ├── system.c ├── system.h ├── utils.c └── utils.h └── tools ├── jlink └── flash.jlink ├── ozone ├── ozone.jdebug └── stm32l0x3.svd └── release.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [src/**] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 4 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [Makefile] 14 | indent_style = tab 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | tools/ozone/ozone.jdebug.user 3 | /*.bin 4 | /*.map 5 | /*.hex 6 | /*.tar.gz 7 | /VERSION 8 | /LIB_VERSION 9 | /release 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/loramac-node"] 2 | path = lib/loramac-node 3 | url = https://github.com/janakj/LoRaMac-node 4 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "LoRa Modem (debug)", 5 | "defines": [ 6 | "STM32L072xx", 7 | "HAL_IWDG_MODULE_ENABLED", 8 | "USE_FULL_LL_DRIVER", 9 | "SOFT_SE", 10 | "SECURE_ELEMENT_PRE_PROVISIONED", 11 | "LORAMAC_CLASSB_ENABLED", 12 | "DEBUG", 13 | "VERSION=\"v1.0.2-10-g08e86e66\"", 14 | "BUILD_DATE=\"2022-May-07 16:11:42 EDT\"", 15 | "VERSION_COMPAT=\"1.1.06\"", 16 | "BUILD_DATE_COMPAT=\"Mar 31 2022 12:35:07\"", 17 | "LIB_VERSION=\"v4.6.0-20-g0e4d8127\"", 18 | "LORAMAC_ABP_VERSION=0x01000400", 19 | "ENABLED_REGIONS=\"AS923 AU915 CN470 CN779 EU433 EU868 IN865 KR920 RU864 US915\"", 20 | "DEFAULT_ACTIVE_REGION=\"EU868\"", 21 | "DEFAULT_UART_BAUDRATE=19200", 22 | "FACTORY_RESET_PIN=1", 23 | "RESTORE_CHMASK_AFTER_JOIN=0", 24 | "TCXO_PIN=1", 25 | "DETACHABLE_LPUART=1", 26 | "DEBUG_LOG=1", 27 | "ENABLE_SWD=1", 28 | "DEBUG_MCU=1", 29 | "CERTIFICATION_ATCI=1" 30 | ], 31 | "includePath": [ 32 | "${workspaceFolder}/**", 33 | "${default}" 34 | ], 35 | "cStandard": "c11" 36 | }, 37 | { 38 | "name": "LoRa Modem (release)", 39 | "defines": [ 40 | "STM32L072xx", 41 | "HAL_IWDG_MODULE_ENABLED", 42 | "USE_FULL_LL_DRIVER", 43 | "SOFT_SE", 44 | "SECURE_ELEMENT_PRE_PROVISIONED", 45 | "LORAMAC_CLASSB_ENABLED", 46 | "RELEASE", 47 | "VERSION=\"v1.0.2-10-g08e86e66\"", 48 | "BUILD_DATE=\"2022-May-07 16:11:42 EDT\"", 49 | "VERSION_COMPAT=\"1.1.06\"", 50 | "BUILD_DATE_COMPAT=\"Mar 31 2022 12:35:07\"", 51 | "LIB_VERSION=\"v4.6.0-20-g0e4d8127\"", 52 | "LORAMAC_ABP_VERSION=0x01000400", 53 | "ENABLED_REGIONS=\"AS923 AU915 CN470 CN779 EU433 EU868 IN865 KR920 RU864 US915\"", 54 | "DEFAULT_ACTIVE_REGION=\"EU868\"", 55 | "DEFAULT_UART_BAUDRATE=19200", 56 | "FACTORY_RESET_PIN=1", 57 | "RESTORE_CHMASK_AFTER_JOIN=0", 58 | "TCXO_PIN=1", 59 | "DETACHABLE_LPUART=1", 60 | "DEBUG_LOG=0", 61 | "ENABLE_SWD=0", 62 | "DEBUG_MCU=0", 63 | "CERTIFICATION_ATCI=1" 64 | ], 65 | "includePath": [ 66 | "${workspaceFolder}/**", 67 | "${default}" 68 | ], 69 | "cStandard": "c11" 70 | } 71 | ], 72 | "version": 4 73 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "command": "make", 6 | "type": "shell", 7 | "tasks": [{ 8 | "label": "build", 9 | "args": [], 10 | "group": "build", 11 | "presentation": { 12 | "reveal": "silent", 13 | "panel": "shared" 14 | }, 15 | "problemMatcher": { 16 | "owner": "cpp", 17 | "fileLocation": ["relative", "${workspaceRoot}"], 18 | "pattern": { 19 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", 20 | "file": 1, 21 | "line": 2, 22 | "column": 3, 23 | "severity": 4, 24 | "message": 5 25 | } 26 | } 27 | }, { 28 | "label": "clean", 29 | "args": ["clean"], 30 | "group": "build", 31 | "presentation": { 32 | "reveal": "never", 33 | "panel": "shared", 34 | "showReuseMessage": true, 35 | "clear": false 36 | } 37 | }] 38 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2022 HARDWARIO a.s. 2 | Copyright (c) 2022 Jan Janak 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open LoRaWAN Modem for Murata Type ABZ Module 2 | 3 | This project develops an open-source LoRaWAN modem firmware for the Type ABZ wireless module by Murata. The firmware provides an [AT [command interface](https://github.com/hardwario/lora-modem/wiki/AT-Command-Interface) that is backward and compatible with Murata Modem, Murata's proprietary LoRaWAN firmware. The firmware can be used on all Type ABZ [variants](https://github.com/hardwario/lora-modem/wiki/Type-ABZ-Modules) with an open (user-programmable) microcontroller (also known as OpenMCU). 4 | 5 | ## Main Features 6 | 7 | * Support for [LoRaWAN 1.0.4](https://resources.lora-alliance.org/technical-specifications/ts001-1-0-4-lorawan-l2-1-0-4-specification), [LoRaWAN 1.1](https://resources.lora-alliance.org/technical-specifications/lorawan-specification-v1-1) ([note on compatibility](https://github.com/hardwario/lora-modem/wiki/LoRaWAN-1.1-Compatibility)), and regional parameters [RP2-1.0.3](https://resources.lora-alliance.org/technical-specifications/rp2-1-0-3-lorawan-regional-parameters) 8 | * Based on the most recent version (4.7.0) of [LoRaMac-node](https://github.com/Lora-net/LoRaMac-node) 9 | * Support for multiple regions configurable at runtime 10 | * All persistent LoRaWAN MAC data stored in NVM (EEPROM) 11 | * Very low [power consumption](https://github.com/hardwario/lora-modem/wiki/Power-Consumption) (1.4 uA when idle) 12 | 13 | The project also provides a high-level [Python library and command line tool](./python) for managing Type ABZ LoRa modems. See this [README](./python/README.md) for more information. 14 | 15 | ## Installation 16 | 17 | Binary firmware images for several platforms embedding the Type ABZ module are available from the [Releases](https://github.com/hardwario/lora-modem/releases) page. We generate a pre-configured firmware [variant](https://github.com/hardwario/lora-modem/wiki/Supported-Platforms) for each of the following platforms: 18 | * HARDWARIO [LoRa Module](https://shop.hardwario.com/lora-module/) 19 | * HARDWARIO [Chester](https://www.hardwario.com/chester/) 20 | * Arduino [MKR WAN 1300](https://store-usa.arduino.cc/products/arduino-mkr-wan-1300-lora-connectivity) 21 | * Arduino [MKR WAN 1310](https://store.arduino.cc/products/arduino-mkr-wan-1310) 22 | * ST [B-L072Z-LRWAN1](https://www.st.com/en/evaluation-tools/b-l072z-lrwan1.html) Discovery Kit 23 | 24 | The [STM32 Cube Programmer](https://www.st.com/en/development-tools/stm32cubeprog.html) or the HARDWARIO [firmware flashing tool](https://tower.hardwario.com/en/latest/tools/hardwario-firmware-flashing-tool/) can be used to flash the firmware into the Type ABZ module. Steps to flash the firmware into HARDWARIO Tower LoRa Module are described in the [wiki](https://github.com/hardwario/lora-modem/wiki/LoRa-Module-Firmware-Update). Firmware update tool for the Arduino MKR WAN 1310 can be found [here](https://github.com/disk91/mkr1310_openLoRaModem_fw_update). 25 | 26 | ## Building 27 | 28 | You will need the embedded gcc toolchain for ARM (arm-none-eabi), `git`, and `make` to build your own firmware binary from the source code. First, clone the repository and initialize git submodules: 29 | ```sh 30 | git clone https://github.com/hardwario/lora-modem 31 | cd lora-modem 32 | git submodule update --init 33 | ``` 34 | If you wish to customize the build, edit the variables at the beginning of the Makefile (or override them at the `make` command line). Then run `make` to build the firmware in release mode: 35 | ```sh 36 | make 37 | ``` 38 | If you wish to build a development version with logging and debugging enabled, run `make debug` instead. *Please note that development builds have higher [idle power consumption](https://github.com/hardwario/lora-modem/wiki/Power-Consumption) than release builds.* 39 | 40 | ## Documentation 41 | * [The Things Network (TTN) provisioning](https://github.com/hardwario/lora-modem/wiki/TTN-Provisioning) 42 | * [AT command interface](https://github.com/hardwario/lora-modem/wiki/AT-Command-Interface) 43 | * Other [similar projects](https://github.com/hardwario/lora-modem/wiki/Related-Work) 44 | 45 | Additional documentation and notes can be found in the [wiki](https://github.com/hardwario/lora-modem/wiki). 46 | 47 | ## Contributing 48 | 49 | [Bug reports](https://github.com/hardwario/lora-modem/issues), [improvement suggestions](https://github.com/hardwario/lora-modem/issues), [pull requests](https://github.com/hardwario/lora-modem/pulls), and updates to the [documentation in the wiki](https://github.com/hardwario/lora-modem/wiki) would be greatly appreciated! 50 | 51 | ## License 52 | 53 | The firmware is open source licensed under the terms of the Revised BSD License. It includes the [LoRaMac-node](https://github.com/Lora-net/LoRaMac-node) library licensed under the Revised BSD License and portions of the [STM32CubeL0](https://github.com/STMicroelectronics/STM32CubeL0) MCU firmware package licensed under the Revised BSD License. 54 | 55 | See [LICENSE](LICENSE) for complete details. 56 | -------------------------------------------------------------------------------- /cfg/STM32L072CZEx_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Abstract : Linker script for STM32L072CZEx Device with 8 | ** 192KByte FLASH, 20KByte RAM 9 | ** 10 | ** Set heap size, stack size and stack location according 11 | ** to application requirements. 12 | ** 13 | ** Set memory bank area and size if external memory is used. 14 | ** 15 | ** Target : STMicroelectronics STM32 16 | ** 17 | ** 18 | ** Distribution: The file is distributed as is, without any warranty 19 | ** of any kind. 20 | ** 21 | ** (c)Copyright Ac6. 22 | ** You may use this file as-is or modify it according to the needs of your 23 | ** project. Distribution of this file (unmodified or modified) is not 24 | ** permitted. Ac6 permit registered System Workbench for MCU users the 25 | ** rights to distribute the assembled, compiled & linked contents of this 26 | ** file as part of an application binary file, provided that it is built 27 | ** using the System Workbench for MCU toolchain. 28 | ** 29 | ***************************************************************************** 30 | */ 31 | 32 | /* Entry Point */ 33 | ENTRY(Reset_Handler) 34 | 35 | /* Highest address of the user mode stack */ 36 | _estack = 0x20005000; /* end of RAM */ 37 | /* Generate a link error if heap and stack don't fit into RAM */ 38 | _Min_Heap_Size = 0; /*0x400;*/ /* required amount of heap */ 39 | _Min_Stack_Size = 0x400; /* required amount of stack */ 40 | 41 | /* Specify the memory areas */ 42 | MEMORY 43 | { 44 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K 45 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 192K 46 | } 47 | 48 | /* Define output sections */ 49 | SECTIONS 50 | { 51 | /* The startup code goes first into FLASH */ 52 | .isr_vector : 53 | { 54 | . = ALIGN(4); 55 | KEEP(*(.isr_vector)) /* Startup code */ 56 | . = ALIGN(4); 57 | } >FLASH 58 | 59 | /* The program code and other data goes into FLASH */ 60 | .text : 61 | { 62 | . = ALIGN(4); 63 | *(.text) /* .text sections (code) */ 64 | *(.text*) /* .text* sections (code) */ 65 | *(.glue_7) /* glue arm to thumb code */ 66 | *(.glue_7t) /* glue thumb to arm code */ 67 | *(.eh_frame) 68 | 69 | KEEP (*(.init)) 70 | KEEP (*(.fini)) 71 | 72 | . = ALIGN(4); 73 | _etext = .; /* define a global symbols at end of code */ 74 | } >FLASH 75 | 76 | /* Constant data goes into FLASH */ 77 | .rodata : 78 | { 79 | . = ALIGN(4); 80 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 81 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 82 | . = ALIGN(4); 83 | } >FLASH 84 | 85 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 86 | .ARM : { 87 | __exidx_start = .; 88 | *(.ARM.exidx*) 89 | __exidx_end = .; 90 | } >FLASH 91 | 92 | .preinit_array : 93 | { 94 | PROVIDE_HIDDEN (__preinit_array_start = .); 95 | KEEP (*(.preinit_array*)) 96 | PROVIDE_HIDDEN (__preinit_array_end = .); 97 | } >FLASH 98 | .init_array : 99 | { 100 | PROVIDE_HIDDEN (__init_array_start = .); 101 | KEEP (*(SORT(.init_array.*))) 102 | KEEP (*(.init_array*)) 103 | PROVIDE_HIDDEN (__init_array_end = .); 104 | } >FLASH 105 | .fini_array : 106 | { 107 | PROVIDE_HIDDEN (__fini_array_start = .); 108 | KEEP (*(SORT(.fini_array.*))) 109 | KEEP (*(.fini_array*)) 110 | PROVIDE_HIDDEN (__fini_array_end = .); 111 | } >FLASH 112 | 113 | /* used by the startup to initialize data */ 114 | _sidata = LOADADDR(.data); 115 | 116 | /* Initialized data sections goes into RAM, load LMA copy after code */ 117 | .data : 118 | { 119 | . = ALIGN(4); 120 | _sdata = .; /* create a global symbol at data start */ 121 | *(.data) /* .data sections */ 122 | *(.data*) /* .data* sections */ 123 | 124 | . = ALIGN(4); 125 | _edata = .; /* define a global symbol at data end */ 126 | } >RAM AT> FLASH 127 | 128 | 129 | /* Uninitialized data section */ 130 | . = ALIGN(4); 131 | .bss : 132 | { 133 | /* This is used by the startup in order to initialize the .bss secion */ 134 | _sbss = .; /* define a global symbol at bss start */ 135 | __bss_start__ = _sbss; 136 | *(.bss) 137 | *(.bss*) 138 | *(COMMON) 139 | 140 | . = ALIGN(4); 141 | _ebss = .; /* define a global symbol at bss end */ 142 | __bss_end__ = _ebss; 143 | } >RAM 144 | 145 | /* User_heap_stack section, used to check that there is enough RAM left */ 146 | ._user_heap_stack : 147 | { 148 | . = ALIGN(8); 149 | PROVIDE ( end = . ); 150 | PROVIDE ( _end = . ); 151 | . = . + _Min_Heap_Size; 152 | . = . + _Min_Stack_Size; 153 | . = ALIGN(8); 154 | } >RAM 155 | 156 | 157 | 158 | /* Remove information from the standard libraries */ 159 | /DISCARD/ : 160 | { 161 | libc.a ( * ) 162 | libm.a ( * ) 163 | libgcc.a ( * ) 164 | } 165 | 166 | .ARM.attributes 0 : { *(.ARM.attributes) } 167 | } 168 | 169 | 170 | -------------------------------------------------------------------------------- /lib/LoRaWAN/Utilities/systime.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file systime.h 3 | * 4 | * \brief System time functions implementation. 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2018 Semtech - STMicroelectronics 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | * 23 | * \author MCD Application Team ( STMicroelectronics International ) 24 | */ 25 | #ifndef __SYS_TIME_H__ 26 | #define __SYS_TIME_H__ 27 | 28 | #ifdef __cplusplus 29 | extern "C" 30 | { 31 | #endif 32 | #include 33 | #include "time.h" 34 | 35 | /*! 36 | * \brief Days, Hours, Minutes and seconds of systime.h 37 | */ 38 | #define TM_DAYS_IN_LEAP_YEAR ( ( uint32_t ) 366U ) 39 | #define TM_DAYS_IN_YEAR ( ( uint32_t ) 365U ) 40 | #define TM_SECONDS_IN_1DAY ( ( uint32_t )86400U ) 41 | #define TM_SECONDS_IN_1HOUR ( ( uint32_t ) 3600U ) 42 | #define TM_SECONDS_IN_1MINUTE ( ( uint32_t ) 60U ) 43 | #define TM_MINUTES_IN_1HOUR ( ( uint32_t ) 60U ) 44 | #define TM_HOURS_IN_1DAY ( ( uint32_t ) 24U ) 45 | 46 | 47 | /*! 48 | * \brief Months of systime.h 49 | */ 50 | #define TM_MONTH_JANUARY ( ( uint8_t ) 0U ) 51 | #define TM_MONTH_FEBRUARY ( ( uint8_t ) 1U ) 52 | #define TM_MONTH_MARCH ( ( uint8_t ) 2U ) 53 | #define TM_MONTH_APRIL ( ( uint8_t ) 3U ) 54 | #define TM_MONTH_MAY ( ( uint8_t ) 4U ) 55 | #define TM_MONTH_JUNE ( ( uint8_t ) 5U ) 56 | #define TM_MONTH_JULY ( ( uint8_t ) 6U ) 57 | #define TM_MONTH_AUGUST ( ( uint8_t ) 7U ) 58 | #define TM_MONTH_SEPTEMBER ( ( uint8_t ) 8U ) 59 | #define TM_MONTH_OCTOBER ( ( uint8_t ) 9U ) 60 | #define TM_MONTH_NOVEMBER ( ( uint8_t )10U ) 61 | #define TM_MONTH_DECEMBER ( ( uint8_t )11U ) 62 | 63 | /*! 64 | * \brief Week days of systime.h 65 | */ 66 | #define TM_WEEKDAY_SUNDAY ( ( uint8_t )0U ) 67 | #define TM_WEEKDAY_MONDAY ( ( uint8_t )1U ) 68 | #define TM_WEEKDAY_TUESDAY ( ( uint8_t )2U ) 69 | #define TM_WEEKDAY_WEDNESDAY ( ( uint8_t )3U ) 70 | #define TM_WEEKDAY_THURSDAY ( ( uint8_t )4U ) 71 | #define TM_WEEKDAY_FRIDAY ( ( uint8_t )5U ) 72 | #define TM_WEEKDAY_SATURDAY ( ( uint8_t )6U ) 73 | 74 | /*! 75 | * \brief Number of seconds elapsed between Unix and GPS epoch 76 | */ 77 | #define UNIX_GPS_EPOCH_OFFSET 315964800 78 | 79 | /*! 80 | * \brief Structure holding the system time in seconds and milliseconds. 81 | */ 82 | typedef struct SysTime_s 83 | { 84 | uint32_t Seconds; 85 | int16_t SubSeconds; 86 | }SysTime_t; 87 | 88 | /*! 89 | * \brief Adds 2 SysTime_t values 90 | * 91 | * \param a Value 92 | * \param b Value to added 93 | * 94 | * \retval result Addition result (SysTime_t value) 95 | */ 96 | SysTime_t SysTimeAdd( SysTime_t a, SysTime_t b ); 97 | 98 | /*! 99 | * \brief Subtracts 2 SysTime_t values 100 | * 101 | * \param a Value 102 | * \param b Value to be subtracted 103 | * 104 | * \retval result Subtraction result (SysTime_t value) 105 | */ 106 | SysTime_t SysTimeSub( SysTime_t a, SysTime_t b ); 107 | 108 | /*! 109 | * \brief Sets new system time 110 | * 111 | * \param sysTime New seconds/sub-seconds since UNIX epoch origin 112 | */ 113 | void SysTimeSet( SysTime_t sysTime ); 114 | 115 | /*! 116 | * \brief Gets current system time 117 | * 118 | * \retval sysTime Current seconds/sub-seconds since UNIX epoch origin 119 | */ 120 | SysTime_t SysTimeGet( void ); 121 | 122 | /*! 123 | * \brief Gets current MCU system time 124 | * 125 | * \retval sysTime Current seconds/sub-seconds since Mcu started 126 | */ 127 | SysTime_t SysTimeGetMcuTime( void ); 128 | 129 | /*! 130 | * Converts the given SysTime to the equivalent RTC value in milliseconds 131 | * 132 | * \param [IN] sysTime System time to be converted 133 | * 134 | * \retval timeMs The RTC converted time value in ms 135 | */ 136 | uint32_t SysTimeToMs( SysTime_t sysTime ); 137 | 138 | /*! 139 | * Converts the given RTC value in milliseconds to the equivalent SysTime 140 | * 141 | * \param [IN] timeMs The RTC time value in ms to be converted 142 | * 143 | * \retval sysTime Converted system time 144 | */ 145 | SysTime_t SysTimeFromMs( uint32_t timeMs ); 146 | 147 | /*! 148 | * \brief Convert a calendar time into time since UNIX epoch as a uint32_t. 149 | * 150 | * \param [IN] localtime Pointer to the object containing the calendar time 151 | * \retval timestamp The calendar time as seconds since UNIX epoch. 152 | */ 153 | uint32_t SysTimeMkTime( const struct tm* localtime ); 154 | 155 | /*! 156 | * \brief Converts a given time in seconds since UNIX epoch into calendar time. 157 | * 158 | * \param [IN] timestamp The time since UNIX epoch to convert into calendar time. 159 | * \param [OUT] localtime Pointer to the calendar time object which will contain 160 | the result of the conversion. 161 | */ 162 | void SysTimeLocalTime( const uint32_t timestamp, struct tm *localtime ); 163 | 164 | #ifdef __cplusplus 165 | } 166 | #endif 167 | 168 | #endif // __SYS_TIME_H__ 169 | -------------------------------------------------------------------------------- /lib/LoRaWAN/Utilities/timeServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Timer objects and scheduling management 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | /****************************************************************************** 16 | * @file timeServer.h 17 | * @author MCD Application Team 18 | * @brief is the timer server driver 19 | ****************************************************************************** 20 | * @attention 21 | * 22 | *

© Copyright (c) 2018 STMicroelectronics. 23 | * All rights reserved.

24 | * 25 | * This software component is licensed by ST under Ultimate Liberty license 26 | * SLA0044, the "License"; You may not use this file except in compliance with 27 | * the License. You may obtain a copy of the License at: 28 | * www.st.com/SLA0044 29 | * 30 | ****************************************************************************** 31 | */ 32 | 33 | /* Define to prevent recursive inclusion -------------------------------------*/ 34 | #ifndef __TIMESERVER_H__ 35 | #define __TIMESERVER_H__ 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | /* Includes ------------------------------------------------------------------*/ 42 | #include 43 | #include "utilities.h" 44 | 45 | 46 | /* Exported types ------------------------------------------------------------*/ 47 | 48 | /*! 49 | * \brief Timer object description 50 | */ 51 | typedef struct TimerEvent_s 52 | { 53 | uint32_t Timestamp; //! Expiring timer value in ticks from TimerContext 54 | uint32_t ReloadValue; //! Reload Value when Timer is restarted 55 | bool IsStarted; //! Is the timer currently running 56 | bool IsNext2Expire; //! Is the next timer to expire 57 | void ( *Callback )( void* context ); //! Timer IRQ callback function 58 | void *Context; //! User defined data object pointer to pass back 59 | struct TimerEvent_s *Next; //! Pointer to the next Timer object. 60 | }TimerEvent_t; 61 | 62 | 63 | /* Exported constants --------------------------------------------------------*/ 64 | /* External variables --------------------------------------------------------*/ 65 | /* Exported macros -----------------------------------------------------------*/ 66 | /* Exported functions ------------------------------------------------------- */ 67 | 68 | /*! 69 | * \brief Initializes the timer object 70 | * 71 | * \remark TimerSetValue function must be called before starting the timer. 72 | * this function initializes timestamp and reload value at 0. 73 | * 74 | * \param [IN] obj Structure containing the timer object parameters 75 | * \param [IN] callback Function callback called at the end of the timeout 76 | */ 77 | void TimerInit( TimerEvent_t *obj, void ( *callback )( void *context ) ); 78 | 79 | /*! 80 | * \brief Sets a user defined object pointer 81 | * 82 | * \param [IN] context User defined data object pointer to pass back 83 | * on IRQ handler callback 84 | */ 85 | void TimerSetContext( TimerEvent_t *obj, void* context ); 86 | 87 | /*! 88 | * \brief Timer IRQ event handler 89 | * 90 | * \note Head Timer Object is automaitcally removed from the List 91 | * 92 | * \note e.g. it is snot needded to stop it 93 | */ 94 | void TimerIrqHandler( void ); 95 | 96 | /*! 97 | * \brief Starts and adds the timer object to the list of timer events 98 | * 99 | * \param [IN] obj Structure containing the timer object parameters 100 | */ 101 | void TimerStart( TimerEvent_t *obj ); 102 | 103 | /*! 104 | * \brief Checks if the provided timer is running 105 | * 106 | * \param [IN] obj Structure containing the timer object parameters 107 | * 108 | * \retval status returns the timer activity status [true: Started, 109 | * false: Stopped] 110 | */ 111 | bool TimerIsStarted( TimerEvent_t *obj ); 112 | 113 | /*! 114 | * \brief Stops and removes the timer object from the list of timer events 115 | * 116 | * \param [IN] obj Structure containing the timer object parameters 117 | */ 118 | void TimerStop( TimerEvent_t *obj ); 119 | 120 | /*! 121 | * \brief Resets the timer object 122 | * 123 | * \param [IN] obj Structure containing the timer object parameters 124 | */ 125 | void TimerReset( TimerEvent_t *obj ); 126 | 127 | /*! 128 | * \brief Set timer new timeout value 129 | * 130 | * \param [IN] obj Structure containing the timer object parameters 131 | * \param [IN] value New timer timeout value 132 | */ 133 | void TimerSetValue( TimerEvent_t *obj, uint32_t value ); 134 | 135 | /*! 136 | * \brief Read the current time 137 | * 138 | * \retval returns current time in ms 139 | */ 140 | TimerTime_t TimerGetCurrentTime( void ); 141 | 142 | /*! 143 | * \brief Return the Time elapsed since a fix moment in Time 144 | * 145 | * \param [IN] savedTime fix moment in Time 146 | * \retval time returns elapsed time in ms 147 | */ 148 | TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); 149 | 150 | /*! 151 | * \brief Computes the temperature compensation for a period of time on a 152 | * specific temperature. 153 | * 154 | * \param [IN] period Time period to compensate 155 | * \param [IN] temperature Current temperature 156 | * 157 | * \retval Compensated time period 158 | */ 159 | TimerTime_t TimerTempCompensation( TimerTime_t period, float temperature ); 160 | 161 | #ifdef __cplusplus 162 | } 163 | #endif 164 | 165 | #endif /* __TIMESERVER_H__*/ 166 | 167 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 168 | -------------------------------------------------------------------------------- /lib/LoRaWAN/Utilities/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Timer objects and scheduling management 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | /****************************************************************************** 16 | * @file timer.h 17 | * @author MCD Application Team 18 | * @brief wrapper to timer server 19 | ****************************************************************************** 20 | * @attention 21 | * 22 | *

© Copyright (c) 2018 STMicroelectronics. 23 | * All rights reserved.

24 | * 25 | * This software component is licensed by ST under Ultimate Liberty license 26 | * SLA0044, the "License"; You may not use this file except in compliance with 27 | * the License. You may obtain a copy of the License at: 28 | * www.st.com/SLA0044 29 | * 30 | ****************************************************************************** 31 | */ 32 | 33 | /* Define to prevent recursive inclusion -------------------------------------*/ 34 | #ifndef __TIMER_H__ 35 | #define __TIMER_H__ 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | /* Includes ------------------------------------------------------------------*/ 42 | #include "timeServer.h" 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* __TIMER_H__*/ 49 | 50 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 51 | -------------------------------------------------------------------------------- /lib/LoRaWAN/Utilities/utilities.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Helper functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #include 16 | #include 17 | #include 18 | #include "utilities.h" 19 | 20 | /*! 21 | * Redefinition of rand() and srand() standard C functions. 22 | * These functions are redefined in order to get the same behavior across 23 | * different compiler toolchains implementations. 24 | */ 25 | // Standard random functions redefinition start 26 | #define RAND_LOCAL_MAX 2147483647L 27 | 28 | static uint32_t next = 1; 29 | 30 | int32_t rand1( void ) 31 | { 32 | return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX ); 33 | } 34 | 35 | void srand1( uint32_t seed ) 36 | { 37 | next = seed; 38 | } 39 | // Standard random functions redefinition end 40 | 41 | int32_t randr( int32_t min, int32_t max ) 42 | { 43 | return ( int32_t )rand1( ) % ( max - min + 1 ) + min; 44 | } 45 | 46 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) 47 | { 48 | while( size-- ) 49 | { 50 | *dst++ = *src++; 51 | } 52 | } 53 | 54 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) 55 | { 56 | dst = dst + ( size - 1 ); 57 | while( size-- ) 58 | { 59 | *dst-- = *src++; 60 | } 61 | } 62 | 63 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ) 64 | { 65 | while( size-- ) 66 | { 67 | *dst++ = value; 68 | } 69 | } 70 | 71 | int8_t Nibble2HexChar( uint8_t a ) 72 | { 73 | if( a < 10 ) 74 | { 75 | return '0' + a; 76 | } 77 | else if( a < 16 ) 78 | { 79 | return 'A' + ( a - 10 ); 80 | } 81 | else 82 | { 83 | return '?'; 84 | } 85 | } 86 | 87 | uint32_t Crc32( uint8_t *buffer, uint16_t length ) 88 | { 89 | // The CRC calculation follows CCITT - 0x04C11DB7 90 | const uint32_t reversedPolynom = 0xEDB88320; 91 | 92 | // CRC initial value 93 | uint32_t crc = 0xFFFFFFFF; 94 | 95 | if( buffer == NULL ) 96 | { 97 | return 0; 98 | } 99 | 100 | for( uint16_t i = 0; i < length; ++i ) 101 | { 102 | crc ^= ( uint32_t )buffer[i]; 103 | for( uint16_t i = 0; i < 8; i++ ) 104 | { 105 | crc = ( crc >> 1 ) ^ ( reversedPolynom & ~( ( crc & 0x01 ) - 1 ) ); 106 | } 107 | } 108 | 109 | return ~crc; 110 | } 111 | 112 | uint32_t Crc32Init( void ) 113 | { 114 | return 0xFFFFFFFF; 115 | } 116 | 117 | uint32_t Crc32Update( uint32_t crcInit, uint8_t *buffer, uint16_t length ) 118 | { 119 | // The CRC calculation follows CCITT - 0x04C11DB7 120 | const uint32_t reversedPolynom = 0xEDB88320; 121 | 122 | // CRC initial value 123 | uint32_t crc = crcInit; 124 | 125 | if( buffer == NULL ) 126 | { 127 | return 0; 128 | } 129 | 130 | for( uint16_t i = 0; i < length; ++i ) 131 | { 132 | crc ^= ( uint32_t )buffer[i]; 133 | for( uint16_t i = 0; i < 8; i++ ) 134 | { 135 | crc = ( crc >> 1 ) ^ ( reversedPolynom & ~( ( crc & 0x01 ) - 1 ) ); 136 | } 137 | } 138 | return crc; 139 | } 140 | 141 | uint32_t Crc32Finalize( uint32_t crc ) 142 | { 143 | return ~crc; 144 | } 145 | -------------------------------------------------------------------------------- /lib/LoRaWAN/Utilities/utilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Helper functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | /****************************************************************************** 16 | * @file utilities.h 17 | * @author MCD Application Team 18 | * @brief Header for driver utilities.c module 19 | ****************************************************************************** 20 | * @attention 21 | * 22 | *

© Copyright (c) 2018 STMicroelectronics. 23 | * All rights reserved.

24 | * 25 | * This software component is licensed by ST under Ultimate Liberty license 26 | * SLA0044, the "License"; You may not use this file except in compliance with 27 | * the License. You may obtain a copy of the License at: 28 | * www.st.com/SLA0044 29 | * 30 | ****************************************************************************** 31 | */ 32 | 33 | #ifndef __UTILITIES_H__ 34 | #define __UTILITIES_H__ 35 | 36 | #include "irq.h" 37 | #include "atci.h" 38 | /* BACKUP_PRIMASK MUST be implemented at the begining of the funtion 39 | that implement a critical section 40 | PRIMASK is saved on STACK and recovered at the end of the funtion 41 | That way RESTORE_PRIMASK ensures critical sections are maintained even in nested calls...*/ 42 | #define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK() 43 | #define DISABLE_IRQ() __disable_irq() 44 | #define ENABLE_IRQ() __enable_irq() 45 | #define RESTORE_PRIMASK() __set_PRIMASK(primask_bit) 46 | 47 | 48 | #define CRITICAL_SECTION_BEGIN( ) uint32_t primask_bit= __get_PRIMASK();\ 49 | __disable_irq() 50 | #define CRITICAL_SECTION_END( ) __set_PRIMASK(primask_bit) 51 | 52 | #define LOG(...) do{ atci_printf(__VA_ARGS__); }while(0); 53 | 54 | /* prepocessor directive to align buffer*/ 55 | #define ALIGN(n) __attribute__((aligned(n))) 56 | 57 | /* delay definition */ 58 | #define DelayMs(n) HAL_Delay(n) 59 | 60 | typedef uint32_t TimerTime_t; 61 | #define TIMERTIME_T_MAX ( ( uint32_t )~0 ) 62 | 63 | 64 | /*! 65 | * \brief Returns the minimum value between a and b 66 | * 67 | * \param [IN] a 1st value 68 | * \param [IN] b 2nd value 69 | * \retval minValue Minimum value 70 | */ 71 | #define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) 72 | 73 | /*! 74 | * \brief Returns the maximum value between a and b 75 | * 76 | * \param [IN] a 1st value 77 | * \param [IN] b 2nd value 78 | * \retval maxValue Maximum value 79 | */ 80 | #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) 81 | 82 | /*! 83 | * \brief Returns 2 raised to the power of n 84 | * 85 | * \param [IN] n power value 86 | * \retval result of raising 2 to the power n 87 | */ 88 | #define POW2( n ) ( 1 << n ) 89 | 90 | /*! 91 | * Version 92 | */ 93 | typedef union Version_u 94 | { 95 | struct Version_s 96 | { 97 | uint8_t Revision; 98 | uint8_t Patch; 99 | uint8_t Minor; 100 | uint8_t Major; 101 | }Fields; 102 | uint32_t Value; 103 | }Version_t; 104 | 105 | /*! 106 | * \brief Initializes the pseudo random generator initial value 107 | * 108 | * \param [IN] seed Pseudo random generator initial value 109 | */ 110 | void srand1( uint32_t seed ); 111 | 112 | /*! 113 | * \brief Computes a random number between min and max 114 | * 115 | * \param [IN] min range minimum value 116 | * \param [IN] max range maximum value 117 | * \retval random random value in range min..max 118 | */ 119 | int32_t randr( int32_t min, int32_t max ); 120 | 121 | /*! 122 | * \brief Computes a random number between 123 | * 124 | * \retval random random value in range min..max 125 | */ 126 | int32_t rand1( void ); 127 | 128 | /*! 129 | * \brief Copies size elements of src array to dst array 130 | * 131 | * \remark STM32 Standard memcpy function only works on pointers that are aligned 132 | * 133 | * \param [OUT] dst Destination array 134 | * \param [IN] src Source array 135 | * \param [IN] size Number of bytes to be copied 136 | */ 137 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ); 138 | 139 | /*! 140 | * \brief Copies size elements of src array to dst array reversing the byte order 141 | * 142 | * \param [OUT] dst Destination array 143 | * \param [IN] src Source array 144 | * \param [IN] size Number of bytes to be copied 145 | */ 146 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ); 147 | 148 | /*! 149 | * \brief Set size elements of dst array with value 150 | * 151 | * \remark STM32 Standard memset function only works on pointers that are aligned 152 | * 153 | * \param [OUT] dst Destination array 154 | * \param [IN] value Default value 155 | * \param [IN] size Number of bytes to be copied 156 | */ 157 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ); 158 | 159 | /*! 160 | * \brief Converts a nibble to an hexadecimal character 161 | * 162 | * \param [IN] a Nibble to be converted 163 | * \retval hexChar Converted hexadecimal character 164 | */ 165 | int8_t Nibble2HexChar( uint8_t a ); 166 | 167 | /*! 168 | * \brief Computes a CCITT 32 bits CRC 169 | * 170 | * \param [IN] buffer Data buffer used to compute the CRC 171 | * \param [IN] length Data buffer length 172 | * 173 | * \retval crc The computed buffer of length CRC 174 | */ 175 | uint32_t Crc32( uint8_t *buffer, uint16_t length ); 176 | 177 | /*! 178 | * \brief Computes the initial value of the CCITT 32 bits CRC. This function 179 | * can be used with functions \ref Crc32Update and \ref Crc32Finalize. 180 | * 181 | * \retval crc Initial crc value. 182 | */ 183 | uint32_t Crc32Init( void ); 184 | 185 | /*! 186 | * \brief Updates the value of the crc value. 187 | * 188 | * \param [IN] crcInit Previous or initial crc value. 189 | * \param [IN] buffer Data pointer. 190 | * \param [IN] length Length of the data. 191 | * 192 | * \retval crc Updated crc value. 193 | */ 194 | uint32_t Crc32Update( uint32_t crcInit, uint8_t *buffer, uint16_t length ); 195 | 196 | /*! 197 | * \brief Finalizes the crc value after the calls to \ref Crc32Update. 198 | * 199 | * \param [IN] crc Recent crc value. 200 | * 201 | * \retval crc Updated crc value. 202 | */ 203 | uint32_t Crc32Finalize( uint32_t crc ); 204 | 205 | #endif // __UTILITIES_H__ 206 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32_assert_template.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32_assert.h 4 | * @author MCD Application Team 5 | * @brief STM32 assert template file. 6 | * This file should be copied to the application folder and renamed 7 | * to stm32_assert.h. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© Copyright (c) 2016 STMicroelectronics. 12 | * All rights reserved.

13 | * 14 | * This software component is licensed by ST under BSD 3-Clause license, 15 | * the "License"; You may not use this file except in compliance with the 16 | * License. You may obtain a copy of the License at: 17 | * opensource.org/licenses/BSD-3-Clause 18 | * 19 | ****************************************************************************** 20 | */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32_ASSERT_H 24 | #define __STM32_ASSERT_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* Exported types ------------------------------------------------------------*/ 31 | /* Exported constants --------------------------------------------------------*/ 32 | /* Includes ------------------------------------------------------------------*/ 33 | /* Exported macro ------------------------------------------------------------*/ 34 | #ifdef USE_FULL_ASSERT 35 | /** 36 | * @brief The assert_param macro is used for function's parameters check. 37 | * @param expr If expr is false, it calls assert_failed function 38 | * which reports the name of the source file and the source 39 | * line number of the call that failed. 40 | * If expr is true, it returns no value. 41 | * @retval None 42 | */ 43 | #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) 44 | /* Exported functions ------------------------------------------------------- */ 45 | void assert_failed(uint8_t* file, uint32_t line); 46 | #else 47 | #define assert_param(expr) ((void)0U) 48 | #endif /* USE_FULL_ASSERT */ 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif /* __STM32_ASSERT_H */ 55 | 56 | 57 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 58 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_comp_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_comp_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of COMP HAL Extended module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32L0xx_HAL_COMP_EX_H 22 | #define __STM32L0xx_HAL_COMP_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #if !defined(STM32L010xB) && !defined (STM32L010x8) && !defined (STM32L010x6) && !defined (STM32L010x4) 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "stm32l0xx_hal_def.h" 31 | 32 | /** @addtogroup STM32L0xx_HAL_Driver 33 | * @{ 34 | */ 35 | 36 | /** @defgroup COMPEx COMPEx 37 | * @{ 38 | */ 39 | 40 | /* Exported functions --------------------------------------------------------*/ 41 | /** @defgroup COMPEx_Exported_Functions COMPEx Exported Functions 42 | * @{ 43 | */ 44 | 45 | /** @defgroup COMPEx_Exported_Functions_Group1 Extended COMP VREFINT setup functions 46 | * @{ 47 | */ 48 | /* COMP specific functions to manage VREFINT *************************************/ 49 | void HAL_COMPEx_EnableVREFINT(void); 50 | void HAL_COMPEx_DisableVREFINT(void); 51 | 52 | /** 53 | * @} 54 | */ 55 | 56 | /** 57 | * @} 58 | */ 59 | 60 | /** 61 | * @} 62 | */ 63 | 64 | /** 65 | * @} 66 | */ 67 | #endif /* #if !defined(STM32L010xB) && !defined (STM32L010x8) && !defined (STM32L010x6) && !defined (STM32L010x4) */ 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif /* __STM32L0xx_HAL_COMP_EX_H */ 74 | 75 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 76 | 77 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_crc_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_crc_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of CRC HAL extended module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef STM32L0xx_HAL_CRC_EX_H 22 | #define STM32L0xx_HAL_CRC_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32l0xx_hal_def.h" 30 | 31 | /** @addtogroup STM32L0xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @addtogroup CRCEx 36 | * @{ 37 | */ 38 | 39 | /* Exported types ------------------------------------------------------------*/ 40 | /* Exported constants --------------------------------------------------------*/ 41 | /** @defgroup CRCEx_Exported_Constants CRC Extended Exported Constants 42 | * @{ 43 | */ 44 | 45 | /** @defgroup CRCEx_Input_Data_Inversion Input Data Inversion Modes 46 | * @{ 47 | */ 48 | #define CRC_INPUTDATA_INVERSION_NONE 0x00000000U /*!< No input data inversion */ 49 | #define CRC_INPUTDATA_INVERSION_BYTE CRC_CR_REV_IN_0 /*!< Byte-wise input data inversion */ 50 | #define CRC_INPUTDATA_INVERSION_HALFWORD CRC_CR_REV_IN_1 /*!< HalfWord-wise input data inversion */ 51 | #define CRC_INPUTDATA_INVERSION_WORD CRC_CR_REV_IN /*!< Word-wise input data inversion */ 52 | /** 53 | * @} 54 | */ 55 | 56 | /** @defgroup CRCEx_Output_Data_Inversion Output Data Inversion Modes 57 | * @{ 58 | */ 59 | #define CRC_OUTPUTDATA_INVERSION_DISABLE 0x00000000U /*!< No output data inversion */ 60 | #define CRC_OUTPUTDATA_INVERSION_ENABLE CRC_CR_REV_OUT /*!< Bit-wise output data inversion */ 61 | /** 62 | * @} 63 | */ 64 | 65 | /** 66 | * @} 67 | */ 68 | 69 | /* Exported macro ------------------------------------------------------------*/ 70 | /** @defgroup CRCEx_Exported_Macros CRC Extended Exported Macros 71 | * @{ 72 | */ 73 | 74 | /** 75 | * @brief Set CRC output reversal 76 | * @param __HANDLE__ CRC handle 77 | * @retval None 78 | */ 79 | #define __HAL_CRC_OUTPUTREVERSAL_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= CRC_CR_REV_OUT) 80 | 81 | /** 82 | * @brief Unset CRC output reversal 83 | * @param __HANDLE__ CRC handle 84 | * @retval None 85 | */ 86 | #define __HAL_CRC_OUTPUTREVERSAL_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(CRC_CR_REV_OUT)) 87 | 88 | /** 89 | * @brief Set CRC non-default polynomial 90 | * @param __HANDLE__ CRC handle 91 | * @param __POLYNOMIAL__ 7, 8, 16 or 32-bit polynomial 92 | * @retval None 93 | */ 94 | #define __HAL_CRC_POLYNOMIAL_CONFIG(__HANDLE__, __POLYNOMIAL__) ((__HANDLE__)->Instance->POL = (__POLYNOMIAL__)) 95 | 96 | /** 97 | * @} 98 | */ 99 | 100 | /* Private macros --------------------------------------------------------*/ 101 | /** @defgroup CRCEx_Private_Macros CRC Extended Private Macros 102 | * @{ 103 | */ 104 | 105 | #define IS_CRC_INPUTDATA_INVERSION_MODE(MODE) (((MODE) == CRC_INPUTDATA_INVERSION_NONE) || \ 106 | ((MODE) == CRC_INPUTDATA_INVERSION_BYTE) || \ 107 | ((MODE) == CRC_INPUTDATA_INVERSION_HALFWORD) || \ 108 | ((MODE) == CRC_INPUTDATA_INVERSION_WORD)) 109 | 110 | #define IS_CRC_OUTPUTDATA_INVERSION_MODE(MODE) (((MODE) == CRC_OUTPUTDATA_INVERSION_DISABLE) || \ 111 | ((MODE) == CRC_OUTPUTDATA_INVERSION_ENABLE)) 112 | 113 | /** 114 | * @} 115 | */ 116 | 117 | /* Exported functions --------------------------------------------------------*/ 118 | 119 | /** @addtogroup CRCEx_Exported_Functions 120 | * @{ 121 | */ 122 | 123 | /** @addtogroup CRCEx_Exported_Functions_Group1 124 | * @{ 125 | */ 126 | /* Initialization and de-initialization functions ****************************/ 127 | HAL_StatusTypeDef HAL_CRCEx_Polynomial_Set(CRC_HandleTypeDef *hcrc, uint32_t Pol, uint32_t PolyLength); 128 | HAL_StatusTypeDef HAL_CRCEx_Input_Data_Reverse(CRC_HandleTypeDef *hcrc, uint32_t InputReverseMode); 129 | HAL_StatusTypeDef HAL_CRCEx_Output_Data_Reverse(CRC_HandleTypeDef *hcrc, uint32_t OutputReverseMode); 130 | 131 | /** 132 | * @} 133 | */ 134 | 135 | /** 136 | * @} 137 | */ 138 | 139 | /** 140 | * @} 141 | */ 142 | 143 | /** 144 | * @} 145 | */ 146 | 147 | #ifdef __cplusplus 148 | } 149 | #endif 150 | 151 | #endif /* STM32L0xx_HAL_CRC_EX_H */ 152 | 153 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 154 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_cryp_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_cryp_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of CRYPEx HAL module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32L0xx_HAL_CRYP_EX_H 22 | #define __STM32L0xx_HAL_CRYP_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #if defined (STM32L021xx) || defined (STM32L041xx) || defined (STM32L061xx) || defined (STM32L062xx) || defined (STM32L063xx) || (STM32L081xx) || defined (STM32L082xx) || defined (STM32L083xx) 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | #include "stm32l0xx_hal_def.h" 32 | 33 | /** @addtogroup STM32L0xx_HAL_Driver 34 | * @{ 35 | */ 36 | 37 | /** @defgroup CRYPEx CRYPEx 38 | * @{ 39 | */ 40 | 41 | /* Exported types ------------------------------------------------------------*/ 42 | /* Exported constants --------------------------------------------------------*/ 43 | /* Exported functions --------------------------------------------------------*/ 44 | 45 | /** @defgroup CRYPEx_Exported_Functions CRYPEx Exported Functions 46 | * @{ 47 | */ 48 | 49 | /** @defgroup CRYPEx_Exported_Functions_Group1 Extended features functions 50 | * @{ 51 | */ 52 | 53 | /* CallBack functions ********************************************************/ 54 | void HAL_CRYPEx_ComputationCpltCallback(CRYP_HandleTypeDef *hcryp); 55 | 56 | /** 57 | * @} 58 | */ 59 | 60 | /** 61 | * @} 62 | */ 63 | 64 | /** 65 | * @} 66 | */ 67 | 68 | /** 69 | * @} 70 | */ 71 | 72 | #endif /* STM32L021xx || STM32L041xx || STM32L061xx || STM32L062xx || STM32L063xx || STM32L081xx || STM32L082xx || STM32L083xx */ 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | #endif /* __STM32L0xx_HAL_CRYP_EX_H */ 79 | 80 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 81 | 82 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_flash_ramfunc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_flash_ramfunc.h 4 | * @author MCD Application Team 5 | * @brief Header file of FLASH RAMFUNC driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32L0xx_FLASH_RAMFUNC_H 22 | #define __STM32L0xx_FLASH_RAMFUNC_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32l0xx_hal_def.h" 30 | 31 | /** @addtogroup STM32L0xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @addtogroup FLASH_RAMFUNC 36 | * @{ 37 | */ 38 | 39 | /* Exported types ------------------------------------------------------------*/ 40 | 41 | 42 | /* Exported functions --------------------------------------------------------*/ 43 | 44 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions 45 | * @{ 46 | */ 47 | 48 | /* 49 | * @brief FLASH memory functions that should be executed from internal SRAM. 50 | * These functions are defined inside the "stm32l0xx_hal_flash_ramfunc.c" 51 | * file. 52 | */ 53 | 54 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group1 55 | * @{ 56 | */ 57 | 58 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableRunPowerDown(void); 59 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableRunPowerDown(void); 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group2 66 | * @{ 67 | */ 68 | 69 | #if defined(FLASH_PECR_PARALLBANK) 70 | 71 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EraseParallelPage(uint32_t Page_Address1, uint32_t Page_Address2); 72 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_ProgramParallelHalfPage(uint32_t Address1, uint32_t* pBuffer1, uint32_t Address2, uint32_t* pBuffer2); 73 | 74 | #endif /* FLASH_PECR_PARALLBANK */ 75 | 76 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_HalfPageProgram(uint32_t Address, uint32_t* pBuffer); 77 | 78 | /** 79 | * @} 80 | */ 81 | 82 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group3 83 | * @{ 84 | */ 85 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_GetError(uint32_t *Error); 86 | /** 87 | * @} 88 | */ 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | /** 99 | * @} 100 | */ 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | 106 | #endif /* __STM32L0xx_FLASH_RAMFUNC_H */ 107 | 108 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 109 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_lptim_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_lptim_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of LPTIM Extended HAL module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32L0xx_HAL_LPTIM_EX_H 22 | #define __STM32L0xx_HAL_LPTIM_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32l0xx_hal_def.h" 30 | 31 | /** @addtogroup STM32L0xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @defgroup LPTIMEx LPTIMEx 36 | * @{ 37 | */ 38 | 39 | /* Exported constants --------------------------------------------------------*/ 40 | 41 | /** @defgroup LPTIMEx_Exported_Constants LPTIMEx Exported Constants 42 | * @{ 43 | */ 44 | 45 | 46 | /** @defgroup LPTIMEx_Trigger_Source LPTIMEx Trigger source 47 | * @{ 48 | */ 49 | #define LPTIM_TRIGSOURCE_SOFTWARE 0x0000FFFFU /*!< LPTIM counter triggered by software*/ 50 | #define LPTIM_TRIGSOURCE_0 0x00000000U /*!< LPTIM counter triggered by GPIO (alternate function LPTIM_ETR) */ 51 | #define LPTIM_TRIGSOURCE_1 LPTIM_CFGR_TRIGSEL_0 /*!< LPTIM counter triggered by RTC alarm A */ 52 | #define LPTIM_TRIGSOURCE_2 LPTIM_CFGR_TRIGSEL_1 /*!< LPTIM counter triggered by RTC alarm B */ 53 | #define LPTIM_TRIGSOURCE_3 (LPTIM_CFGR_TRIGSEL_0 | LPTIM_CFGR_TRIGSEL_1) /*!< LPTIM counter triggered by RTC_TAMP1 input detection */ 54 | #define LPTIM_TRIGSOURCE_4 LPTIM_CFGR_TRIGSEL_2 /*!< LPTIM counter triggered by RTC_TAMP2 input detection */ 55 | #if defined(RTC_TAMPER3_SUPPORT) 56 | #define LPTIM_TRIGSOURCE_5 (LPTIM_CFGR_TRIGSEL_0 | LPTIM_CFGR_TRIGSEL_2) /*!< LPTIM counter triggered by RTC_TAMP3 input detection */ 57 | #endif /* RTC_TAMPER3_SUPPORT */ 58 | #if defined(COMP1) && defined(COMP2) 59 | #define LPTIM_TRIGSOURCE_6 (LPTIM_CFGR_TRIGSEL_1 | LPTIM_CFGR_TRIGSEL_2) /*!< LPTIM counter triggered by COMP1_OUT */ 60 | #define LPTIM_TRIGSOURCE_7 LPTIM_CFGR_TRIGSEL /*!< LPTIM counter triggered by COMP2_OUT */ 61 | #endif /* COMP1 && COMP2 */ 62 | /** 63 | * @} 64 | */ 65 | 66 | /** 67 | * @} 68 | */ 69 | 70 | /** @addtogroup LPTIMEx_Private 71 | * @{ 72 | */ 73 | #if defined(RTC_TAMPER3_SUPPORT) && defined(COMP1) && defined(COMP2) 74 | #define IS_LPTIM_TRG_SOURCE(__TRIG__) (((__TRIG__) == LPTIM_TRIGSOURCE_SOFTWARE) || \ 75 | ((__TRIG__) == LPTIM_TRIGSOURCE_0) || \ 76 | ((__TRIG__) == LPTIM_TRIGSOURCE_1) || \ 77 | ((__TRIG__) == LPTIM_TRIGSOURCE_2) || \ 78 | ((__TRIG__) == LPTIM_TRIGSOURCE_3) || \ 79 | ((__TRIG__) == LPTIM_TRIGSOURCE_4) || \ 80 | ((__TRIG__) == LPTIM_TRIGSOURCE_5) || \ 81 | ((__TRIG__) == LPTIM_TRIGSOURCE_6) || \ 82 | ((__TRIG__) == LPTIM_TRIGSOURCE_7)) 83 | #elif defined(RTC_TAMPER3_SUPPORT) 84 | #define IS_LPTIM_TRG_SOURCE(__TRIG__) (((__TRIG__) == LPTIM_TRIGSOURCE_SOFTWARE) || \ 85 | ((__TRIG__) == LPTIM_TRIGSOURCE_0) || \ 86 | ((__TRIG__) == LPTIM_TRIGSOURCE_1) || \ 87 | ((__TRIG__) == LPTIM_TRIGSOURCE_2) || \ 88 | ((__TRIG__) == LPTIM_TRIGSOURCE_3) || \ 89 | ((__TRIG__) == LPTIM_TRIGSOURCE_4) || \ 90 | ((__TRIG__) == LPTIM_TRIGSOURCE_5)) 91 | #else 92 | #define IS_LPTIM_TRG_SOURCE(__TRIG__) (((__TRIG__) == LPTIM_TRIGSOURCE_SOFTWARE) || \ 93 | ((__TRIG__) == LPTIM_TRIGSOURCE_0) || \ 94 | ((__TRIG__) == LPTIM_TRIGSOURCE_1) || \ 95 | ((__TRIG__) == LPTIM_TRIGSOURCE_2) || \ 96 | ((__TRIG__) == LPTIM_TRIGSOURCE_3) || \ 97 | ((__TRIG__) == LPTIM_TRIGSOURCE_4) || \ 98 | ((__TRIG__) == LPTIM_TRIGSOURCE_6) || \ 99 | ((__TRIG__) == LPTIM_TRIGSOURCE_7)) 100 | #endif /* RTC_TAMPER3_SUPPORT && COMP1 && COMP2 */ 101 | /** 102 | * @} 103 | */ 104 | 105 | /** 106 | * @} 107 | */ 108 | 109 | /** 110 | * @} 111 | */ 112 | 113 | #ifdef __cplusplus 114 | } 115 | #endif 116 | 117 | #endif /* __STM32L0xx_HAL_LPTIM_EX_H */ 118 | 119 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 120 | 121 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_pcd_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_pcd_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of PCD HAL Extension module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef STM32L0xx_HAL_PCD_EX_H 22 | #define STM32L0xx_HAL_PCD_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32l0xx_hal_def.h" 30 | 31 | #if defined (USB) 32 | /** @addtogroup STM32L0xx_HAL_Driver 33 | * @{ 34 | */ 35 | 36 | /** @addtogroup PCDEx 37 | * @{ 38 | */ 39 | /* Exported types ------------------------------------------------------------*/ 40 | /* Exported constants --------------------------------------------------------*/ 41 | /* Exported macros -----------------------------------------------------------*/ 42 | /* Exported functions --------------------------------------------------------*/ 43 | /** @addtogroup PCDEx_Exported_Functions PCDEx Exported Functions 44 | * @{ 45 | */ 46 | /** @addtogroup PCDEx_Exported_Functions_Group1 Peripheral Control functions 47 | * @{ 48 | */ 49 | 50 | 51 | 52 | HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, 53 | uint16_t ep_addr, 54 | uint16_t ep_kind, 55 | uint32_t pmaadress); 56 | 57 | 58 | HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd); 59 | HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd); 60 | 61 | 62 | HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd); 63 | HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd); 64 | void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd); 65 | 66 | void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg); 67 | void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg); 68 | 69 | /** 70 | * @} 71 | */ 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | /** 78 | * @} 79 | */ 80 | 81 | /** 82 | * @} 83 | */ 84 | #endif /* defined (USB) */ 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | 91 | #endif /* STM32L0xx_HAL_PCD_EX_H */ 92 | 93 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 94 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_pwr_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_pwr_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of PWR HAL Extension module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32L0xx_HAL_PWR_EX_H 22 | #define __STM32L0xx_HAL_PWR_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32l0xx_hal_def.h" 30 | 31 | /** @addtogroup STM32L0xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @defgroup PWREx PWREx 36 | * @{ 37 | */ 38 | 39 | /** @defgroup PWREx_Exported_Macros PWREx Exported Macros 40 | * @{ 41 | */ 42 | 43 | /** @brief Macros to enable the Deep-sleep mode with Flash memory kept off. 44 | * @note When entering low power mode (stop or standby only), if DS_EE_KOFF and RUN_PD of 45 | * FLASH_ACR register are both set , the Flash memory will not be woken up 46 | * when exiting from deep-sleep mode. 47 | */ 48 | #define __HAL_PWR_FLASHWAKEUP_ENABLE() CLEAR_BIT(PWR->CR, PWR_CR_DSEEKOFF) 49 | 50 | /** @brief Macros to disable the Deep-sleep mode with Flash memory kept off. 51 | * @note When entering low power mode (stop or standby only), if DS_EE_KOFF and RUN_PD of 52 | * FLASH_ACR register are both set , the Flash memory will not be woken up 53 | * when exiting from deep-sleep mode. 54 | */ 55 | #define __HAL_PWR_FLASHWAKEUP_DISABLE() SET_BIT(PWR->CR, PWR_CR_DSEEKOFF) 56 | /** 57 | * @} 58 | */ 59 | 60 | /** @defgroup PWREx_Exported_Functions PWREx Exported Functions 61 | * @{ 62 | */ 63 | uint32_t HAL_PWREx_GetVoltageRange(void); 64 | void HAL_PWREx_EnableFastWakeUp(void); 65 | void HAL_PWREx_DisableFastWakeUp(void); 66 | void HAL_PWREx_EnableUltraLowPower(void); 67 | void HAL_PWREx_DisableUltraLowPower(void); 68 | void HAL_PWREx_EnableLowPowerRunMode(void); 69 | HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void); 70 | /** 71 | * @} 72 | */ 73 | 74 | /* Define the private group ***********************************/ 75 | /**************************************************************/ 76 | /** @defgroup PWREx_Private PWREx Private 77 | * @{ 78 | */ 79 | /** 80 | * @} 81 | */ 82 | /**************************************************************/ 83 | 84 | /** 85 | * @} 86 | */ 87 | 88 | /** 89 | * @} 90 | */ 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif /* __STM32L0xx_HAL_PWR_EX_H */ 97 | 98 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 99 | 100 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_comp_ex.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_comp_ex.c 4 | * @author MCD Application Team 5 | * @brief Extended COMP HAL module driver. 6 | * @brief This file provides firmware functions to manage voltage reference 7 | * VrefInt that must be specifically controled for comparator 8 | * instance COMP2. 9 | @verbatim 10 | ============================================================================== 11 | ##### COMP peripheral Extended features ##### 12 | ============================================================================== 13 | 14 | [..] Comparing to other previous devices, the COMP interface for STM32L0XX 15 | devices contains the following additional features 16 | 17 | (+) Possibility to enable or disable the VREFINT which is used as input 18 | to the comparator. 19 | 20 | 21 | @endverbatim 22 | ****************************************************************************** 23 | * @attention 24 | * 25 | *

© Copyright(c) 2016 STMicroelectronics. 26 | * All rights reserved.

27 | * 28 | * This software component is licensed by ST under BSD 3-Clause license, 29 | * the "License"; You may not use this file except in compliance with the 30 | * License. You may obtain a copy of the License at: 31 | * opensource.org/licenses/BSD-3-Clause 32 | * 33 | ****************************************************************************** 34 | */ 35 | 36 | #if !defined (STM32L010xB) && !defined (STM32L010x8) && !defined (STM32L010x6) && !defined (STM32L010x4) 37 | /* Includes ------------------------------------------------------------------*/ 38 | #include "stm32l0xx_hal.h" 39 | 40 | /** @addtogroup STM32L0xx_HAL_Driver 41 | * @{ 42 | */ 43 | 44 | #ifdef HAL_COMP_MODULE_ENABLED 45 | 46 | /** @addtogroup COMPEx 47 | * @brief Extended COMP HAL module driver 48 | * @{ 49 | */ 50 | 51 | /* Private define ------------------------------------------------------------*/ 52 | /** @addtogroup COMP_Private_Constants 53 | * @{ 54 | */ 55 | 56 | /* Delay for COMP voltage scaler stabilization time (voltage from VrefInt, */ 57 | /* delay based on VrefInt startup time). */ 58 | /* Literal set to maximum value (refer to device datasheet, */ 59 | /* parameter "TVREFINT"). */ 60 | /* Unit: us */ 61 | #define COMP_DELAY_VOLTAGE_SCALER_STAB_US ((uint32_t)3000U) /*!< Delay for COMP voltage scaler stabilization time */ 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | /* Exported functions --------------------------------------------------------*/ 68 | /** @addtogroup COMPEx_Exported_Functions 69 | * @{ 70 | */ 71 | 72 | /** @addtogroup COMPEx_Exported_Functions_Group1 73 | * @brief Extended functions to manage VREFINT for the comparator 74 | * 75 | * @{ 76 | */ 77 | 78 | /** 79 | * @brief Enable Vrefint and path to comparator, used by comparator 80 | * instance COMP2 input based on VrefInt or subdivision of VrefInt. 81 | * @note The equivalent of this function is managed automatically when 82 | * using function "HAL_COMP_Init()". 83 | * @note VrefInt requires a startup time 84 | * (refer to device datasheet, parameter "TVREFINT"). 85 | * This function waits for the startup time 86 | * (alternative solution: poll for bit SYSCFG_CFGR3_VREFINT_RDYF set). 87 | * @note VrefInt must be disabled before entering in low-power mode. 88 | * Refer to description of bit EN_VREFINT in reference manual. 89 | * @retval None 90 | */ 91 | void HAL_COMPEx_EnableVREFINT(void) 92 | { 93 | __IO uint32_t wait_loop_index = 0U; 94 | 95 | /* Enable VrefInt voltage reference and buffer */ 96 | SYSCFG->CFGR3 |= (SYSCFG_CFGR3_ENBUFLP_VREFINT_COMP | SYSCFG_CFGR3_EN_VREFINT); 97 | 98 | /* Wait loop initialization and execution */ 99 | /* Note: Variable divided by 2 to compensate partially */ 100 | /* CPU processing cycles. */ 101 | wait_loop_index = (COMP_DELAY_VOLTAGE_SCALER_STAB_US * (SystemCoreClock / (1000000U * 2U))); 102 | while(wait_loop_index != 0U) 103 | { 104 | wait_loop_index--; 105 | } 106 | } 107 | 108 | /** 109 | * @brief Disable Vrefint and path to comparator, used by comparator 110 | * instance COMP2 input based on VrefInt or subdivision of VrefInt. 111 | * @note VrefInt must be disabled before entering in low-power mode. 112 | * Refer to description of bit EN_VREFINT in reference manual. 113 | * @retval None 114 | */ 115 | void HAL_COMPEx_DisableVREFINT(void) 116 | { 117 | /* Disable VrefInt voltage reference and buffer */ 118 | SYSCFG->CFGR3 &= (uint32_t)~((uint32_t)(SYSCFG_CFGR3_ENBUFLP_VREFINT_COMP | SYSCFG_CFGR3_EN_VREFINT)); 119 | } 120 | 121 | /** 122 | * @} 123 | */ 124 | 125 | /** 126 | * @} 127 | */ 128 | 129 | /** 130 | * @} 131 | */ 132 | 133 | #endif /* HAL_COMP_MODULE_ENABLED */ 134 | 135 | /** 136 | * @} 137 | */ 138 | #endif /* #if !defined (STM32L010xB) && !defined (STM32L010x8) && !defined (STM32L010x6) && !defined (STM32L010x4) */ 139 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 140 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_cryp_ex.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_cryp_ex.c 4 | * @author MCD Application Team 5 | * @brief CRYPEx HAL module driver. 6 | * 7 | * This file provides firmware functions to manage the following 8 | * functionalities of the Cryptography (CRYP) extension peripheral: 9 | * + Computation completed callback. 10 | * 11 | ****************************************************************************** 12 | * @attention 13 | * 14 | *

© Copyright(c) 2016 STMicroelectronics. 15 | * All rights reserved.

16 | * 17 | * This software component is licensed by ST under BSD 3-Clause license, 18 | * the "License"; You may not use this file except in compliance with the 19 | * License. You may obtain a copy of the License at: 20 | * opensource.org/licenses/BSD-3-Clause 21 | * 22 | ****************************************************************************** 23 | */ 24 | 25 | #if defined (STM32L021xx) || defined (STM32L041xx) || defined (STM32L061xx) || defined (STM32L062xx) || defined (STM32L063xx) || defined (STM32L081xx) || defined (STM32L082xx) || defined (STM32L083xx) 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32l0xx_hal.h" 28 | 29 | /** @addtogroup STM32L0xx_HAL_Driver 30 | * @{ 31 | */ 32 | #ifdef HAL_CRYP_MODULE_ENABLED 33 | 34 | 35 | /** @addtogroup CRYPEx 36 | * @brief CRYP HAL Extended module driver. 37 | * @{ 38 | */ 39 | 40 | 41 | /* Private typedef -----------------------------------------------------------*/ 42 | /* Private define ------------------------------------------------------------*/ 43 | /* Private macro -------------------------------------------------------------*/ 44 | /* Private variables ---------------------------------------------------------*/ 45 | /* Private function prototypes -----------------------------------------------*/ 46 | /* Private functions ---------------------------------------------------------*/ 47 | 48 | /** @addtogroup CRYPEx_Exported_Functions 49 | * @{ 50 | */ 51 | 52 | 53 | /** @addtogroup CRYPEx_Exported_Functions_Group1 54 | * @brief Extended features functions. 55 | * 56 | @verbatim 57 | =============================================================================== 58 | ##### Extended features functions ##### 59 | =============================================================================== 60 | [..] This section provides callback functions: 61 | (+) Computation completed. 62 | 63 | @endverbatim 64 | * @{ 65 | */ 66 | 67 | /** 68 | * @brief Computation completed callbacks. 69 | * @param hcryp pointer to a CRYP_HandleTypeDef structure that contains 70 | * the configuration information for CRYP module 71 | * @retval None 72 | */ 73 | __weak void HAL_CRYPEx_ComputationCpltCallback(CRYP_HandleTypeDef *hcryp) 74 | { 75 | /* Prevent unused argument(s) compilation warning */ 76 | UNUSED(hcryp); 77 | 78 | /* NOTE : This function Should not be modified, when the callback is needed, 79 | the HAL_CRYP_ComputationCpltCallback could be implemented in the user file 80 | */ 81 | } 82 | 83 | /** 84 | * @} 85 | */ 86 | 87 | 88 | /** 89 | * @} 90 | */ 91 | /** 92 | * @} 93 | */ 94 | 95 | #endif /* HAL_CRYP_MODULE_ENABLED */ 96 | 97 | /** 98 | * @} 99 | */ 100 | #endif /* STM32L021xx || STM32L041xx || STM32L061xx || STM32L062xx || STM32L063xx || STM32L081xx || STM32L082xx || STM32L083xx */ 101 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 102 | 103 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_msp_template.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_msp_template.c 4 | * @author MCD Application Team 5 | * @brief HAL MSP module. 6 | * This file template is located in the HAL folder and should be copied 7 | * to the user folder. 8 | * 9 | @verbatim 10 | =============================================================================== 11 | ##### How to use this driver ##### 12 | =============================================================================== 13 | [..] 14 | This file is eventually modified by the user. 15 | 16 | @endverbatim 17 | ****************************************************************************** 18 | * @attention 19 | * 20 | *

© Copyright (c) 2016 STMicroelectronics. 21 | * All rights reserved.

22 | * 23 | * This software component is licensed by ST under BSD 3-Clause license, 24 | * the "License"; You may not use this file except in compliance with the 25 | * License. You may obtain a copy of the License at: 26 | * opensource.org/licenses/BSD-3-Clause 27 | * 28 | ****************************************************************************** 29 | */ 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32l0xx_hal.h" 33 | 34 | /** @addtogroup STM32L0xx_HAL_Driver 35 | * @{ 36 | */ 37 | 38 | /** @defgroup HAL_MSP 39 | * @brief HAL MSP module. 40 | * @{ 41 | */ 42 | 43 | /* Private typedef -----------------------------------------------------------*/ 44 | /* Private define ------------------------------------------------------------*/ 45 | /* Private macro -------------------------------------------------------------*/ 46 | /* Private variables ---------------------------------------------------------*/ 47 | /* Private function prototypes -----------------------------------------------*/ 48 | /* Private functions ---------------------------------------------------------*/ 49 | 50 | /** @defgroup HAL_MSP_Private_Functions 51 | * @{ 52 | */ 53 | 54 | /** 55 | * @brief Initializes the Global BSP. 56 | * @param None 57 | * @retval None 58 | */ 59 | void HAL_MspInit(void) 60 | { 61 | /* NOTE : This function is eventually modified by the user */ 62 | } 63 | 64 | /** 65 | * @brief DeInitializes the Global MSP. 66 | * @param None 67 | * @retval None 68 | */ 69 | void HAL_MspDeInit(void) 70 | { 71 | /* NOTE : This function is eventually modified by the user */ 72 | } 73 | 74 | /** 75 | * @brief Initializes the PPP MSP. 76 | * @param None 77 | * @retval None 78 | */ 79 | void HAL_PPP_MspInit(void) 80 | { 81 | /* NOTE : This function is eventually modified by the user */ 82 | } 83 | 84 | /** 85 | * @brief DeInitializes the PPP MSP. 86 | * @param None 87 | * @retval None 88 | */ 89 | void HAL_PPP_MspDeInit(void) 90 | { 91 | /* NOTE : This function is eventually modified by the user */ 92 | } 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | /** 99 | * @} 100 | */ 101 | 102 | /** 103 | * @} 104 | */ 105 | 106 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 107 | 108 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr_ex.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_hal_pwr_ex.c 4 | * @author MCD Application Team 5 | * @brief Extended PWR HAL module driver. 6 | * This file provides firmware functions to manage the following 7 | * functionalities of the Power Controller (PWR) peripheral: 8 | * + Extended Initialization and de-initialization functions 9 | * + Extended Peripheral Control functions 10 | * 11 | ****************************************************************************** 12 | * @attention 13 | * 14 | *

© Copyright(c) 2016 STMicroelectronics. 15 | * All rights reserved.

16 | * 17 | * This software component is licensed by ST under BSD 3-Clause license, 18 | * the "License"; You may not use this file except in compliance with the 19 | * License. You may obtain a copy of the License at: 20 | * opensource.org/licenses/BSD-3-Clause 21 | * 22 | ****************************************************************************** 23 | */ 24 | 25 | /* Includes ------------------------------------------------------------------*/ 26 | #include "stm32l0xx_hal.h" 27 | 28 | #ifdef HAL_PWR_MODULE_ENABLED 29 | /** @addtogroup STM32L0xx_HAL_Driver 30 | * @{ 31 | */ 32 | 33 | /** @addtogroup PWREx 34 | * @{ 35 | */ 36 | 37 | /** @addtogroup PWREx_Private 38 | * @{ 39 | */ 40 | 41 | /** @defgroup PWR_Extended_TimeOut_Value PWREx Flag Setting Time Out Value 42 | * @{ 43 | */ 44 | #define PWR_FLAG_SETTING_DELAY_US 50U 45 | /** 46 | * @} 47 | */ 48 | 49 | /** 50 | * @} 51 | */ 52 | 53 | 54 | /** @addtogroup PWREx_Exported_Functions 55 | * @brief Low Power modes configuration functions 56 | * 57 | @verbatim 58 | 59 | =============================================================================== 60 | ##### Peripheral extended features functions ##### 61 | =============================================================================== 62 | @endverbatim 63 | * @{ 64 | */ 65 | 66 | /** 67 | * @brief Return Voltage Scaling Range. 68 | * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_SCALE1, PWR_REGULATOR_VOLTAGE_SCALE2 or PWR_REGULATOR_VOLTAGE_SCALE3) 69 | */ 70 | uint32_t HAL_PWREx_GetVoltageRange(void) 71 | { 72 | return (PWR->CR & PWR_CR_VOS); 73 | } 74 | 75 | 76 | /** 77 | * @brief Enables the Fast WakeUp from Ultra Low Power mode. 78 | * @note This bit works in conjunction with ULP bit. 79 | * Means, when ULP = 1 and FWU = 1 :VREFINT startup time is ignored when 80 | * exiting from low power mode. 81 | * @retval None 82 | */ 83 | void HAL_PWREx_EnableFastWakeUp(void) 84 | { 85 | /* Enable the fast wake up */ 86 | SET_BIT(PWR->CR, PWR_CR_FWU); 87 | } 88 | 89 | /** 90 | * @brief Disables the Fast WakeUp from Ultra Low Power mode. 91 | * @retval None 92 | */ 93 | void HAL_PWREx_DisableFastWakeUp(void) 94 | { 95 | /* Disable the fast wake up */ 96 | CLEAR_BIT(PWR->CR, PWR_CR_FWU); 97 | } 98 | 99 | /** 100 | * @brief Enables the Ultra Low Power mode 101 | * @retval None 102 | */ 103 | void HAL_PWREx_EnableUltraLowPower(void) 104 | { 105 | /* Enable the Ultra Low Power mode */ 106 | SET_BIT(PWR->CR, PWR_CR_ULP); 107 | } 108 | 109 | /** 110 | * @brief Disables the Ultra Low Power mode 111 | * @retval None 112 | */ 113 | void HAL_PWREx_DisableUltraLowPower(void) 114 | { 115 | /* Disable the Ultra Low Power mode */ 116 | CLEAR_BIT(PWR->CR, PWR_CR_ULP); 117 | } 118 | 119 | /** 120 | * @brief Enable the Low Power Run mode. 121 | * @note Low power run mode can only be entered when VCORE is in range 2. 122 | * In addition, the dynamic voltage scaling must not be used when Low 123 | * power run mode is selected. Only Stop and Sleep modes with regulator 124 | * configured in Low power mode is allowed when Low power run mode is 125 | * selected. 126 | * @note The frequency of the system clock must be decreased to not exceed the 127 | * frequency of RCC_MSIRANGE_1. 128 | * @note In Low power run mode, all I/O pins keep the same state as in Run mode. 129 | * @retval None 130 | */ 131 | void HAL_PWREx_EnableLowPowerRunMode(void) 132 | { 133 | /* Enters the Low Power Run mode */ 134 | SET_BIT(PWR->CR, PWR_CR_LPSDSR); 135 | SET_BIT(PWR->CR, PWR_CR_LPRUN); 136 | } 137 | 138 | /** 139 | * @brief Disable the Low Power Run mode. 140 | * @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that 141 | * REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode 142 | * returns HAL_TIMEOUT status). The system clock frequency can then be 143 | * increased above 2 MHz. 144 | * @retval HAL_StatusTypeDef 145 | */ 146 | HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void) 147 | { 148 | uint32_t wait_loop_index = 0U; 149 | 150 | /* Exit the Low Power Run mode */ 151 | CLEAR_BIT(PWR->CR, PWR_CR_LPRUN); 152 | CLEAR_BIT(PWR->CR, PWR_CR_LPSDSR); 153 | 154 | /* Wait until REGLPF is reset */ 155 | wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000U)); 156 | 157 | while ((wait_loop_index != 0U) && (HAL_IS_BIT_SET(PWR->CSR, PWR_CSR_REGLPF))) 158 | { 159 | wait_loop_index--; 160 | } 161 | 162 | if (HAL_IS_BIT_SET(PWR->CSR, PWR_CSR_REGLPF)) 163 | { 164 | return HAL_TIMEOUT; 165 | } 166 | 167 | return HAL_OK; 168 | } 169 | 170 | /** 171 | * @} 172 | */ 173 | 174 | /** 175 | * @} 176 | */ 177 | 178 | /** 179 | * @} 180 | */ 181 | #endif /* HAL_PWR_MODULE_ENABLED */ 182 | 183 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 184 | 185 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_wwdg.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hardwario/lora-modem/7220b7bbe391d91aa0e3a696da66c268e082c783/lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_wwdg.c -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_crc.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_ll_crc.c 4 | * @author MCD Application Team 5 | * @brief CRC LL module driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | #if defined(USE_FULL_LL_DRIVER) 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "stm32l0xx_ll_crc.h" 23 | #include "stm32l0xx_ll_bus.h" 24 | 25 | #ifdef USE_FULL_ASSERT 26 | #include "stm32_assert.h" 27 | #else 28 | #define assert_param(expr) ((void)0U) 29 | #endif 30 | 31 | /** @addtogroup STM32L0xx_LL_Driver 32 | * @{ 33 | */ 34 | 35 | #if defined (CRC) 36 | 37 | /** @addtogroup CRC_LL 38 | * @{ 39 | */ 40 | 41 | /* Private types -------------------------------------------------------------*/ 42 | /* Private variables ---------------------------------------------------------*/ 43 | /* Private constants ---------------------------------------------------------*/ 44 | /* Private macros ------------------------------------------------------------*/ 45 | /* Private function prototypes -----------------------------------------------*/ 46 | 47 | /* Exported functions --------------------------------------------------------*/ 48 | /** @addtogroup CRC_LL_Exported_Functions 49 | * @{ 50 | */ 51 | 52 | /** @addtogroup CRC_LL_EF_Init 53 | * @{ 54 | */ 55 | 56 | /** 57 | * @brief De-initialize CRC registers (Registers restored to their default values). 58 | * @param CRCx CRC Instance 59 | * @retval An ErrorStatus enumeration value: 60 | * - SUCCESS: CRC registers are de-initialized 61 | * - ERROR: CRC registers are not de-initialized 62 | */ 63 | ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx) 64 | { 65 | ErrorStatus status = SUCCESS; 66 | 67 | /* Check the parameters */ 68 | assert_param(IS_CRC_ALL_INSTANCE(CRCx)); 69 | 70 | if (CRCx == CRC) 71 | { 72 | /* Force CRC reset */ 73 | LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_CRC); 74 | 75 | /* Release CRC reset */ 76 | LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_CRC); 77 | } 78 | else 79 | { 80 | status = ERROR; 81 | } 82 | 83 | return (status); 84 | } 85 | 86 | /** 87 | * @} 88 | */ 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | #endif /* defined (CRC) */ 99 | 100 | /** 101 | * @} 102 | */ 103 | 104 | #endif /* USE_FULL_LL_DRIVER */ 105 | 106 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 107 | 108 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_crs.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_ll_crs.h 4 | * @author MCD Application Team 5 | * @brief CRS LL module driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | #if defined(USE_FULL_LL_DRIVER) 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "stm32l0xx_ll_crs.h" 23 | #include "stm32l0xx_ll_bus.h" 24 | 25 | /** @addtogroup STM32L0xx_LL_Driver 26 | * @{ 27 | */ 28 | 29 | #if defined(CRS) 30 | 31 | /** @defgroup CRS_LL CRS 32 | * @{ 33 | */ 34 | 35 | /* Private types -------------------------------------------------------------*/ 36 | /* Private variables ---------------------------------------------------------*/ 37 | /* Private constants ---------------------------------------------------------*/ 38 | /* Private macros ------------------------------------------------------------*/ 39 | /* Private function prototypes -----------------------------------------------*/ 40 | 41 | /* Exported functions --------------------------------------------------------*/ 42 | /** @addtogroup CRS_LL_Exported_Functions 43 | * @{ 44 | */ 45 | 46 | /** @addtogroup CRS_LL_EF_Init 47 | * @{ 48 | */ 49 | 50 | /** 51 | * @brief De-Initializes CRS peripheral registers to their default reset values. 52 | * @retval An ErrorStatus enumeration value: 53 | * - SUCCESS: CRS registers are de-initialized 54 | * - ERROR: not applicable 55 | */ 56 | ErrorStatus LL_CRS_DeInit(void) 57 | { 58 | LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_CRS); 59 | LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_CRS); 60 | 61 | return SUCCESS; 62 | } 63 | 64 | 65 | 66 | /** 67 | * @} 68 | */ 69 | 70 | /** 71 | * @} 72 | */ 73 | 74 | /** 75 | * @} 76 | */ 77 | 78 | #endif /* defined(CRS) */ 79 | 80 | /** 81 | * @} 82 | */ 83 | 84 | #endif /* USE_FULL_LL_DRIVER */ 85 | 86 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 87 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_ll_pwr.c 4 | * @author MCD Application Team 5 | * @brief PWR LL module driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | #if defined(USE_FULL_LL_DRIVER) 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "stm32l0xx_ll_pwr.h" 23 | #include "stm32l0xx_ll_bus.h" 24 | 25 | /** @addtogroup STM32L0xx_LL_Driver 26 | * @{ 27 | */ 28 | 29 | #if defined(PWR) 30 | 31 | /** @defgroup PWR_LL PWR 32 | * @{ 33 | */ 34 | 35 | /* Private types -------------------------------------------------------------*/ 36 | /* Private variables ---------------------------------------------------------*/ 37 | /* Private constants ---------------------------------------------------------*/ 38 | /* Private macros ------------------------------------------------------------*/ 39 | /* Private function prototypes -----------------------------------------------*/ 40 | 41 | /* Exported functions --------------------------------------------------------*/ 42 | /** @addtogroup PWR_LL_Exported_Functions 43 | * @{ 44 | */ 45 | 46 | /** @addtogroup PWR_LL_EF_Init 47 | * @{ 48 | */ 49 | 50 | /** 51 | * @brief De-initialize the PWR registers to their default reset values. 52 | * @retval An ErrorStatus enumeration value: 53 | * - SUCCESS: PWR registers are de-initialized 54 | * - ERROR: not applicable 55 | */ 56 | ErrorStatus LL_PWR_DeInit(void) 57 | { 58 | /* Force reset of PWR clock */ 59 | LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_PWR); 60 | 61 | /* Release reset of PWR clock */ 62 | LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_PWR); 63 | 64 | return SUCCESS; 65 | } 66 | 67 | /** 68 | * @} 69 | */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** 76 | * @} 77 | */ 78 | #endif /* defined(PWR) */ 79 | /** 80 | * @} 81 | */ 82 | 83 | #endif /* USE_FULL_LL_DRIVER */ 84 | 85 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 86 | -------------------------------------------------------------------------------- /lib/stm/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rng.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32l0xx_ll_rng.c 4 | * @author MCD Application Team 5 | * @brief RNG LL module driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2018 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | #if defined(USE_FULL_LL_DRIVER) 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "stm32l0xx_ll_rng.h" 23 | #include "stm32l0xx_ll_bus.h" 24 | 25 | #ifdef USE_FULL_ASSERT 26 | #include "stm32_assert.h" 27 | #else 28 | #define assert_param(expr) ((void)0U) 29 | #endif 30 | 31 | /** @addtogroup STM32L0xx_LL_Driver 32 | * @{ 33 | */ 34 | 35 | #if defined (RNG) 36 | 37 | /** @addtogroup RNG_LL 38 | * @{ 39 | */ 40 | 41 | /* Private types -------------------------------------------------------------*/ 42 | /* Private variables ---------------------------------------------------------*/ 43 | /* Private constants ---------------------------------------------------------*/ 44 | /* Private macros ------------------------------------------------------------*/ 45 | /* Private function prototypes -----------------------------------------------*/ 46 | 47 | /* Exported functions --------------------------------------------------------*/ 48 | /** @addtogroup RNG_LL_Exported_Functions 49 | * @{ 50 | */ 51 | 52 | /** @addtogroup RNG_LL_EF_Init 53 | * @{ 54 | */ 55 | 56 | /** 57 | * @brief De-initialize RNG registers (Registers restored to their default values). 58 | * @param RNGx RNG Instance 59 | * @retval An ErrorStatus enumeration value: 60 | * - SUCCESS: RNG registers are de-initialized 61 | * - ERROR: not applicable 62 | */ 63 | ErrorStatus LL_RNG_DeInit(RNG_TypeDef *RNGx) 64 | { 65 | /* Check the parameters */ 66 | assert_param(IS_RNG_ALL_INSTANCE(RNGx)); 67 | /* Enable RNG reset state */ 68 | LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_RNG); 69 | 70 | /* Release RNG from reset state */ 71 | LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_RNG); 72 | return (SUCCESS); 73 | } 74 | 75 | /** 76 | * @} 77 | */ 78 | 79 | /** 80 | * @} 81 | */ 82 | 83 | /** 84 | * @} 85 | */ 86 | 87 | #endif /* RNG */ 88 | 89 | /** 90 | * @} 91 | */ 92 | 93 | #endif /* USE_FULL_LL_DRIVER */ 94 | 95 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 96 | 97 | -------------------------------------------------------------------------------- /lib/stm/include/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.2 5 | * @date 19. April 2017 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2017 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /lib/stm/include/system_stm32l0xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32l0xx.h 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Header File. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright(c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /** @addtogroup CMSIS 21 | * @{ 22 | */ 23 | 24 | /** @addtogroup stm32l0xx_system 25 | * @{ 26 | */ 27 | 28 | /** 29 | * @brief Define to prevent recursive inclusion 30 | */ 31 | #ifndef __SYSTEM_STM32L0XX_H 32 | #define __SYSTEM_STM32L0XX_H 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** @addtogroup STM32L0xx_System_Includes 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @} 44 | */ 45 | 46 | 47 | /** @addtogroup STM32L0xx_System_Exported_types 48 | * @{ 49 | */ 50 | /* This variable is updated in three ways: 51 | 1) by calling CMSIS function SystemCoreClockUpdate() 52 | 2) by calling HAL API function HAL_RCC_GetSysClockFreq() 53 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 54 | Note: If you use this function to configure the system clock; then there 55 | is no need to call the 2 first functions listed above, since SystemCoreClock 56 | variable is updated automatically. 57 | */ 58 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 59 | /* 60 | */ 61 | extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ 62 | extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ 63 | extern const uint8_t PLLMulTable[9]; /*!< PLL multipiers table values */ 64 | 65 | 66 | /** 67 | * @} 68 | */ 69 | 70 | /** @addtogroup STM32L0xx_System_Exported_Constants 71 | * @{ 72 | */ 73 | 74 | /** 75 | * @} 76 | */ 77 | 78 | /** @addtogroup STM32L0xx_System_Exported_Macros 79 | * @{ 80 | */ 81 | 82 | /** 83 | * @} 84 | */ 85 | 86 | /** @addtogroup STM32L0xx_System_Exported_Functions 87 | * @{ 88 | */ 89 | 90 | extern void SystemInit(void); 91 | extern void SystemCoreClockUpdate(void); 92 | /** 93 | * @} 94 | */ 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif /*__SYSTEM_STM32L0XX_H */ 101 | 102 | /** 103 | * @} 104 | */ 105 | 106 | /** 107 | * @} 108 | */ 109 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 110 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | /*.egg-info 3 | /dist 4 | /build 5 | /.mypy_cache 6 | /.env 7 | -------------------------------------------------------------------------------- /python/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Jan Janak 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python library for the Murata TypeABZ LoRa modem 2 | 3 | This project provides a Python support library for working with the Murata TypeABZ LoRaWAN modem. The modem communicates with the host over an AT command interface. The Python library abstracts away the AT command interface and provides an easier-to-use high-level API. The library provides a Python module that can be embedded into a larger Python application and a command line tool called `lora` that can be used to manage the modem from the terminal. The Python module supports the original Murata Modem firmware shipped with some TypeABZ modules and the open LoRaWAN firmware from the [lora-modem](https://github.com/hardwario/lora-modem) GitHub repository. The command line tool only works with the open firmware. 4 | 5 | ## Installation 6 | You can install the library with pip from PyPI as follows: 7 | ```sh 8 | pip install --upgrade lora-modem 9 | ``` 10 | Alternatively, you can also install the library from the GitHub repository as follows: 11 | ``` 12 | git clone https://github.com/hardwario/lora-modem 13 | cd lora-modem/python 14 | pip install --editable . 15 | ``` 16 | 17 | ## Usage from Python 18 | The basic usage from a Python program looks as follows: 19 | ```python 20 | from lora import TypeABZ, OpenLoRaModem, MurataModem 21 | 22 | # Create an instance of the TypeABZ device 23 | device = TypeABZ('/dev/ttyUSB0') 24 | 25 | # Try to detect the serial port baud rate used by the device 26 | baudrate = device.detect_baud_rate() 27 | if baudrate is None: 28 | raise SystemExit('Could not detect modem baud rate') 29 | 30 | # Open the serial port and connect to the TypeABZ device 31 | device.open(baudrate) 32 | try: 33 | # Create an API instance depending on the firmware 34 | # Use MurataModem instead if your module has the original firmware 35 | modem = OpenLoRaModem(device) 36 | 37 | # Show fimware version 38 | print(modem.version) 39 | 40 | # Send an unconfirmed uplink to the default port 41 | # The message must be a bytes value, not str 42 | modem.utx(b'ping') 43 | finally: 44 | # Close the serial port 45 | device.close() 46 | ``` 47 | The class `TypeABZ` represents the physical modem device. The classes `OpenLoRaModem` and `MurataModem` then implement a particular version of the modem API. The class `OpenLoRaModem` has been designed for the open firmware from the [lora-modem](https://github.com/hardwario/lora-modem) Github. The class `MurataModem` has been designed for the original Murata Modem firmware preinstalled on some TypeABZ modules. Please refer to the documentation in `lora.py` for more information. 48 | 49 | ## Command Line Tool 50 | 51 | *Note: The command line tool only works with the open modem firmware.* 52 | 53 | The library provides a command line tool installed under the name `lora`. The tool can interact with TypeABZ LoRaWAN modems from shell scripts and the terminal. To invoke the tool, pass the pathname to the modem's serial port via the environment variable PORT or the command line option `-p`. Without any arguments, the tool displays information about the selected modem: 54 | ``` 55 | $ lora -p /dev/serial0 56 | Device information for modem /dev/serial0: 57 | +---------------------+-------------------------------------------------------------------+ 58 | | Port configuration | 19200 8N1 | 59 | | Device model | ABZ | 60 | | Firmware version | 1.1.1-43-gf86592d2 (modified) [LoRaMac-node 4.6.0-23-g50155c55] | 61 | | Data encoding | binary | 62 | | LoRaWAN version | 1.1.1 / 1.0.4 (1.0.4 for ABP) | 63 | | Regional parameters | RP002-1.0.3 | 64 | | Supported regions | AS923 AU915 CN470 CN779 EU433 EU868 IN865 KR920 RU864 US915 | 65 | | Device EUI | 323838377B308503 | 66 | +---------------------+-------------------------------------------------------------------+ 67 | Network activation information for modem /dev/serial0: 68 | +------------------+------------------+ 69 | | Network type | public | 70 | | Activation | OTAA | 71 | | Network ID | 00000013 | 72 | | Join EUI | 0101010101010101 | 73 | | Protocol version | LoRaWAN 1.1.1 | 74 | | Device address | 260C56AC | 75 | +------------------+------------------+ 76 | Current state of modem /dev/serial0: 77 | +---------------------------+-----------------------------------------------------------+ 78 | | Current region | US915 | 79 | | LoRaWAN class | A | 80 | | Channel mask | 00FF00000000000000000000 | 81 | | Data rate | SF10_125 | 82 | | Maximum message size | 11 B | 83 | | RF power index | 0 | 84 | | ADR enabled | True | 85 | | Duty cycling enabled | False | 86 | | Join duty cycling enabled | True | 87 | | Maximum EIRP | 32 dBm | 88 | | Uplink frame counter | 2 | 89 | | Downlink frame counter | 0 | 90 | | Last downlink RSSI | -105 dBm | 91 | | Last downlink SNR | -4 dB | 92 | | RX1 window | Delay: 5000 ms | 93 | | RX2 window | Delay: 6000 ms, Frequency: 923.3 MHz, Data rate: SF12_500 | 94 | | Join response windows | RX1: 5000 ms, RX2: 6000 ms | 95 | +---------------------------+-----------------------------------------------------------+ 96 | ``` 97 | To see the full list of supported commands, run `lora --help`: 98 | ``` 99 | ... 100 | Commands: 101 | device Show basic modem information. 102 | get Retrieve modem setting(s). 103 | join Perform a LoRaWAN OTAA Join. 104 | keygen Generate new random LoRaWAN security keys. 105 | keys Show current LoRaWAN security keys. 106 | link Check the radio link. 107 | network Show current network activation parameters. 108 | reboot Restart the modem. 109 | reset Reset the modem to factory defaults. 110 | set Update modem setting. 111 | state Show the current modem state. 112 | trx Transmit and receive LoRaWAN messages. 113 | ``` 114 | Run `lora --help` to see the built-in documentation for each command. 115 | 116 | ## License 117 | 118 | The library is licensed under the terms of the Revised BSD License. See [LICENSE](https://github.com/hardwario/lora-modem/blob/main/python/LICENSE) for full details. 119 | 120 | Copyright (c) 2022-2023 Jan Janak \ 121 | -------------------------------------------------------------------------------- /python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61", "setuptools-git-versioning"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.setuptools-git-versioning] 6 | enabled = true 7 | template = "{tag}" 8 | dev_template = "{tag}.{ccount}+g{sha}" 9 | dirty_template = "{tag}.{ccount}+g{sha}.modified" 10 | 11 | [project] 12 | name = "lora-modem" 13 | dynamic = ["version"] 14 | description = "Python library for the Murata TypeABZ LoRaWAN modem" 15 | authors = [ 16 | { name = "Jan Janak", email = "jan@janakj.org" } 17 | ] 18 | license = { file = "LICENSE" } 19 | readme = "README.md" 20 | keywords = ["iot", "lora", "lorawan", "lpwan", "lorawan-device", "firmware", "stm32"] 21 | classifiers = [ 22 | "Programming Language :: Python :: 3", 23 | "Environment :: Console", 24 | "License :: OSI Approved :: BSD License", 25 | "Topic :: Communications", 26 | "Topic :: Software Development :: Embedded Systems", 27 | "Topic :: System :: Networking", 28 | "Topic :: Utilities" 29 | ] 30 | requires-python = ">=3.9" 31 | dependencies = [ 32 | "click", 33 | "pymitter", 34 | "pyserial", 35 | "tabulate", 36 | "tzlocal", 37 | "python-dateutil" 38 | ] 39 | 40 | [project.optional-dependencies] 41 | dev = [ 42 | "build", 43 | "twine", 44 | "mypy", 45 | "types-pyserial", 46 | "types-python-dateutil", 47 | "types-tabulate" 48 | ] 49 | 50 | [project.urls] 51 | Homepage = "https://github.com/hardwario/lora-modem" 52 | Documentation = "https://github.com/hardwario/lora-modem/wiki" 53 | "Bug Tracker" = "https://github.com/hardwario/lora-modem/issues" 54 | 55 | [project.scripts] 56 | lora = "lora:cli" 57 | -------------------------------------------------------------------------------- /src/adc.c: -------------------------------------------------------------------------------- 1 | #include "adc.h" 2 | #include 3 | #include "log.h" 4 | 5 | #define VDDA_VREFINT_CAL ((uint32_t)3000) 6 | 7 | // Internal voltage reference, parameter VREFINT_CAL 8 | #define VREFINT_CAL ((uint16_t *)((uint32_t)0x1FF80078)) 9 | 10 | // Internal temperature sensor: constants data used for indicative values in 11 | // this example. Refer to device datasheet for min/typ/max values. 12 | 13 | // Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at a 14 | // temperature of 110 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). 15 | #define TEMP30_CAL_ADDR ((uint16_t *)((uint32_t)0x1FF8007A)) 16 | 17 | // Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at a 18 | // temperature of 30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). 19 | #define TEMP110_CAL_ADDR ((uint16_t *)((uint32_t)0x1FF8007E)) 20 | 21 | // Vdda value with which temperature sensor has been calibrated in production 22 | // (+-10 mV). 23 | #define VDDA_TEMP_CAL ((uint32_t)3000) 24 | 25 | #define COMPUTE_TEMPERATURE(TS_ADC_DATA, VDDA_APPLI) \ 26 | (((((((int32_t)((TS_ADC_DATA * VDDA_APPLI) / VDDA_TEMP_CAL) - \ 27 | (int32_t)*TEMP30_CAL_ADDR)) * (int32_t)(110 - 30)) << 8) / \ 28 | (int32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR)) + (30 << 8)) 29 | 30 | 31 | static ADC_HandleTypeDef adc = { 32 | .Init = { 33 | .OversamplingMode = DISABLE, 34 | 35 | .ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4, 36 | .LowPowerAutoPowerOff = DISABLE, 37 | .LowPowerFrequencyMode = ENABLE, 38 | .LowPowerAutoWait = DISABLE, 39 | 40 | .Resolution = ADC_RESOLUTION_12B, 41 | .SamplingTime = ADC_SAMPLETIME_160CYCLES_5, 42 | .ScanConvMode = ADC_SCAN_DIRECTION_FORWARD, 43 | .DataAlign = ADC_DATAALIGN_RIGHT, 44 | .ContinuousConvMode = DISABLE, 45 | .DiscontinuousConvMode = DISABLE, 46 | .ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE, 47 | .EOCSelection = ADC_EOC_SINGLE_CONV, 48 | .DMAContinuousRequests = DISABLE 49 | } 50 | }; 51 | 52 | 53 | void adc_init(void) 54 | { 55 | // We do not initialize ADC when the system boots up. Instead, the ADC 56 | // peripheral is initialized on first use, e.g., when the LoRa MAC attempts 57 | // to measure batter or temperature levels. 58 | } 59 | 60 | 61 | void adc_deinit(void) 62 | { 63 | if (adc.Instance != NULL) { 64 | __HAL_RCC_ADC1_CLK_ENABLE(); 65 | HAL_ADC_DeInit(&adc); 66 | adc.Instance = NULL; 67 | } 68 | __HAL_RCC_ADC1_CLK_DISABLE(); 69 | } 70 | 71 | 72 | void adc_before_stop(void) 73 | { 74 | // Disable ADC entirely before going to Stop mode 75 | if (adc.Instance != NULL) { 76 | __HAL_RCC_ADC1_CLK_ENABLE(); 77 | HAL_ADC_DeInit(&adc); 78 | adc.Instance = NULL; 79 | } 80 | } 81 | 82 | 83 | void adc_after_stop(void) 84 | { 85 | // Do nothing when waking up from Stop mode. We will instead initialize the 86 | // ADC on first use. 87 | } 88 | 89 | 90 | uint16_t adc_get_value(uint32_t channel) 91 | { 92 | HAL_StatusTypeDef rc; 93 | ADC_ChannelConfTypeDef cfg = { 0 }; 94 | 95 | __HAL_RCC_ADC1_CLK_ENABLE(); 96 | 97 | if (adc.Instance == NULL) { 98 | // This branch will execute if ADC has not been initialized yet. This 99 | // happens the first time ADC is used after boot or the first time the 100 | // ADC is used after waking up from the Stop mode. 101 | 102 | // Wait for the Vrefint to stabilize if we're waking up from Stop mode 103 | __HAL_RCC_PWR_CLK_ENABLE(); 104 | while (__HAL_PWR_GET_FLAG(PWR_FLAG_VREFINTRDY) == RESET); 105 | __HAL_RCC_PWR_CLK_DISABLE(); 106 | 107 | adc.Instance = ADC1; 108 | rc = HAL_ADC_Init(&adc); 109 | if (rc != HAL_OK) { 110 | log_error("Error while initializing ADC: %d", rc); 111 | goto error; 112 | } 113 | 114 | rc = HAL_ADCEx_Calibration_Start(&adc, ADC_SINGLE_ENDED); 115 | if (rc != HAL_OK) { 116 | log_error("Error while calibrating ADC: %d", rc); 117 | goto error; 118 | } 119 | } 120 | 121 | // Deselect all channels 122 | cfg.Channel = ADC_CHANNEL_MASK; 123 | cfg.Rank = ADC_RANK_NONE; 124 | rc = HAL_ADC_ConfigChannel(&adc, &cfg); 125 | if (rc != HAL_OK) { 126 | log_error("Error in HAL_ADC_ConfigChannel: %d", rc); 127 | goto error; 128 | } 129 | 130 | // Configure ADC channel 131 | cfg.Channel = channel; 132 | cfg.Rank = ADC_RANK_CHANNEL_NUMBER; 133 | rc = HAL_ADC_ConfigChannel(&adc, &cfg); 134 | if (rc != HAL_OK) { 135 | log_error("Error in HAL_ADC_ConfigChannel: %d", rc); 136 | goto error; 137 | } 138 | 139 | rc = HAL_ADC_Start(&adc); 140 | if (rc != HAL_OK) { 141 | log_error("Error in HAL_ADC_Start: %d", rc); 142 | goto error; 143 | } 144 | 145 | rc = HAL_ADC_PollForConversion(&adc, HAL_MAX_DELAY); 146 | if (rc != HAL_OK) { 147 | log_error("Error in HAL_ADC_PollForConversion: %d", rc); 148 | goto error2; 149 | } 150 | 151 | uint16_t v = HAL_ADC_GetValue(&adc); 152 | HAL_ADC_Stop(&adc); 153 | __HAL_RCC_ADC1_CLK_DISABLE(); 154 | return v; 155 | 156 | error2: 157 | HAL_ADC_Stop(&adc); 158 | error: 159 | if (adc.Instance != NULL) { 160 | HAL_ADC_DeInit(&adc); 161 | adc.Instance = NULL; 162 | } 163 | __HAL_RCC_ADC1_CLK_DISABLE(); 164 | return 0; 165 | } 166 | 167 | 168 | uint16_t adc_get_battery_level(void) 169 | { 170 | uint16_t v = adc_get_value(ADC_CHANNEL_VREFINT); 171 | if (v == 0) return 0; 172 | return (((uint32_t)VDDA_VREFINT_CAL * (*VREFINT_CAL)) / v); 173 | } 174 | 175 | 176 | uint16_t adc_get_temperature_level(void) 177 | { 178 | uint32_t v = adc_get_battery_level(); 179 | uint16_t t = adc_get_value(ADC_CHANNEL_TEMPSENSOR); 180 | return COMPUTE_TEMPERATURE(t, v); 181 | } 182 | 183 | 184 | float adc_get_temperature_celsius(void) 185 | { 186 | uint16_t t = adc_get_temperature_level(); 187 | uint16_t i = t >> 8; 188 | uint16_t f = ((t - (i << 8)) * 100) >> 8; 189 | float v = (float)i + (float)f / 100.f; 190 | log_debug("adc_get_temperature_celsius: %f", v); 191 | return v; 192 | } 193 | -------------------------------------------------------------------------------- /src/adc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADC_H 2 | #define _ADC_H 3 | 4 | #include 5 | 6 | //! @brief Initializes the ADC input 7 | 8 | void adc_init(void); 9 | 10 | void adc_before_stop(void); 11 | 12 | void adc_after_stop(void); 13 | 14 | //! @brief DeInitializes the ADC 15 | 16 | void adc_deinit(void); 17 | 18 | //! @brief Read the analog voltage value 19 | //! @param[in] Channel to read 20 | //! @retval value Analogue value 21 | 22 | uint16_t adc_get_value(uint32_t channel); 23 | 24 | //! @brief Get the current temperature 25 | //! @retval value temperature in degreeCelcius( q7.8 ) 26 | 27 | uint16_t adc_get_temperature_level(void); 28 | 29 | //! @brief Get the current temperature in Celsius 30 | //! @retval value temperature 31 | 32 | float adc_get_temperature_celsius(void); 33 | 34 | //! @brief Get the current battery level 35 | //! @retval value battery level ( 0: very low, 254: fully charged ) 36 | 37 | uint16_t adc_get_battery_level(void); 38 | 39 | #endif // _ADC_H 40 | -------------------------------------------------------------------------------- /src/atci.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATCI_H 2 | #define _ATCI_H 3 | 4 | #include 5 | #include 6 | #include "lpuart.h" 7 | 8 | #define ATCI_EOL "\r\n\r\n" 9 | 10 | #define ATCI_UNKNOWN_CMD "+ERR=-1" ATCI_EOL 11 | #define ATCI_UKNOWN_CMD_LEN (sizeof(ATCI_UNKNOWN_CMD) - 1) 12 | 13 | #define ATCI_OK "+OK" ATCI_EOL 14 | #define ATCI_OK_LEN (sizeof(ATCI_OK) - 1) 15 | 16 | #define ATCI_COMMANDS_LENGTH(COMMANDS) (sizeof(COMMANDS) / sizeof(COMMANDS[0])) 17 | 18 | #define ATCI_COMMAND_CLAC {"+CLAC", atci_clac_action, NULL, NULL, NULL, "List all supported AT commands"} 19 | #define ATCI_COMMAND_HELP {"$HELP", atci_help_action, NULL, NULL, NULL, "This help"} 20 | 21 | #define atci_flush lpuart_flush 22 | 23 | 24 | //! @brief AT param struct 25 | typedef struct 26 | { 27 | char *txt; 28 | size_t length; 29 | size_t offset; 30 | 31 | } atci_param_t; 32 | 33 | 34 | typedef enum 35 | { 36 | ATCI_DATA_OK = 0, 37 | ATCI_DATA_ABORTED = -1, 38 | ATCI_DATA_ENCODING_ERROR = -2 39 | } atci_data_status_t; 40 | 41 | 42 | //! @brief AT command struct 43 | typedef struct 44 | { 45 | const char *command; 46 | void (*action)(atci_param_t *param); 47 | void (*set)(atci_param_t *param); 48 | void (*read)(void); 49 | void (*help)(void); 50 | const char *hint; 51 | 52 | } atci_command_t; 53 | 54 | 55 | typedef enum 56 | { 57 | ATCI_ENCODING_BIN = 0, 58 | ATCI_ENCODING_HEX = 1 59 | } atci_encoding_t; 60 | 61 | 62 | //! @brief Initialize 63 | //! @param[in] baudrate The baudrate to configure on the UART interface 64 | //! @param[in] commands 65 | //! @param[in] length Number of commands 66 | 67 | void atci_init(unsigned int baudrate, const atci_command_t *commands, int length); 68 | 69 | 70 | //! @brief 71 | void atci_process(void); 72 | 73 | 74 | //! @brief Print message 75 | //! @param[in] message Message 76 | size_t atci_print(const char *message); 77 | 78 | 79 | //! @brief Print format message 80 | //! @param[in] format Format string (printf style) 81 | //! @param[in] ... Optional format arguments 82 | //! @return Number of bytes written 83 | size_t atci_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 84 | 85 | 86 | //! @brief Print buffer as HEX string 87 | //! @param[in] buffer Pointer to source buffer 88 | //! @param[in] length Number of bytes to be written 89 | //! @return Number of bytes written 90 | size_t atci_print_buffer_as_hex(const void *buffer, size_t length); 91 | 92 | 93 | //! @brief Write data 94 | //! @param[in] buffer Pointer to source buffer 95 | //! @param[in] length Number of bytes to be written 96 | //! @return Number of bytes written 97 | size_t atci_write(const char *buffer, size_t length); 98 | 99 | 100 | //! @brief Parse buffer from HEX string 101 | //! @param[in] param Param instance 102 | //! @param[in] buffer Pointer to destination buffer 103 | //! @param[in] length Number of bytes to be read 104 | //! @param[in] param_length Maximum number of bytes to consume from param 105 | //! @return Number of bytes read 106 | size_t atci_param_get_buffer_from_hex(atci_param_t *param, void *buffer, size_t length, size_t param_length); 107 | 108 | 109 | //! @brief Parse string to uint and move the parsing cursor forward 110 | //! @param[in] param Param instance 111 | //! @param[in] value pointer to number 112 | //! @return true On success 113 | //! @return false On failure 114 | bool atci_param_get_uint(atci_param_t *param, uint32_t *value); 115 | 116 | 117 | //! @brief Parse string to int and move the parsing cursor forward 118 | //! @param[in] param Param instance 119 | //! @param[in] value pointer to number 120 | //! @return true On success 121 | //! @return false On failure 122 | bool atci_param_get_int(atci_param_t *param, int32_t *value); 123 | 124 | 125 | //! @brief Check if the character at the cursor is a comma and move the parsing cursor forward 126 | //! @param[in] param Param instance 127 | //! @return true Is comma 128 | //! @return false No comma 129 | bool atci_param_is_comma(atci_param_t *param); 130 | 131 | 132 | //! @brief Set callback for next data 133 | bool atci_set_read_next_data(size_t length, atci_encoding_t encoding, void (*callback)(atci_data_status_t status, atci_param_t *param)); 134 | 135 | 136 | //! @brief Abort the reception of next data, e.g., on time out 137 | void atci_abort_read_next_data(void); 138 | 139 | 140 | //! @brief Helper for clac action 141 | void atci_clac_action(atci_param_t *param); 142 | 143 | //! @brief Helper for help action 144 | void atci_help_action(atci_param_t *param); 145 | 146 | #endif //_ATCI_H 147 | -------------------------------------------------------------------------------- /src/board.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | 3 | void BoardGetUniqueId( uint8_t *id ) 4 | { 5 | system_get_unique_id(id); 6 | } 7 | -------------------------------------------------------------------------------- /src/board.h: -------------------------------------------------------------------------------- 1 | #ifndef _BOARD_H 2 | #define _BOARD_H 3 | 4 | #include "system.h" 5 | 6 | // Need for /lib/loramac-node/src/peripherals/soft-se 7 | 8 | //! @brief Gets the board 64 bits unique ID 9 | 10 | void BoardGetUniqueId( uint8_t *id ); 11 | 12 | #endif // _BOARD_H 13 | -------------------------------------------------------------------------------- /src/cbuf.c: -------------------------------------------------------------------------------- 1 | #include "cbuf.h" 2 | #include 3 | 4 | 5 | static inline size_t min(size_t a, size_t b) 6 | { 7 | return a < b ? a : b; 8 | } 9 | 10 | 11 | static inline size_t space_left(volatile const cbuf_t *c) 12 | { 13 | return c->max_length - c->length; 14 | } 15 | 16 | 17 | void cbuf_init(volatile cbuf_t *c, void *buffer, size_t size) 18 | { 19 | c->buffer = buffer; 20 | c->max_length = size; 21 | c->length = 0; 22 | c->read = 0; 23 | c->write = 0; 24 | } 25 | 26 | 27 | cbuf_view_t *cbuf_tail(const volatile cbuf_t *c, cbuf_view_t *v) 28 | { 29 | size_t l = space_left(c); 30 | v->ptr[0] = c->buffer + c->write; 31 | v->len[0] = min(c->max_length - c->write, l); 32 | v->ptr[1] = c->buffer; 33 | v->len[1] = l - v->len[0]; 34 | return v; 35 | } 36 | 37 | 38 | size_t cbuf_copy_in(const cbuf_view_t *v, const void *data, size_t len) 39 | { 40 | len = min(len, v->len[0] + v->len[1]); 41 | 42 | size_t a = min(len, v->len[0]); 43 | size_t b = len - a; 44 | 45 | memcpy(v->ptr[0], data, a); 46 | memcpy(v->ptr[1], (char *)data + a, b); 47 | return a + b; 48 | } 49 | 50 | 51 | size_t cbuf_produce(volatile cbuf_t *c, size_t len) 52 | { 53 | len = min(len, space_left(c)); 54 | c->write = (c->write + len) % c->max_length; 55 | c->length += len; 56 | return len; 57 | } 58 | 59 | 60 | size_t cbuf_put(volatile cbuf_t *c, const void *data, size_t len) 61 | { 62 | cbuf_view_t t; 63 | return cbuf_produce(c, cbuf_copy_in(cbuf_tail(c, &t), data, len)); 64 | } 65 | 66 | 67 | cbuf_view_t *cbuf_head(const volatile cbuf_t *c, cbuf_view_t *h) 68 | { 69 | h->ptr[0] = c->buffer + c->read; 70 | h->len[0] = min(c->max_length - c->read, c->length); 71 | h->ptr[1] = c->buffer; 72 | h->len[1] = c->length - h->len[0]; 73 | return h; 74 | } 75 | 76 | 77 | size_t cbuf_copy_out(void *buffer, const cbuf_view_t *v, size_t max_len) 78 | { 79 | size_t len = min(max_len, v->len[0] + v->len[1]); 80 | 81 | size_t a = min(len, v->len[0]); 82 | size_t b = len - a; 83 | 84 | memcpy(buffer, v->ptr[0], a); 85 | memcpy((char *)buffer + a, v->ptr[1], b); 86 | return a + b; 87 | } 88 | 89 | 90 | size_t cbuf_consume(volatile cbuf_t *c, size_t len) 91 | { 92 | len = min(len, c->length); 93 | c->read = (c->read + len) % c->max_length; 94 | c->length -= len; 95 | return len; 96 | } 97 | 98 | 99 | size_t cbuf_get(volatile cbuf_t *c, void *buffer, size_t max_len) 100 | { 101 | cbuf_view_t h; 102 | return cbuf_consume(c, cbuf_copy_out(buffer, cbuf_head(c, &h), max_len)); 103 | } 104 | -------------------------------------------------------------------------------- /src/cmd.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMD_H 2 | #define _CMD_H 3 | 4 | #include "atci.h" 5 | 6 | 7 | enum cmd_event { 8 | CMD_EVENT_MODULE = 0, 9 | CMD_EVENT_JOIN = 1, 10 | CMD_EVENT_NETWORK = 2, 11 | CMD_EVENT_CERT = 9 12 | }; 13 | 14 | 15 | enum cmd_event_module { 16 | CMD_MODULE_BOOT = 0, 17 | CMD_MODULE_FACNEW = 1, 18 | CMD_MODULE_BOOTLOADER = 2, 19 | CMD_MODULE_HALT = 3 20 | }; 21 | 22 | 23 | enum cmd_event_join { 24 | CMD_JOIN_FAILED = 0, 25 | CMD_JOIN_SUCCEEDED = 1 26 | }; 27 | 28 | 29 | enum cmd_event_net { 30 | CMD_NET_NOANSWER = 0, 31 | CMD_NET_ANSWER = 1, 32 | CMD_NET_RETRANSMISSION = 2 33 | }; 34 | 35 | 36 | enum cmd_event_cert { 37 | CMD_CERT_CW_ENDED = 0, 38 | CMD_CERT_CM_ENDED = 1 39 | }; 40 | 41 | 42 | extern bool schedule_reset; 43 | 44 | void cmd_init(unsigned int baudrate); 45 | 46 | void cmd_event(unsigned int type, unsigned subtype); 47 | 48 | #if DETACHABLE_LPUART == 1 49 | void cmd_init_attach_pin(void); 50 | #endif 51 | 52 | #define cmd_process atci_process 53 | #define cmd_print atci_print 54 | #define cmd_printf atci_printf 55 | 56 | #endif // _CMD_H 57 | -------------------------------------------------------------------------------- /src/debug/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include "rtc.h" 7 | #include "system.h" 8 | #include "usart.h" 9 | 10 | enum log_state 11 | { 12 | LOG_STATE_SIMPLE_MSG = 0, 13 | LOG_STATE_COMPOSITE_MSG, 14 | LOG_STATE_HAVE_HEADER 15 | }; 16 | 17 | typedef struct 18 | { 19 | bool initialized; 20 | log_level_t level; 21 | log_timestamp_t timestamp; 22 | uint32_t tick_last; 23 | enum log_state state; 24 | char buffer[LOG_BUFFER_SIZE]; 25 | } log_t; 26 | 27 | 28 | static log_t _log = { .initialized = false }; 29 | 30 | 31 | void _log_init(log_level_t level, log_timestamp_t timestamp) 32 | { 33 | if (_log.initialized) return; 34 | 35 | memset(&_log, 0, sizeof(_log)); 36 | 37 | _log.level = level; 38 | _log.timestamp = timestamp; 39 | _log.initialized = true; 40 | _log.state = LOG_STATE_SIMPLE_MSG; 41 | 42 | #if DEBUG_LOG != 3 43 | usart_init(); 44 | #else 45 | SEGGER_RTT_Init(); 46 | #endif 47 | } 48 | 49 | 50 | log_level_t _log_get_level(void) 51 | { 52 | return _log.level; 53 | } 54 | 55 | 56 | void _log_set_level(log_level_t level) 57 | { 58 | _log.level = level; 59 | } 60 | 61 | 62 | static void _write(const char *buf, size_t len) 63 | { 64 | #if DEBUG_LOG != 3 65 | usart_write(buf, len); 66 | #else 67 | SEGGER_RTT_Write(0, buf, len); 68 | #endif 69 | } 70 | 71 | 72 | static void _write_message(log_level_t level, char id, const char *format, va_list ap) 73 | { 74 | #if DEBUG_LOG == 0 75 | return; 76 | #endif 77 | 78 | if (!_log.initialized) return; 79 | 80 | if (_log.level > level) return; 81 | 82 | size_t offset = 0; 83 | 84 | if (_log.state == LOG_STATE_SIMPLE_MSG || _log.state == LOG_STATE_COMPOSITE_MSG) { 85 | if (_log.timestamp == LOG_TIMESTAMP_ABS) { 86 | TimerTime_t now = rtc_tick2ms(rtc_get_timer_value()); 87 | TimerTime_t timestamp_abs = now / 10; 88 | offset = sprintf(_log.buffer, "# %lu.%02lu <%c> ", timestamp_abs / 100, timestamp_abs % 100, id); 89 | } else if (_log.timestamp == LOG_TIMESTAMP_REL) { 90 | TimerTime_t now = rtc_tick2ms(rtc_get_timer_value()); 91 | TimerTime_t timestamp_rel = (now - _log.tick_last) / 10; 92 | offset = sprintf(_log.buffer, "# +%lu.%02lu <%c> ", timestamp_rel / 100, timestamp_rel % 100, id); 93 | _log.tick_last = now; 94 | } else { 95 | strcpy(_log.buffer, "# "); 96 | _log.buffer[3] = id; 97 | offset = 6; 98 | } 99 | 100 | if (_log.state == LOG_STATE_COMPOSITE_MSG) 101 | _log.state = LOG_STATE_HAVE_HEADER; 102 | } 103 | 104 | offset += vsnprintf(&_log.buffer[offset], sizeof(_log.buffer) - offset - 1, format, ap); 105 | 106 | if (offset >= sizeof(_log.buffer)) { 107 | offset = sizeof(_log.buffer) - 3 - 3; // space for ...\r\n 108 | _log.buffer[offset++] = '.'; 109 | _log.buffer[offset++] = '.'; 110 | _log.buffer[offset++] = '.'; 111 | } 112 | 113 | if (_log.state == LOG_STATE_SIMPLE_MSG) { 114 | _log.buffer[offset++] = '\r'; 115 | _log.buffer[offset++] = '\n'; 116 | } 117 | 118 | _write(_log.buffer, offset); 119 | } 120 | 121 | 122 | void _log_dump(const void *buffer, size_t length, const char *format, ...) 123 | { 124 | size_t position; 125 | size_t offset; 126 | va_list ap; 127 | uint32_t line_size; 128 | uint32_t i; 129 | 130 | #if DEBUG_LOG == 0 131 | return; 132 | #endif 133 | 134 | if (_log.level > LOG_LEVEL_DUMP) return; 135 | 136 | va_start(ap, format); 137 | _write_message(LOG_LEVEL_DUMP, 'X', format, ap); 138 | va_end(ap); 139 | 140 | size_t offset_base = 0; 141 | 142 | for (; offset_base < sizeof(_log.buffer); offset_base++) { 143 | if (_log.buffer[offset_base] == '>') break; 144 | } 145 | 146 | offset_base += 2; 147 | 148 | if (buffer != NULL && length != 0) { 149 | for (position = 0; position < length; position += LOG_DUMP_WIDTH) { 150 | offset = offset_base + snprintf(_log.buffer + offset_base, sizeof(_log.buffer) - offset_base, "%3d: ", position); 151 | char *ptr_hex = _log.buffer + offset; 152 | offset += (LOG_DUMP_WIDTH * 3 + 2 + 1); 153 | char *ptr_text = _log.buffer + offset; 154 | offset += LOG_DUMP_WIDTH; 155 | 156 | if ((position + LOG_DUMP_WIDTH) <= length) { 157 | line_size = LOG_DUMP_WIDTH; 158 | } else { 159 | line_size = length - position; 160 | } 161 | 162 | for (i = 0; i < line_size; i++) { 163 | uint8_t value = ((uint8_t *)buffer)[position + i]; 164 | 165 | if (i == (LOG_DUMP_WIDTH / 2)) { 166 | *ptr_hex++ = '|'; 167 | *ptr_hex++ = ' '; 168 | } 169 | 170 | snprintf(ptr_hex, 4, "%02X ", value); 171 | 172 | ptr_hex += 3; 173 | 174 | if (value < 32 || value > 126) { 175 | *ptr_text++ = '.'; 176 | } else { 177 | *ptr_text++ = value; 178 | } 179 | } 180 | 181 | for (; i < LOG_DUMP_WIDTH; i++) { 182 | if (i == (LOG_DUMP_WIDTH / 2)) { 183 | *ptr_hex++ = '|'; 184 | *ptr_hex++ = ' '; 185 | } 186 | 187 | strcpy(ptr_hex, " "); 188 | 189 | ptr_hex += 3; 190 | *ptr_text++ = ' '; 191 | } 192 | 193 | _log.buffer[offset++] = '\r'; 194 | _log.buffer[offset++] = '\n'; 195 | 196 | _write(_log.buffer, offset); 197 | } 198 | } 199 | } 200 | 201 | 202 | void _log_message(log_level_t level, char id, const char *format, ...) 203 | { 204 | va_list ap; 205 | va_start(ap, format); 206 | _write_message(level, id, format, ap); 207 | va_end(ap); 208 | } 209 | 210 | 211 | void _log_finish(void) 212 | { 213 | switch(_log.state) { 214 | case LOG_STATE_SIMPLE_MSG: 215 | break; 216 | 217 | case LOG_STATE_COMPOSITE_MSG: 218 | break; 219 | 220 | case LOG_STATE_HAVE_HEADER: 221 | _write("\r\n", 2); 222 | break; 223 | 224 | default: 225 | // This is bug, do nothing 226 | break; 227 | } 228 | 229 | _log.state = LOG_STATE_SIMPLE_MSG; 230 | } 231 | 232 | 233 | void _log_compose(void) 234 | { 235 | switch(_log.state) { 236 | case LOG_STATE_SIMPLE_MSG: 237 | _log.state = LOG_STATE_COMPOSITE_MSG; 238 | break; 239 | 240 | case LOG_STATE_COMPOSITE_MSG: 241 | // do nothing 242 | break; 243 | 244 | case LOG_STATE_HAVE_HEADER: 245 | // The previous message started via log_compose hasn't been finish. 246 | // Finish it now and start a new one. 247 | _log_finish(); 248 | _log.state = LOG_STATE_COMPOSITE_MSG; 249 | break; 250 | 251 | default: 252 | // This is a bug, do nothing 253 | break; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/debug/log.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOG_H 2 | #define _LOG_H 3 | 4 | #include 5 | 6 | #ifndef LOG_BUFFER_SIZE 7 | #define LOG_BUFFER_SIZE 256 8 | #endif 9 | 10 | #define LOG_DUMP_WIDTH 8 11 | 12 | //! @brief Log level 13 | 14 | typedef enum 15 | { 16 | //! @brief Logging DUMP 17 | LOG_LEVEL_DUMP = 0, 18 | 19 | //! @brief Log level DEBUG 20 | LOG_LEVEL_DEBUG = 1, 21 | 22 | //! @brief Log level INFO 23 | LOG_LEVEL_INFO = 2, 24 | 25 | //! @brief Log level WARNING 26 | LOG_LEVEL_WARNING = 3, 27 | 28 | //! @brief Log level ERROR 29 | LOG_LEVEL_ERROR = 4, 30 | 31 | //! @brief Logging disabled 32 | LOG_LEVEL_OFF = 5 33 | 34 | } log_level_t; 35 | 36 | //! @brief Log timestamp 37 | 38 | typedef enum 39 | { 40 | //! @brief Timestamp logging disabled 41 | LOG_TIMESTAMP_OFF = -1, 42 | 43 | //! @brief Timestamp logging enabled (absolute time format) 44 | LOG_TIMESTAMP_ABS = 0, 45 | 46 | //! @brief Timestamp logging enabled (relative time format) 47 | LOG_TIMESTAMP_REL = 1 48 | 49 | } log_timestamp_t; 50 | 51 | //! @brief Initialize logging facility 52 | //! @param[in] level Minimum required message level for propagation 53 | //! @param[in] timestamp Timestamp logging setting 54 | 55 | #if DEBUG_LOG != 0 56 | 57 | void _log_init(log_level_t level, log_timestamp_t timestamp); 58 | 59 | log_level_t _log_get_level(void); 60 | 61 | void _log_set_level(log_level_t level); 62 | 63 | //! @brief Log DUMP message (annotated in log as ) 64 | //! @param[in] buffer Pointer to source buffer 65 | //! @param[in] length Number of bytes to be printed 66 | //! @param[in] format Format string (printf style) 67 | //! @param[in] ... Optional format arguments 68 | 69 | void _log_dump(const void *buffer, size_t length, const char *format, ...) __attribute__ ((format (printf, 3, 4))); 70 | 71 | void _log_message(log_level_t level, char id, const char *format, ...) __attribute__ ((format (printf, 3, 4))); 72 | 73 | //! @brief Start a log line composed via repeated calls to log_* 74 | void _log_compose(void); 75 | 76 | //! @brief Finish the log line previously started via log_compose 77 | void _log_finish(void); 78 | 79 | #define log_init(...) _log_init(__VA_ARGS__) 80 | #define log_get_level(...) _log_get_level(__VA_ARGS__) 81 | #define log_set_level(...) _log_set_level(__VA_ARGS__) 82 | #define log_dump(...) _log_dump(__VA_ARGS__) 83 | #define log_debug(...) _log_message(LOG_LEVEL_DEBUG, 'D', __VA_ARGS__) 84 | #define log_info(...) _log_message(LOG_LEVEL_INFO, 'I', __VA_ARGS__) 85 | #define log_warning(...) _log_message(LOG_LEVEL_WARNING, 'W', __VA_ARGS__) 86 | #define log_error(...) _log_message(LOG_LEVEL_ERROR, 'E', __VA_ARGS__) 87 | #define log_compose(...) _log_compose(__VA_ARGS__) 88 | #define log_finish(...) _log_finish(__VA_ARGS__) 89 | 90 | #else 91 | 92 | #define log_init(...) {} 93 | #define log_get_level(...) {} 94 | #define log_set_level(...) {} 95 | #define log_dump(...) {} 96 | #define log_debug(...) {} 97 | #define log_info(...) {} 98 | #define log_warning(...) {} 99 | #define log_error(...) {} 100 | #define log_compose(...) {} 101 | #define log_finish(...) {} 102 | 103 | #endif 104 | 105 | #endif // _LOG_H 106 | -------------------------------------------------------------------------------- /src/debug/usart.c: -------------------------------------------------------------------------------- 1 | #include "usart.h" 2 | #include 3 | #include 4 | #include "cbuf.h" 5 | #include "irq.h" 6 | #include "system.h" 7 | #include "halt.h" 8 | 9 | #if DEBUG_LOG != 3 10 | 11 | #if DEBUG_LOG == 1 12 | # define PORT USART1 13 | # define IRQn USART1_IRQn 14 | # define CLK_ENABLE __USART1_CLK_ENABLE 15 | # define PIN GPIO_PIN_9 16 | # define ALTERNATE GPIO_AF4_USART1 17 | #elif DEBUG_LOG == 2 18 | # define PORT USART2 19 | # define IRQn USART2_IRQn 20 | # define CLK_ENABLE __USART2_CLK_ENABLE 21 | # define PIN GPIO_PIN_2 22 | # define ALTERNATE GPIO_AF4_USART2 23 | #else 24 | # error Unsupported DEBUG_LOG value 25 | #endif 26 | 27 | 28 | #ifndef USART_TX_BUFFER_SIZE 29 | #define USART_TX_BUFFER_SIZE 1024 30 | #endif 31 | 32 | 33 | static char tx_buffer[USART_TX_BUFFER_SIZE]; 34 | static cbuf_t tx_fifo; 35 | 36 | 37 | void usart_init(void) 38 | { 39 | cbuf_init(&tx_fifo, tx_buffer, sizeof(tx_buffer)); 40 | uint32_t masked = disable_irq(); 41 | 42 | CLK_ENABLE(); 43 | 44 | LL_USART_InitTypeDef params = { 45 | .BaudRate = 115200, 46 | .DataWidth = LL_USART_DATAWIDTH_8B, 47 | .StopBits = LL_USART_STOPBITS_1, 48 | .Parity = LL_USART_PARITY_NONE, 49 | .TransferDirection = LL_USART_DIRECTION_TX, 50 | .HardwareFlowControl = LL_USART_HWCONTROL_NONE, 51 | .OverSampling = LL_USART_OVERSAMPLING_16 52 | }; 53 | 54 | if (LL_USART_Init(PORT, ¶ms) != 0) goto error; 55 | 56 | LL_USART_Enable(PORT); 57 | 58 | LL_USART_DisableIT_TXE(PORT); 59 | LL_USART_EnableIT_TC(PORT); 60 | 61 | // Configure interrupts 62 | HAL_NVIC_SetPriority(IRQn, 0, 0); 63 | HAL_NVIC_EnableIRQ(IRQn); 64 | 65 | // Configure GPIO 66 | __GPIOA_CLK_ENABLE(); 67 | __GPIOA_CLK_ENABLE(); 68 | 69 | GPIO_InitTypeDef gpio = { 70 | .Pin = PIN, 71 | .Mode = GPIO_MODE_AF_PP, 72 | .Pull = GPIO_NOPULL, 73 | .Speed = GPIO_SPEED_HIGH, 74 | .Alternate = ALTERNATE 75 | }; 76 | 77 | HAL_GPIO_Init(GPIOA, &gpio); 78 | 79 | reenable_irq(masked); 80 | return; 81 | error: 82 | reenable_irq(masked); 83 | halt("Error while initializing USART port"); 84 | } 85 | 86 | 87 | size_t usart_write(const char *buffer, size_t length) 88 | { 89 | cbuf_view_t v; 90 | uint32_t masked = disable_irq(); 91 | cbuf_tail(&tx_fifo, &v); 92 | reenable_irq(masked); 93 | 94 | size_t stored = cbuf_copy_in(&v, buffer, length); 95 | 96 | system_wait_hsi(); 97 | 98 | masked = disable_irq(); 99 | cbuf_produce(&tx_fifo, stored); 100 | 101 | // Enable the transmission buffer empty interrupt, which will pick up the 102 | // data written by the FIFO using the above code and starts transmitting it. 103 | if (!LL_USART_IsEnabledIT_TXE(PORT)) { 104 | system_stop_lock |= SYSTEM_MODULE_USART; 105 | LL_USART_EnableIT_TXE(PORT); 106 | } 107 | 108 | reenable_irq(masked); 109 | return stored; 110 | } 111 | 112 | 113 | #if DEBUG_LOG == 1 114 | void USART1_IRQHandler(void) 115 | #elif DEBUG_LOG == 2 116 | void USART2_IRQHandler(void) 117 | #else 118 | #error Unsupport DEBUG_LOG 119 | #endif 120 | { 121 | uint8_t c; 122 | 123 | if (LL_USART_IsEnabledIT_TXE(PORT) && LL_USART_IsActiveFlag_TXE(PORT)) { 124 | if (cbuf_get(&tx_fifo, &c, 1) != 0) { 125 | LL_USART_TransmitData8(PORT, c); 126 | } else { 127 | LL_USART_DisableIT_TXE(PORT); 128 | } 129 | } 130 | 131 | if (LL_USART_IsActiveFlag_TC(PORT)) { 132 | LL_USART_ClearFlag_TC(PORT); 133 | system_stop_lock &= ~SYSTEM_MODULE_USART; 134 | } 135 | } 136 | 137 | #endif -------------------------------------------------------------------------------- /src/debug/usart.h: -------------------------------------------------------------------------------- 1 | #ifndef __USART_H__ 2 | #define __USART_H__ 3 | #if DEBUG_LOG != 3 4 | 5 | #include 6 | 7 | //! @brief Init usart 8 | 9 | void usart_init(void); 10 | 11 | //! @brief Write data to usart 12 | //! @param[in] buffer Pointer to source buffer 13 | //! @param[in] length Number of bytes to be written 14 | //! @return Number of bytes written 15 | 16 | size_t usart_write(const char *buffer, size_t length); 17 | 18 | #endif 19 | #endif /* __USART_H__ */ 20 | -------------------------------------------------------------------------------- /src/delay.h: -------------------------------------------------------------------------------- 1 | #ifndef _DELAY_H 2 | #define _DELAY_H 3 | 4 | #include "rtc.h" 5 | 6 | //! @brief Blocking delay of "s" seconds 7 | 8 | #define Delay(s) rtc_delay_ms(ms * 1000); 9 | 10 | //! @brief Blocking delay of "ms" milliseconds 11 | 12 | #ifndef DelayMs 13 | #define DelayMs(ms) rtc_delay_ms(ms) 14 | #endif 15 | 16 | #endif // _DELAY_H -------------------------------------------------------------------------------- /src/eeprom.c: -------------------------------------------------------------------------------- 1 | #include "eeprom.h" 2 | #include 3 | #include 4 | #include 5 | #include "irq.h" 6 | 7 | #define _EEPROM_BASE DATA_EEPROM_BASE 8 | #define _EEPROM_END DATA_EEPROM_BANK2_END 9 | #define _EEPROM_IS_BUSY() ((FLASH->SR & FLASH_SR_BSY) != 0UL) 10 | 11 | static bool _eeprom_is_busy(TimerTime_t timeout); 12 | static void _eeprom_unlock(void); 13 | static void _eeprom_lock(void); 14 | static bool _eeprom_write(uint32_t address, size_t *i, uint8_t *buffer, size_t length); 15 | 16 | bool eeprom_write(uint32_t address, const void *buffer, size_t length) 17 | { 18 | // Add EEPROM base offset to address 19 | address += _EEPROM_BASE; 20 | 21 | // If user attempts to write outside EEPROM area... 22 | if ((address + length) > (_EEPROM_END + 1)) 23 | { 24 | // Indicate failure 25 | return false; 26 | } 27 | 28 | if (_eeprom_is_busy(50)) 29 | { 30 | return false; 31 | } 32 | 33 | _eeprom_unlock(); 34 | 35 | size_t i = 0; 36 | 37 | while (i < length) 38 | { 39 | _eeprom_write(address, &i, (uint8_t *) buffer, length); 40 | } 41 | 42 | _eeprom_lock(); 43 | 44 | // If we do not read what we wrote... 45 | if (memcmp(buffer, (void *) address, length) != 0UL) 46 | { 47 | // Indicate failure 48 | return false; 49 | } 50 | 51 | // Indicate success 52 | return true; 53 | } 54 | 55 | const void *eeprom_mmap(uint32_t address, size_t length) 56 | { 57 | // Add EEPROM base offset to address 58 | address += _EEPROM_BASE; 59 | 60 | // If user attempts to read outside of EEPROM boundary... 61 | if ((address + length) > (_EEPROM_END + 1)) 62 | { 63 | // Indicate failure 64 | return NULL; 65 | } 66 | 67 | return (const void *)address; 68 | } 69 | 70 | bool eeprom_read(uint32_t address, void *buffer, size_t length) 71 | { 72 | const void *mem = eeprom_mmap(address, length); 73 | if (mem == NULL) 74 | { 75 | // Indicate failure 76 | return false; 77 | } 78 | 79 | // Read from EEPROM memory to buffer 80 | memcpy(buffer, mem, length); 81 | 82 | // Indicate success 83 | return true; 84 | } 85 | 86 | 87 | size_t eeprom_get_size(void) 88 | { 89 | // Return EEPROM memory size 90 | return _EEPROM_END - _EEPROM_BASE + 1; 91 | } 92 | 93 | static bool _eeprom_is_busy(TimerTime_t timeout) 94 | { 95 | timeout += TimerGetCurrentTime(); 96 | 97 | while (_EEPROM_IS_BUSY()) 98 | { 99 | if (timeout > TimerGetCurrentTime()) 100 | { 101 | return true; 102 | } 103 | } 104 | 105 | return false; 106 | } 107 | 108 | static void _eeprom_unlock(void) 109 | { 110 | uint32_t masked = disable_irq(); 111 | 112 | // Unlock FLASH_PECR register 113 | if ((FLASH->PECR & FLASH_PECR_PELOCK) != 0) 114 | { 115 | FLASH->PEKEYR = FLASH_PEKEY1; 116 | FLASH->PEKEYR = FLASH_PEKEY2; 117 | } 118 | 119 | reenable_irq(masked); 120 | } 121 | 122 | static void _eeprom_lock(void) 123 | { 124 | uint32_t masked = disable_irq(); 125 | 126 | // Lock FLASH_PECR register 127 | FLASH->PECR |= FLASH_PECR_PELOCK; 128 | 129 | reenable_irq(masked); 130 | } 131 | 132 | static bool _eeprom_write(uint32_t address, size_t *i, uint8_t *buffer, size_t length) 133 | { 134 | uint32_t addr = address + *i; 135 | 136 | uint8_t mod = addr % 4; 137 | 138 | bool write = false; 139 | 140 | if (mod == 0) 141 | { 142 | if (*i + 4 > length) 143 | { 144 | mod = (addr % 2) + 2; 145 | } 146 | } 147 | 148 | if (mod == 2) 149 | { 150 | if (*i + 2 > length) 151 | { 152 | mod = 1; 153 | } 154 | } 155 | 156 | if (mod == 0) 157 | { 158 | uint32_t value = ((uint32_t) buffer[*i + 3]) << 24 | ((uint32_t) buffer[*i + 2]) << 16 | ((uint32_t) buffer[*i + 1]) << 8 | buffer[*i]; 159 | 160 | if (*((uint32_t *) addr) != value) 161 | { 162 | *((uint32_t *) addr) = value; 163 | 164 | write = true; 165 | } 166 | 167 | *i += 4; 168 | } 169 | else if (mod == 2) 170 | { 171 | uint16_t value = ((uint16_t) buffer[*i + 1]) << 8 | (uint16_t) buffer[*i]; 172 | 173 | if (*((uint16_t *) addr) != value) 174 | { 175 | *((uint16_t *) addr) = value; 176 | 177 | write = true; 178 | } 179 | 180 | *i += 2; 181 | } 182 | else 183 | { 184 | uint8_t value = buffer[*i]; 185 | 186 | if (*((uint8_t *) addr) != value) 187 | { 188 | *((uint8_t *) addr) = value; 189 | 190 | write = true; 191 | } 192 | 193 | *i += 1; 194 | } 195 | 196 | while (_EEPROM_IS_BUSY()) 197 | { 198 | continue; 199 | } 200 | 201 | return write; 202 | } 203 | 204 | -------------------------------------------------------------------------------- /src/eeprom.h: -------------------------------------------------------------------------------- 1 | #ifndef _EEPROM_H 2 | #define _EEPROM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | //! @brief Write buffer to EEPROM area and verify it 9 | //! @param[in] address EEPROM start address (starts at 0) 10 | //! @param[in] buffer Pointer to source buffer 11 | //! @param[in] length Number of bytes to be written 12 | //! @return true On success 13 | //! @return false On failure 14 | 15 | bool eeprom_write(uint32_t address, const void *buffer, size_t length); 16 | 17 | //! @brief Read buffer from EEPROM area 18 | //! @param[in] address EEPROM start address (starts at 0) 19 | //! @param[out] buffer Pointer to destination buffer 20 | //! @param[in] length Number of bytes to be read 21 | //! @return true On success 22 | //! @return false On failure 23 | 24 | bool eeprom_read(uint32_t address, void *buffer, size_t length); 25 | 26 | 27 | //! @brief Return memory pointer for given EEPROM address 28 | //! @param[in] address EEPROM start address (starts at 0) 29 | //! @param[in] length Number of bytes to be read 30 | //! @return Pointer to corresponding memory address 31 | //! @return NULL On failure 32 | 33 | const void *eeprom_mmap(uint32_t address, size_t length); 34 | 35 | 36 | //! @brief Return size of EEPROM area 37 | //! @return Size of EEPROM area in bytes 38 | 39 | size_t eeprom_get_size(void); 40 | 41 | #endif // _EEPROM_H 42 | -------------------------------------------------------------------------------- /src/gpio.c: -------------------------------------------------------------------------------- 1 | #include "gpio.h" 2 | 3 | static gpio_irq_handler_t *_gpio_irq[16] = {NULL}; 4 | static uint8_t HW_GPIO_Getbit_pos(uint16_t pin); 5 | 6 | void gpio_init(GPIO_TypeDef *port, uint16_t pin, GPIO_InitTypeDef *init_struct) 7 | { 8 | 9 | switch ((uint32_t) port) 10 | { 11 | case GPIOA_BASE: 12 | __HAL_RCC_GPIOA_CLK_ENABLE(); 13 | break; 14 | case GPIOB_BASE: 15 | __HAL_RCC_GPIOB_CLK_ENABLE(); 16 | break; 17 | case GPIOC_BASE: 18 | __HAL_RCC_GPIOC_CLK_ENABLE(); 19 | break; 20 | case GPIOD_BASE: 21 | __HAL_RCC_GPIOD_CLK_ENABLE(); 22 | break; 23 | case GPIOH_BASE: 24 | default: 25 | __HAL_RCC_GPIOH_CLK_ENABLE(); 26 | } 27 | 28 | init_struct->Pin = pin; 29 | 30 | HAL_GPIO_Init(port, init_struct); 31 | } 32 | 33 | void gpio_set_irq(GPIO_TypeDef *port, uint16_t pin, uint32_t prio, gpio_irq_handler_t *irqHandler) 34 | { 35 | (void) port; 36 | IRQn_Type irq_nb; 37 | 38 | uint32_t bit_pos = HW_GPIO_Getbit_pos(pin); 39 | 40 | if (irqHandler != NULL) 41 | { 42 | _gpio_irq[bit_pos] = irqHandler; 43 | 44 | switch (pin) 45 | { 46 | case GPIO_PIN_0: 47 | case GPIO_PIN_1: 48 | irq_nb = EXTI0_1_IRQn; 49 | break; 50 | case GPIO_PIN_2: 51 | case GPIO_PIN_3: 52 | irq_nb = EXTI2_3_IRQn; 53 | break; 54 | case GPIO_PIN_4: 55 | case GPIO_PIN_5: 56 | case GPIO_PIN_6: 57 | case GPIO_PIN_7: 58 | case GPIO_PIN_8: 59 | case GPIO_PIN_9: 60 | case GPIO_PIN_10: 61 | case GPIO_PIN_11: 62 | case GPIO_PIN_12: 63 | case GPIO_PIN_13: 64 | case GPIO_PIN_14: 65 | case GPIO_PIN_15: 66 | default: 67 | irq_nb = EXTI4_15_IRQn; 68 | } 69 | 70 | HAL_NVIC_SetPriority(irq_nb, prio, 0); 71 | 72 | HAL_NVIC_EnableIRQ(irq_nb); 73 | } 74 | else 75 | { 76 | _gpio_irq[bit_pos] = NULL; 77 | } 78 | } 79 | 80 | void gpio_hal_msp_irq_handler(uint16_t pin) 81 | { 82 | uint32_t bit_pos = HW_GPIO_Getbit_pos(pin); 83 | 84 | if (_gpio_irq[bit_pos] != NULL) 85 | { 86 | _gpio_irq[bit_pos](NULL); 87 | } 88 | } 89 | 90 | void gpio_write(GPIO_TypeDef *port, uint16_t pin, uint32_t value) 91 | { 92 | HAL_GPIO_WritePin(port, pin, (GPIO_PinState)value); 93 | } 94 | 95 | uint32_t gpio_read(GPIO_TypeDef *port, uint16_t pin) 96 | { 97 | return HAL_GPIO_ReadPin(port, pin); 98 | } 99 | 100 | static uint8_t HW_GPIO_Getbit_pos(uint16_t pin) 101 | { 102 | uint8_t pin_pos = 0; 103 | 104 | if ((pin & 0xFF00) != 0) 105 | { 106 | pin_pos |= 0x8; 107 | } 108 | if ((pin & 0xF0F0) != 0) 109 | { 110 | pin_pos |= 0x4; 111 | } 112 | if ((pin & 0xCCCC) != 0) 113 | { 114 | pin_pos |= 0x2; 115 | } 116 | if ((pin & 0xAAAA) != 0) 117 | { 118 | pin_pos |= 0x1; 119 | } 120 | 121 | return pin_pos; 122 | } 123 | 124 | void EXTI0_1_IRQHandler(void) 125 | { 126 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); 127 | 128 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); 129 | } 130 | 131 | void EXTI2_3_IRQHandler(void) 132 | { 133 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); 134 | 135 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); 136 | } 137 | 138 | void EXTI4_15_IRQHandler(void) 139 | { 140 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); 141 | 142 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); 143 | 144 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); 145 | 146 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); 147 | 148 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); 149 | 150 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); 151 | 152 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); 153 | 154 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); 155 | 156 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); 157 | 158 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); 159 | 160 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); 161 | 162 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); 163 | } 164 | 165 | 166 | void GpioWrite(Gpio_t *obj, uint32_t value) 167 | { 168 | gpio_write(obj->port, obj->pinIndex, value); 169 | } 170 | -------------------------------------------------------------------------------- /src/gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef _HW_GPIO_H 2 | #define _HW_GPIO_H 3 | 4 | #include 5 | 6 | 7 | typedef void(gpio_irq_handler_t)(void *context); 8 | 9 | //! @brief Initializes the given GPIO object 10 | //! @param [IN] port where x can be (A..E and H) 11 | //! @param [IN] pin specifies the port bit to be written. 12 | //! @param [IN] init_struct GPIO_InitTypeDef intit structure 13 | 14 | void gpio_init(GPIO_TypeDef *port, uint16_t pin, GPIO_InitTypeDef *init_struct); 15 | 16 | //! @brief Records the interrupt handler for the GPIO object 17 | //! @param [IN] port where x can be (A..E and H) 18 | //! @param [IN] pin specifies the port bit to be written. 19 | //! @param [IN] prio NVIC priority (0 is highest) 20 | //! @param [IN] irqHandler points to the function to execute 21 | 22 | void gpio_set_irq(GPIO_TypeDef *port, uint16_t pin, uint32_t prio, gpio_irq_handler_t *irqHandler); 23 | 24 | //! @brief Writes the given value to the GPIO output 25 | //! @param [IN] pin specifies the port bit to be written 26 | //! @param [IN] value New GPIO output value 27 | 28 | void gpio_write(GPIO_TypeDef *port, uint16_t pin, uint32_t value); 29 | 30 | //! @brief Reads the current GPIO input value 31 | //! @param [IN] port where x can be (A..E and H) 32 | //! @param [IN] pin specifies the port bit to be read 33 | //! @retval value Current GPIO input value 34 | 35 | uint32_t gpio_read(GPIO_TypeDef *port, uint16_t pin); 36 | 37 | //! @brief Execute the interrupt from the object 38 | //! @param [IN] port where x can be (A..E and H) 39 | //! @param [IN] pin specifies the port bit to set the irq handler for 40 | 41 | void gpio_hal_msp_irq_handler(uint16_t pin); 42 | 43 | 44 | // The following function is a wrapper for LoRaMac-node 45 | 46 | typedef struct 47 | { 48 | GPIO_TypeDef *port; 49 | uint16_t pinIndex; 50 | } Gpio_t; 51 | 52 | 53 | void GpioWrite(Gpio_t *obj, uint32_t value); 54 | 55 | #endif // _HW_GPIO_H 56 | 57 | -------------------------------------------------------------------------------- /src/halt.c: -------------------------------------------------------------------------------- 1 | #include "halt.h" 2 | #include 3 | #include "lpuart.h" 4 | #include "log.h" 5 | #include "system.h" 6 | #include "cmd.h" 7 | #include "irq.h" 8 | 9 | 10 | __attribute__((noreturn)) void halt(const char *msg) 11 | { 12 | #if DEBUG_LOG != 0 13 | const char prefix[] = "Halted"; 14 | #endif 15 | cmd_event(CMD_EVENT_MODULE, CMD_MODULE_HALT); 16 | 17 | if (msg == NULL) { 18 | log_error(prefix); 19 | } else { 20 | log_error("%s: %s\r\n", prefix, msg); 21 | } 22 | 23 | lpuart_flush(); 24 | 25 | disable_irq(); 26 | 27 | // Make sure we can enter the low-power Stop mode 28 | system_sleep_lock = 0; 29 | system_stop_lock = 0; 30 | 31 | // Mask all EXTI interrupts and events to ensure we're not woken up. The 32 | // only way of recovering from a halt should be via the external reset pin. 33 | // This is to ensure that the LoRa modem doesn't drain the device's battery 34 | // while being halted due to an irrecoverable error. 35 | EXTI->IMR = LL_EXTI_LINE_NONE; 36 | EXTI->EMR = LL_EXTI_LINE_NONE; 37 | 38 | // Hopefully, we can enter the low-power Stop mode now. Note that if there 39 | // are any pending interrupts, the MCU will not enter Sleep or Stop modes 40 | // and the loop below will keep spinning. We have tried preventing that by 41 | // masking all EXTI interrupts and events above. 42 | for(;;) system_idle(); 43 | } 44 | -------------------------------------------------------------------------------- /src/halt.h: -------------------------------------------------------------------------------- 1 | #ifndef _HALT_H 2 | #define _HALT_H 3 | 4 | void halt(const char *msg) __attribute__ ((noreturn)); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef __IRQ_H__ 2 | #define __IRQ_H__ 3 | 4 | #include 5 | 6 | 7 | __STATIC_FORCEINLINE uint32_t disable_irq(void) 8 | { 9 | uint32_t mask = __get_PRIMASK(); 10 | __disable_irq(); 11 | return mask; 12 | } 13 | 14 | 15 | __STATIC_FORCEINLINE void reenable_irq(uint32_t mask) 16 | { 17 | __set_PRIMASK(mask); 18 | } 19 | 20 | 21 | __STATIC_FORCEINLINE void enable_irq(void) 22 | { 23 | __enable_irq(); 24 | } 25 | 26 | 27 | #endif // __IRQ_H__ -------------------------------------------------------------------------------- /src/lpuart.h: -------------------------------------------------------------------------------- 1 | #ifndef __LPUART_H__ 2 | #define __LPUART_H__ 3 | 4 | #include 5 | #include 6 | #include "cbuf.h" 7 | #include "gpio.h" 8 | 9 | 10 | extern volatile cbuf_t lpuart_tx_fifo; 11 | extern volatile cbuf_t lpuart_rx_fifo; 12 | 13 | #if DETACHABLE_LPUART == 1 14 | 15 | /*! @brief Detach from the ATCI LPUART port 16 | * 17 | * Detach (disconnect) from the LPUART port used by the AT command interface. 18 | * Detaching pauses active DMA transfer (if any) and reconfigures the GPIO ports 19 | * used by the LPUART port in analog mode. 20 | * 21 | * This function is intended for use on boards that share the LPUART lines with 22 | * some other peripheral. This is the case, e.g., on MKRWAN boards. Forcing the 23 | * modem to detach allows the host to use the lines to communicate temporarily 24 | * with the other peripheral. 25 | */ 26 | void lpuart_detach(void); 27 | 28 | /*! @brief Attach the ATCI LPUART port 29 | * 30 | * Attach to the LPUART port used by the AT command interface. Calling this 31 | * function reconfigures the GPIO ports used by LPUART1, and if there is an 32 | * active DMA transfer, it is resumed. 33 | * 34 | * This function is intended to restore ATCI functionality after the modem has 35 | * detached from LPUART1 (used by the ATCI). The function should be invoked 36 | * after an interrupt on a preconfigured GPIO pin or timeout. 37 | */ 38 | void lpuart_attach(void); 39 | 40 | #endif 41 | 42 | /*! @brief Initialize LPUART1 43 | * 44 | * Initialize the LPUART1 port for buffered DMA-based I/O. Both transmission and 45 | * reception will use DMA. Two fixed-size FIFOs backed by circular buffers are 46 | * used to enqueue outgoing and incoming data. 47 | * 48 | * @param[in] baudrate The baudrate to be configured 49 | */ 50 | void lpuart_init(unsigned int baudrate); 51 | 52 | 53 | /*! @brief Write up to @p bytes to LPUART1 54 | * 55 | * Schedule up to @p length bytes of data from @p buffer for transmission over 56 | * LPUART1. The data is copied into an internal queue and will be transmitted as 57 | * soon as possible. If there is not enough space to store @p length bytes in 58 | * the internal queue, the function enqueues as many bytes as possible. 59 | * 60 | * This is a non-blocking function. 61 | * 62 | * @param[in] buffer A pointer to a memory buffer with data to be sent 63 | * @param[in] length The number of bytes from @p buffer to be sent 64 | * @return Number of bytes from @p buffer enqueued (less than or equal to @p length ) 65 | */ 66 | size_t lpuart_write(const char *buffer, size_t length); 67 | 68 | 69 | /*! @brief Write @p bytes to LPUART1 70 | * 71 | * Schedule @p length bytes of data from @p buffer for transmission over 72 | * LPUART1. This is a blocking version of lpuart_write. This function blocks 73 | * until all data have been written into the internal memory queue. 74 | * 75 | * Note: If you want to wait until all data have been transmitted over the port, 76 | * invoke lpuart_flush after this function. 77 | * 78 | * @param[in] buffer A pointer to a memory buffer with data to be sent 79 | * @param[in] length The number of bytes from @p buffer to be sent 80 | */ 81 | void lpuart_write_blocking(const char *buffer, size_t length); 82 | 83 | 84 | /*! @brief Read up to @p length bytes from LPUART1 85 | * 86 | * This function reads up to @p length bytes from the LPUART1 port and copies 87 | * the data into the destination buffer @p buffer . If there is not enough data 88 | * in the internal queue, the function will read fewer than @p length bytes. 89 | * Number of bytes read is returned. 90 | * 91 | * This is a non-blocking function. 92 | * 93 | * @param[in] buffer A pointer to the destination buffer 94 | * @param[in] length The maximum number of bytes to read 95 | * @return The number of bytes read (less than or equal to @p length ) 96 | */ 97 | size_t lpuart_read(char *buffer, size_t length); 98 | 99 | 100 | /*! @brief Wait for all data from the internal queue to be sent 101 | * 102 | * This function blocks until all data from the internal queue have been 103 | * transmitted. 104 | */ 105 | void lpuart_flush(void); 106 | 107 | 108 | /*! @brief Pause DMA and enable the WKUP interrupt on LPUART1 109 | * 110 | * This function is meant to be invoked by the system before it enters the Stop 111 | * low-power mode. In this mode, DMA is paused, but its registers are retained. 112 | * To be able to receive data in Stop mode, we pause DMA and enable the WKUP 113 | * interrupt, which will wake the MCU once a start bit has been detected on the 114 | * line. 115 | */ 116 | void lpuart_before_stop(void); 117 | 118 | 119 | /*! @brief Disable WKUP interrupt and resume DMA on LPUART1 120 | * 121 | * This function is meant to be invoked after the system has left the low-power 122 | * Stop mode. It disables the WKUP interrupt on LPUART1 and resumes DMA-based 123 | * receive operation. This function can only be used with low-power modes that 124 | * retain DMA register values, e.g., the Stop mode. 125 | */ 126 | void lpuart_after_stop(void); 127 | 128 | 129 | /*! @brief Pause modem->host transmissions over LPUART1 130 | * 131 | * Calling this function pauses modem->host transmissions over LPUART1 until 132 | * lpuart_resume_tx is called again. Previous and existing data will still 133 | * finish transmitting, but any data written to the port after calling this 134 | * function will only be written into an internal buffer. The data will begin 135 | * transmitting after the next call to lpuart_resume_tx. 136 | * 137 | * This function allows the implementation of a polling mode of communication, 138 | * where the host polls the modem for asynchronous messages. This is useful, 139 | * e.g., if the host needs to save power by shutting down its UART peripheral 140 | * between interactions with the modem over the ATCI. 141 | */ 142 | void lpuart_pause_tx(); 143 | 144 | 145 | /*! @brief Resume modem->host transmissions over LPUART1 146 | * 147 | * Invoke this function to resume modem->host transmissions over LPUART1 after 148 | * calling lpuart_pause_tx(). All data stored in the internal transmission 149 | * buffer will be transmitted over the UART port. 150 | */ 151 | void lpuart_resume_tx(); 152 | 153 | #endif /* __LPUART_H__ */ 154 | -------------------------------------------------------------------------------- /src/lrw.h: -------------------------------------------------------------------------------- 1 | #ifndef _LRW_H 2 | #define _LRW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "part.h" 8 | 9 | 10 | extern unsigned int lrw_event_subtype; 11 | extern TimerTime_t lrw_dutycycle_deadline; 12 | 13 | /** @brief Initialize the LoRaMac stack 14 | * 15 | * If a previously saved state is found in NVM, the state will be restored and 16 | * LoRaMac will continue where it left off. Otherwise, LoRaMac is initialized 17 | * with default parameter values. 18 | */ 19 | void lrw_init(void); 20 | 21 | 22 | /** @brief Obtain a pointer to the internal LoRaMac state 23 | * 24 | * Use this function to obtain a pointer to the internal state of the LoRaMac 25 | * library. This could be used to get or set parameters that have not been 26 | * exposed through LoRaMac's MIB API. 27 | * 28 | * @return A pointer to LoRaMac's internal state 29 | */ 30 | LoRaMacNvmData_t *lrw_get_state(void); 31 | 32 | 33 | /** @brief LoRaMac main processing function. It should be invoked repeatedly as 34 | * long as the system is not sleeping. 35 | */ 36 | void lrw_process(void); 37 | 38 | 39 | /** @brief Send an uplink message 40 | * 41 | * This function can be used to send a confirmed or unconfirmed uplink message 42 | * to the specified LoRaWAN port number (1-223). Set the parameter @c confirmed 43 | * to true to request an ACK from the network. Note that the maximum size of the 44 | * message can vary considerably and depends on the currently selected data rate. 45 | * 46 | * @param[in] port LoRaWAN port number 47 | * @param[in] buffer Pointer to source buffer 48 | * @param[in] length Number of bytes in the source buffer 49 | * @param[in] confirmed Send as confirmed uplink when true 50 | * @return Zero on success, a @c LoRaMacStatus_t value on error 51 | */ 52 | int lrw_send(uint8_t port, void *buffer, uint8_t length, bool confirmed); 53 | 54 | 55 | /** @brief Activate the node according to the mode selected with AT+MODE 56 | * 57 | * This activates the node on the network according to the mode previously 58 | * selected with AT+MODE. If the selected mode is OTAA, a Join message will be 59 | * sent to the LoRaWAN network server. If the selected mode is ABP, this 60 | * function will only perform internal re-configuration of the LoRaMac stack for 61 | * ABP. No messages will be sent to the network in this case. 62 | * 63 | * @param[in] datarate Data rate to be used for OTAA Join (0-15) 64 | * @param[in] tries Total number of transmissions (0 for ABP, 1-16 for OTAA) 65 | * @return Zero on success, a @c LoRaMacState_t value on error 66 | */ 67 | int lrw_join(uint8_t datarate, uint8_t tries); 68 | 69 | 70 | /** @brief Perform a LoRaWAN link check 71 | * 72 | * This function sends a LoRaWAN @c LinkCheckReq message to the network server. 73 | * The server will return a @c LinkCheckAns back with the measured RSSI and SNR 74 | * values for the device. This function does not wait (block) for the answer. 75 | * 76 | * If the parameter @c piggyback is set to @c true, the @c LinkCheckReq request 77 | * will be sent together with the next uplink message sent by the client. Set 78 | * the parameter to @c false to send the request immediately. In that case, it 79 | * will be sent with an empty payload to port 0. 80 | 81 | * @param[in] piggyback Send with next uplink if @c true, send immediately otherwise 82 | * @return Zero on success, a @c LoRaMacStatus_t value on error 83 | */ 84 | int lrw_check_link(bool piggyback); 85 | 86 | 87 | /** @brief Reconfigure LoRaMac for the given region 88 | * 89 | * This function reconfigures the LoRaMac library for the specified region. The 90 | * region must be active, i.e., the corresponding regional files must have been 91 | * included at compile time. 92 | * 93 | * This function will internally shutdown the LoRaMac library and perform a 94 | * factory reset of most of the persistent state stored in NVM in order to apply 95 | * new regional defaults. The application needs to invoke lrw_init() to 96 | * reactivate the stack upon invoking this function. System reboot is also 97 | * recommended. 98 | * 99 | * @param[in] region LoRaWAN region identifier 100 | * @return 0 on success, -1 if the region is already active, a @c LoRaMacState_t 101 | * value on error 102 | */ 103 | int lrw_set_region(unsigned int region); 104 | 105 | 106 | /** @brief Return currently selected LoRaWAN activation mode (ABP or OTAA) 107 | * @retval 0 Activation by provisioning (ABP) mode is selected 108 | * @retval 1 Over-the-air activation (OTAA) mode is selected 109 | */ 110 | unsigned int lrw_get_mode(void); 111 | 112 | 113 | /** @brief Select LoRaWAN activation mode (ABP or OTAA) 114 | * 115 | * Configure the LoRaMac library to use the specified activation mode. The value 116 | * 0 selects activation by personalization (ABP). The value 1 selects over the 117 | * air activation (OTAA). 118 | * 119 | * @return Zero on success, a @c LoRaMacStatus_t value on error 120 | */ 121 | int lrw_set_mode(unsigned int mode); 122 | 123 | 124 | /** @brief Return current LoRaWan device class (A, B, or C) 125 | * @retval 0 if LoRaWAN class A is selected 126 | * @retval 1 if LoRaWAN class B is selected 127 | * @retval 2 if LoRaWAN class C is selected 128 | */ 129 | DeviceClass_t lrw_get_class(void); 130 | 131 | 132 | /** @brief Select a LoRaWAN device class (A, B, or C) 133 | * 134 | * This function will configure the LoRaMac stack to use the specified class. 135 | * The value will be persistently stored in NVM. 136 | * 137 | * @param[in] device_class The class to be used (0 for A, 1 for B, 2 for C) 138 | * @return Zero on success, a @c LoRaMacStatus_t value on error 139 | */ 140 | int lrw_set_class(DeviceClass_t device_class); 141 | 142 | 143 | /** @brief Configure the maximum effective isotropic radiated power (EIRP) 144 | * @param[in] maxeirp Maximum EIRP to be used by the transmitter 145 | */ 146 | void lrw_set_maxeirp(unsigned int maxeirp); 147 | 148 | 149 | /** @brief Configure whether the node respects dwell time (only relevant in AS923) 150 | * @param[in] uplink Enable or disable dwell time checking on the uplink 151 | @ @param[in] downlink Enable or disable dwell time checking on the downlink 152 | * @return Zero on success, a @c LoRaMacStatus_t value on error 153 | */ 154 | int lrw_set_dwell(bool uplink, bool downlink); 155 | 156 | 157 | /** @brief Update the device's LoRaWAN 1.1 DevNonce value 158 | * @param[in] nonce LoRaWAN 1.1 DevNonce value 159 | */ 160 | void lrw_set_devnonce(uint16_t nonce); 161 | 162 | 163 | /** @brief Return the maximum number of channels for the currently active region 164 | * @return Number of channels 165 | */ 166 | int lrw_get_max_channels(void); 167 | 168 | 169 | LoRaMacStatus_t lrw_mlme_request(MlmeReq_t* req); 170 | 171 | // A simple wrapper over LoRaMacMcpsRequest that properly configures uplink 172 | // retransmissions and keeps track of the duty cycle wait time returned by the 173 | // function for the benefit of AT+BACKOFF 174 | LoRaMacStatus_t lrw_mcps_request(McpsReq_t* req, int transmissions); 175 | 176 | 177 | void lrw_factory_reset(bool reset_devnonce, bool reset_deveui); 178 | 179 | 180 | /** @brief Get LoRaWAN network time via the DeviceTimeReq MAC command 181 | * 182 | * This function can be used to get the current LoRaWAN network time. It uses 183 | * the DeviceTimeReq MAC command, which is available in LoRaWAN 1.0.3 or higher. 184 | * 185 | * The function sends the uplink and returns immediately. The time will be sent 186 | * to the application via an asynchronous notification. 187 | * 188 | * @return Zero on success, a @c LoRaMacStatus_t value on error 189 | */ 190 | LoRaMacStatus_t lrw_get_device_time(bool piggyback); 191 | 192 | #endif // _LRW_H 193 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "atci.h" 4 | #include "cmd.h" 5 | #include "adc.h" 6 | #include "lrw.h" 7 | #include "system.h" 8 | #include "log.h" 9 | #include "lpuart.h" 10 | #include "spi.h" 11 | #include "gpio.h" 12 | #include "rtc.h" 13 | #include "usart.h" 14 | #include "irq.h" 15 | #include "part.h" 16 | #include "eeprom.h" 17 | #include "halt.h" 18 | #include "nvm.h" 19 | #include "sx1276-board.h" 20 | 21 | 22 | int main(void) 23 | { 24 | int busy; 25 | system_init(); 26 | 27 | #ifdef DEBUG 28 | log_init(LOG_LEVEL_DUMP, LOG_TIMESTAMP_ABS); 29 | #else 30 | log_init(LOG_LEVEL_OFF, LOG_TIMESTAMP_ABS); 31 | #endif 32 | log_info("Open LoRaWAN modem %s [LoRaMac %s] built on %s", VERSION, LIB_VERSION, BUILD_DATE); 33 | 34 | nvm_init(); 35 | cmd_init(sysconf.uart_baudrate); 36 | 37 | adc_init(); 38 | 39 | SX1276.DIO0.port = GPIOB; 40 | SX1276.DIO0.pinIndex = GPIO_PIN_4; 41 | SX1276.DIO1.port = GPIOB; 42 | SX1276.DIO1.pinIndex = GPIO_PIN_1; 43 | SX1276.DIO2.port = GPIOB; 44 | SX1276.DIO2.pinIndex = GPIO_PIN_0; 45 | SX1276.DIO3.port = GPIOC; 46 | SX1276.DIO3.pinIndex = GPIO_PIN_13; 47 | SX1276.DIO4.port = GPIOA; 48 | SX1276.DIO4.pinIndex = GPIO_PIN_5; 49 | SX1276.DIO5.port = GPIOA; 50 | SX1276.DIO5.pinIndex = GPIO_PIN_4; 51 | SX1276.Reset.port = GPIOC; 52 | SX1276.Reset.pinIndex = GPIO_PIN_0; 53 | 54 | spi_init(&SX1276.Spi, 10000000); 55 | SX1276IoInit(); 56 | 57 | lrw_init(); 58 | log_debug("LoRaMac: Starting"); 59 | LoRaMacStart(); 60 | cmd_event(CMD_EVENT_MODULE, CMD_MODULE_BOOT); 61 | 62 | while (1) { 63 | cmd_process(); 64 | lrw_process(); 65 | sysconf_process(); 66 | 67 | disable_irq(); 68 | 69 | // If the application has scheduled a system reset, postpone it until 70 | // there are no more pending tasks. We don't really have the notion of 71 | // tasks in the modem software; however, we can tell that nothing is 72 | // going on once both low-power modes (sleep and stop) are not prevented 73 | // by any of the subsystems. The low-power sleep mode is typically 74 | // prevented if a subsystem requests that the application iterates 75 | // through its main loop as quickly as possible, e.g., to handle an ISR 76 | // from the main thread. The stop mode can be prevented by hardware 77 | // peripherals such as LPUART1, RTC, or SX1276 while they need to finish 78 | // some background work. We specifically ignore the RADIO subsystem in 79 | // the code below and instead rely on LoRaMacIsBusy to tell us whether 80 | // the MAC subsystem (which owns the radio) is busy. This will allow a 81 | // reboot in class C, where the radio is continuously listening. This 82 | // heuristic to determine when to perform the reset is a bit hackish, 83 | // but it's the best we can do in the absence of better activity 84 | // tracking mechanism. 85 | 86 | busy = system_sleep_lock | (system_stop_lock & ~SYSTEM_MODULE_RADIO) | LoRaMacIsBusy(); 87 | if (schedule_reset && !busy) { 88 | NVIC_SystemReset(); 89 | } else { 90 | system_idle(); 91 | } 92 | 93 | enable_irq(); 94 | 95 | // Invoke lrw_process as the first thing after waking up to give the MAC 96 | // a chance to timestamp incoming downlink as quickly as possible. 97 | lrw_process(); 98 | } 99 | } 100 | 101 | 102 | void system_before_stop(void) 103 | { 104 | SX1276IoDeInit(); 105 | spi_io_deinit(&SX1276.Spi); 106 | adc_before_stop(); 107 | lpuart_before_stop(); 108 | } 109 | 110 | 111 | void system_after_stop(void) 112 | { 113 | lpuart_after_stop(); 114 | adc_after_stop(); 115 | spi_io_init(&SX1276.Spi); 116 | SX1276IoInit(); 117 | } 118 | -------------------------------------------------------------------------------- /src/mlm32l0xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "halt.h" 4 | #include "rtc.h" 5 | #include "gpio.h" 6 | 7 | /* when fast wake up is enabled, the mcu wakes up in ~20us * and 8 | * does not wait for the VREFINT to be settled. THis is ok for 9 | * most of the case except when adc must be used in this case before 10 | *starting the adc, you must make sure VREFINT is settled*/ 11 | #define ENABLE_FAST_WAKEUP 12 | 13 | /** 14 | * @brief This function configures the source of the time base. 15 | * @brief don't enable systick 16 | * @param TickPriority: Tick interrupt priority. 17 | * @retval HAL status 18 | */ 19 | HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) 20 | { 21 | (void) TickPriority; 22 | return HAL_OK; 23 | } 24 | 25 | /** 26 | * @brief This function provides delay (in ms) 27 | * @param Delay: specifies the delay time length in milliseconds. 28 | * @retval None 29 | */ 30 | void HAL_Delay(__IO uint32_t Delay) 31 | { 32 | rtc_delay_ms(Delay); /* based on RTC */ 33 | } 34 | 35 | /** 36 | * @brief Initializes the MSP. 37 | * @retval None 38 | */ 39 | void HAL_MspInit(void) 40 | { 41 | __HAL_RCC_PWR_CLK_ENABLE(); 42 | 43 | /* Disable the Power Voltage Detector */ 44 | HAL_PWR_DisablePVD(); 45 | 46 | /* Enables the Ultra Low Power mode */ 47 | HAL_PWREx_EnableUltraLowPower(); 48 | 49 | /* In the debug mode, e.g., when DBGMCU is activated, the ARM core has always 50 | * clocks and will not wait until the flash is ready to be read. In this case, 51 | * it can miss the first instruction. To overcome this issue, the flash 52 | * remains clocked during sleep mode. 53 | */ 54 | #ifdef DEBUG 55 | do 56 | { 57 | __HAL_FLASH_SLEEP_POWERDOWN_DISABLE(); 58 | } while (0); 59 | #else 60 | __HAL_FLASH_SLEEP_POWERDOWN_ENABLE(); 61 | #endif 62 | 63 | #ifdef ENABLE_FAST_WAKEUP 64 | /*Enable fast wakeUp*/ 65 | HAL_PWREx_EnableFastWakeUp(); 66 | #else 67 | HAL_PWREx_DisableFastWakeUp(); 68 | #endif 69 | 70 | __HAL_RCC_PWR_CLK_DISABLE(); 71 | } 72 | 73 | /** 74 | * @brief RTC MSP Initialization This function configures the hardware 75 | * resources used in this example: - Peripheral's clock enable 76 | * @param hrtc: RTC handle pointer 77 | * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select 78 | * the RTC clock source; in this case, the Backup domain will be reset 79 | * in order to modify the RTC Clock source, as a consequence, RTC 80 | * registers (including the backup registers) and RCC_CSR registers are 81 | * set to their reset values. 82 | * @retval None 83 | */ 84 | void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) 85 | { 86 | (void) hrtc; 87 | RCC_PeriphCLKInitTypeDef rcc = { 0 }; 88 | 89 | // Note: The LSE must be enabled before this function is called. In the LoRa 90 | // firmware, LSE is enabled in the clock initialization function in system.c 91 | 92 | // Select LSE as RTC clock source 93 | rcc.PeriphClockSelection = RCC_PERIPHCLK_RTC; 94 | rcc.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; 95 | if (HAL_RCCEx_PeriphCLKConfig(&rcc) != HAL_OK) 96 | halt("Error while initializing LSE as RTC clock source"); 97 | 98 | __HAL_RCC_RTC_ENABLE(); 99 | 100 | // Configure the NVIC for RTC alarms 101 | HAL_NVIC_SetPriority(RTC_IRQn, 0x0, 0); 102 | HAL_NVIC_EnableIRQ(RTC_IRQn); 103 | } 104 | 105 | /** 106 | * @brief RTC MSP De-Initialization 107 | * This function freezes the hardware resources used in this example: 108 | * - Disable the Peripheral's clock 109 | * @param hrtc: RTC handle pointer 110 | * @retval None 111 | */ 112 | void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc) 113 | { 114 | (void) hrtc; 115 | /* Reset peripherals */ 116 | __HAL_RCC_RTC_DISABLE(); 117 | } 118 | 119 | /** 120 | * @brief Alarm A callback. 121 | * @param hrtc: RTC handle 122 | * @retval None 123 | */ 124 | void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) 125 | { 126 | (void) hrtc; 127 | TimerIrqHandler(); 128 | } 129 | 130 | /** 131 | * @brief EXTI line detection callbacks. 132 | * @param GPIO_Pin: Specifies the pins connected to the EXTI line. 133 | * @retval None 134 | */ 135 | void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 136 | { 137 | gpio_hal_msp_irq_handler(GPIO_Pin); 138 | } 139 | -------------------------------------------------------------------------------- /src/nvm.h: -------------------------------------------------------------------------------- 1 | #ifndef _NVM_H_ 2 | #define _NVM_H_ 3 | 4 | #include "part.h" 5 | 6 | 7 | /* The sysconf data structure is meant to be used for platform configuration 8 | * (UART parameters, etc.) and for configuration that cannot be stored 9 | * elsewhere, e.g., the LoRaMAC MIB. Some of the parameters, e.g., device_class, 10 | * need to be kept synchronized with the MIB. 11 | */ 12 | typedef struct sysconf 13 | { 14 | /* The baud rate to be used by the ATCI UART interface. The following values 15 | * are supported: 1200, 2400, 4800, 9600, 19200, 38400. 16 | */ 17 | unsigned int uart_baudrate; 18 | 19 | /* The maximum time (in milliseconds) for payload (data) uploads over the 20 | * ATCI. If the client does not upload all data within this time, the upload 21 | * will be terminated, and the ATCI will wait for further AT commands. 22 | */ 23 | uint16_t uart_timeout; 24 | 25 | /* The default port number to be used with AT+UTX and AT+CXT commands. */ 26 | uint8_t default_port; 27 | 28 | /* The data encoding of payload data expected by the firmware. The value 0 29 | * indicates that the client submits payloads in binary form. The value 1 30 | * indicates that the client submits payloads in a hex form. 31 | */ 32 | uint8_t data_format : 1; 33 | 34 | /* This parameter controls whether the firmware enters low-power modes when 35 | * idle. Set to 0 to disable all low-power modes, set to 1 to enable 36 | * low-power modes. 37 | */ 38 | uint8_t sleep : 1; 39 | 40 | /* We need to keep LoRa device class here, in addition to the MIB, because 41 | * the MIB variable is reset to class A during Join. Having a separate copy 42 | * here allows us to restore the class after Join. 43 | */ 44 | uint8_t device_class : 2; 45 | 46 | /* When this flag is set to 1, the AT command interface will prevent the 47 | * application from reading the various LoRaWAN security keys. The 48 | * corresponding AT commands will return an error. This flag can be only 49 | * reset back to 0 with a factory reset. 50 | */ 51 | uint8_t lock_keys : 1; 52 | 53 | /* When this flag is set to 1 (default), the AT command interface will send 54 | * event notifications asynchronously. When set to 0, the asynchronous event 55 | * notifications will be buffered and will be only delivered to the host 56 | * between an AT command and its response (e.g., +OK or +ERR). This allows 57 | * the host to implement a polling mode where the UART can be powered down 58 | * between AT commands. 59 | */ 60 | uint8_t async_uart : 1; 61 | 62 | /* The maximum number of retransmissions of unconfirmed uplink messages. 63 | * Receiving a downlink message from the network stops retransmissions. 64 | */ 65 | uint8_t unconfirmed_retransmissions; 66 | 67 | /* The maximum number of retransmissions of confirmed uplink messages. 68 | * Receiving a downlink message from the network stops retransmissions. 69 | */ 70 | uint8_t confirmed_retransmissions; 71 | 72 | uint32_t crc32; 73 | } sysconf_t; 74 | 75 | 76 | struct nvm_parts { 77 | part_t sysconf; 78 | part_t crypto; 79 | part_t mac1; 80 | part_t mac2; 81 | part_t se; 82 | part_t region1; 83 | part_t region2; 84 | part_t classb; 85 | part_t user; 86 | }; 87 | 88 | 89 | #define USER_NVM_MAX_SIZE 64 // The maximum number of NVM user data registers 90 | #define USER_NVM_MAGIC 0xD15C9101 91 | 92 | typedef struct user_nvm_s { 93 | uint32_t magic; 94 | uint8_t values[USER_NVM_MAX_SIZE]; 95 | uint32_t crc32; 96 | } user_nvm_t; 97 | 98 | 99 | extern struct nvm_parts nvm_parts; 100 | extern sysconf_t sysconf; 101 | extern bool sysconf_modified; 102 | extern uint16_t nvm_flags; 103 | extern user_nvm_t user_nvm; 104 | 105 | void nvm_init(void); 106 | 107 | int nvm_erase(void); 108 | 109 | void sysconf_process(void); 110 | 111 | void nvm_update_user_data(void); 112 | 113 | #endif // _NVM_H_ 114 | -------------------------------------------------------------------------------- /src/part.h: -------------------------------------------------------------------------------- 1 | #ifndef _PART_H_ 2 | #define _PART_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAX_LABEL_SIZE 16 9 | 10 | #define PART_ALIGNMENT 4 11 | #define PART_ALIGN(v) (((v) + PART_ALIGNMENT - 1) / PART_ALIGNMENT * PART_ALIGNMENT) 12 | 13 | #define FIXED_PART_TABLE_SIZE (PART_ALIGN(sizeof(part_table_t))) 14 | #define VARIABLE_PART_TABLE_SIZE(n) ((n) * PART_ALIGN(sizeof(part_dsc_t))) 15 | #define PART_TABLE_SIZE(n) (FIXED_PART_TABLE_SIZE + VARIABLE_PART_TABLE_SIZE((n))) 16 | 17 | 18 | typedef struct part_dsc { 19 | uint32_t start; 20 | uint32_t size; 21 | char label[MAX_LABEL_SIZE]; 22 | } part_dsc_t; 23 | 24 | 25 | typedef struct part { 26 | const struct part_block *block; 27 | const part_dsc_t *dsc; 28 | } part_t; 29 | 30 | 31 | typedef struct part_table { 32 | uint32_t signature; //Well-known signature of the partition table 33 | size_t size; // Size of the partition table, including signature and the parts array that follows the partition table 34 | uint8_t num_parts; // Number of partitions in the parts array 35 | } part_table_t; 36 | 37 | 38 | typedef struct part_block { 39 | const uint32_t start; // The first memory address of the partitioned memory block 40 | const size_t size; // The size of the partitioned memory block in bytes 41 | const part_table_t *table; // A mmaped pointer to the partition table 42 | const part_dsc_t *parts; // A mmaped pointer to the partition array 43 | bool (*write)(uint32_t address, const void *buffer, size_t length); 44 | const void *(*mmap)(uint32_t address, size_t length); 45 | } part_block_t; 46 | 47 | 48 | int part_erase_block(part_block_t *block); 49 | int part_format_block(part_block_t *block, unsigned int max_parts); 50 | int part_open_block(part_block_t *block); 51 | void part_close_block(part_block_t *block); 52 | 53 | int part_find(part_t *part, const part_block_t *block, const char *label); 54 | int part_create(part_t *part, const part_block_t *block, const char *label, size_t size); 55 | 56 | bool part_write(const part_t *part, uint32_t address, const void *buffer, size_t length); 57 | const void *part_mmap(size_t *size, const part_t *part); 58 | bool part_erase(const part_t *part); 59 | 60 | int part_dump_block(part_block_t *block); 61 | 62 | #endif // _PART_H_ -------------------------------------------------------------------------------- /src/radio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "log.h" 3 | 4 | 5 | int16_t radio_rssi; 6 | int8_t radio_snr; 7 | 8 | // Below, we replace the RxDone callback given to us by LoRaMac-node with our 9 | // own version to save the RSSI and SNR if each received packet. The original 10 | // callback (the one from LoRaMac-node) is kept here. 11 | static void (*OrigRxDone)(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); 12 | 13 | #if DEBUG_LOG != 0 14 | 15 | static const char *modem2str(RadioModems_t modem) 16 | { 17 | switch(modem) { 18 | case MODEM_FSK : return "FSK"; 19 | case MODEM_LORA : return "LoRa"; 20 | default : return "?"; 21 | } 22 | } 23 | 24 | 25 | static const char *lora_bandwidth2str(uint32_t bandwidth) 26 | { 27 | switch(bandwidth) { 28 | case 0: return "125kHz"; 29 | case 1: return "250kHz"; 30 | case 2: return "500kHz"; 31 | default: return "?"; 32 | } 33 | } 34 | 35 | 36 | static const char *lora_sf2str(uint32_t sf) 37 | { 38 | switch(sf) { 39 | case 6: return "SF6"; 40 | case 7: return "SF7"; 41 | case 8: return "SF8"; 42 | case 9: return "SF9"; 43 | case 10: return "SF10"; 44 | case 11: return "SF11"; 45 | case 12: return "SF12"; 46 | default: return "SF?"; 47 | } 48 | } 49 | 50 | 51 | static const char *coderate2str(uint8_t coderate) 52 | { 53 | switch(coderate) { 54 | case 1 : return "4/5"; break; 55 | case 2 : return "4/6"; break; 56 | case 3 : return "4/7"; break; 57 | case 4 : return "4/8"; break; 58 | default: return "?/?"; break; 59 | } 60 | } 61 | 62 | #endif 63 | 64 | static bool SX1276CheckRfFrequency(__attribute__((unused)) uint32_t frequency) 65 | { 66 | // Implement check. Currently, all frequencies are supported 67 | log_debug("SX1276CheckRfFrequency: %ld", frequency); 68 | return true; 69 | } 70 | 71 | 72 | static void SetChannel(uint32_t freq) 73 | { 74 | log_debug("SX1276SetChannel: %.3f MHz", (float)freq / (float)1000000); 75 | SX1276SetChannel(freq); 76 | } 77 | 78 | 79 | static void SetTxConfig(RadioModems_t modem, int8_t power, uint32_t fdev, 80 | uint32_t bandwidth, uint32_t datarate, uint8_t coderate, 81 | uint16_t preambleLen, bool fixLen, bool crcOn, bool freqHopOn, 82 | uint8_t hopPeriod, bool iqInverted, uint32_t timeout) 83 | { 84 | #if DEBUG_LOG != 0 85 | log_compose(); 86 | log_debug("SX1276SetTxConfig: %d dBm", power); 87 | log_debug(" %s", modem2str(modem)); 88 | 89 | if (modem == MODEM_LORA) { 90 | log_debug(" %s/%s %s", lora_sf2str(datarate), 91 | lora_bandwidth2str(bandwidth), coderate2str(coderate)); 92 | log_debug(" preamb=%d", preambleLen); 93 | 94 | if (fixLen) log_debug(" fixLen"); 95 | if (crcOn) log_debug(" CRC"); 96 | if (freqHopOn) log_debug(" fHop(%d)", hopPeriod); 97 | if (iqInverted) log_debug(" iqInv"); 98 | } else if (modem == MODEM_FSK) { 99 | log_debug(" fdev=%ld dr=%ld preamb=%d", fdev, datarate, preambleLen); 100 | if (fixLen) log_debug(" fixLen"); 101 | if (crcOn) log_debug(" CRC"); 102 | } 103 | 104 | log_debug(" tout=%ldms", timeout); 105 | log_finish(); 106 | #endif 107 | 108 | SX1276SetTxConfig(modem, power, fdev, bandwidth, datarate, coderate, 109 | preambleLen, fixLen, crcOn, freqHopOn, hopPeriod, iqInverted, 110 | timeout); 111 | } 112 | 113 | 114 | static void SetRxConfig(RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, 115 | uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, 116 | uint16_t symbTimeout, bool fixLen, uint8_t payloadLen, bool crcOn, 117 | bool freqHopOn, uint8_t hopPeriod, bool iqInverted, bool rxContinuous) 118 | { 119 | #if DEBUG_LOG != 0 120 | log_compose(); 121 | log_debug("SX1276SetRxConfig: %s", modem2str(modem)); 122 | 123 | if (modem == MODEM_LORA) { 124 | log_debug(" %s/%s %s", lora_sf2str(datarate), 125 | lora_bandwidth2str(bandwidth), coderate2str(coderate)); 126 | log_debug(" preamb=%d", preambleLen); 127 | log_debug(" symTout=%d", symbTimeout); 128 | 129 | if (fixLen) log_debug(" fixLen(%d)", payloadLen); 130 | if (crcOn) log_debug(" CRC"); 131 | if (freqHopOn) log_debug(" fHop(%d)", hopPeriod); 132 | if (iqInverted) log_debug(" iqInv"); 133 | if (rxContinuous) log_debug(" rxCont"); 134 | } else if (modem == MODEM_FSK) { 135 | log_debug(" bw=%ld", bandwidth); 136 | log_debug(" dr=%ld", datarate); 137 | log_debug(" bwAfc=%ld", bandwidthAfc); 138 | log_debug(" preamb=%d", preambleLen); 139 | log_debug(" symTout=%d", symbTimeout); 140 | if (fixLen) log_debug(" fixLen(%d)", payloadLen); 141 | if (crcOn) log_debug(" CRC"); 142 | if (rxContinuous) log_debug(" rxCont"); 143 | } 144 | 145 | log_finish(); 146 | #endif 147 | 148 | SX1276SetRxConfig(modem, bandwidth, datarate, coderate, bandwidthAfc, 149 | preambleLen, symbTimeout, fixLen, payloadLen, crcOn, freqHopOn, 150 | hopPeriod, iqInverted, rxContinuous); 151 | } 152 | 153 | 154 | // This is our custom RxDone callback. We save the RSSI and SNR in global static 155 | // variables so that they could be accessed from the application and delegated 156 | // to the original callback. 157 | static void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 158 | { 159 | radio_rssi = rssi; 160 | radio_snr = snr; 161 | if (OrigRxDone != NULL) OrigRxDone(payload, size, rssi, snr); 162 | } 163 | 164 | 165 | static void Init(RadioEvents_t *events) 166 | { 167 | // Save the original RxDone callback and replace it with our own version 168 | OrigRxDone = events->RxDone; 169 | events->RxDone = RxDone; 170 | SX1276Init(events); 171 | } 172 | 173 | 174 | // Radio driver structure initialization 175 | const struct Radio_s Radio = { 176 | .Init = Init, 177 | .GetStatus = SX1276GetStatus, 178 | .SetModem = SX1276SetModem, 179 | .SetChannel = SetChannel, 180 | .IsChannelFree = SX1276IsChannelFree, 181 | .Random = SX1276Random, 182 | .SetRxConfig = SetRxConfig, 183 | .SetTxConfig = SetTxConfig, 184 | .CheckRfFrequency = SX1276CheckRfFrequency, 185 | .TimeOnAir = SX1276GetTimeOnAir, 186 | .Send = SX1276Send, 187 | .Sleep = SX1276SetSleep, 188 | .Standby = SX1276SetStby, 189 | .Rx = SX1276SetRx, 190 | .StartCad = SX1276StartCad, 191 | .SetTxContinuousWave = SX1276SetTxContinuousWave, 192 | .Rssi = SX1276ReadRssi, 193 | .Write = SX1276Write, 194 | .Read = SX1276Read, 195 | .WriteBuffer = SX1276WriteBuffer, 196 | .ReadBuffer = SX1276ReadBuffer, 197 | .SetMaxPayloadLength = SX1276SetMaxPayloadLength, 198 | .SetPublicNetwork = SX1276SetPublicNetwork, 199 | .GetWakeupTime = SX1276GetWakeupTime, 200 | .IrqProcess = NULL, 201 | .RxBoosted = NULL, 202 | .SetRxDutyCycle = NULL 203 | }; 204 | -------------------------------------------------------------------------------- /src/rtc.h: -------------------------------------------------------------------------------- 1 | #ifndef _HW_RTC_H 2 | #define _HW_RTC_H 3 | 4 | #include 5 | #include 6 | 7 | //! @param Temperature coefficient of the clock source 8 | 9 | #define RTC_TEMP_COEFFICIENT (-0.035) 10 | 11 | //! @param Temperature coefficient deviation of the clock source 12 | 13 | #define RTC_TEMP_DEV_COEFFICIENT (0.0035) 14 | 15 | //! @param Turnover temperature of the clock source 16 | 17 | #define RTC_TEMP_TURNOVER (25.0) 18 | 19 | //! @param Turnover temperature deviation of the clock source 20 | 21 | #define RTC_TEMP_DEV_TURNOVER (5.0) 22 | 23 | //! @param Initializes the RTC timer 24 | //! @note The timer is based on the RTC 25 | 26 | void rtc_init(void); 27 | 28 | //! @param Stop the Alarm 29 | 30 | void rtc_stop_alarm(void); 31 | 32 | //! @param Return the minimum timeout the RTC is able to handle 33 | //! @retval minimum value for a timeout 34 | 35 | uint32_t rtc_get_min_timeout(void); 36 | 37 | //! @brief Set the alarm 38 | //! @note The alarm is set at Reference + timeout 39 | //! @param timeout Duration of the Timer in ticks 40 | 41 | void rtc_set_alarm(uint32_t timeout); 42 | 43 | //! @brief Get the RTC timer elapsed time since the last Reference was set 44 | //! @retval RTC Elapsed time in ticks 45 | 46 | uint32_t rtc_get_timer_elapsed_time(void); 47 | 48 | //! @brief Get the RTC timer value 49 | 50 | uint32_t rtc_get_timer_value(void); 51 | 52 | //! @brief Set the RTC timer Reference 53 | //! @retval Timer Reference Value in Ticks 54 | 55 | uint32_t rtc_set_timer_context(void); 56 | 57 | //! @brief Get the RTC timer Reference 58 | //! @retval Timer Value in Ticks 59 | 60 | uint32_t rtc_get_timer_context(void); 61 | 62 | //! @brief a delay of delay ms by polling RTC 63 | //! @param delay in ms 64 | 65 | void rtc_delay_ms(uint32_t delay); 66 | 67 | //! @brief calculates the wake up time between wake up and mcu start 68 | //! @note resolution in RTC_ALARM_TIME_BASE 69 | 70 | void rtc_set_mcu_wake_up_time(void); 71 | 72 | //! @brief returns the wake up time in us 73 | //! @retval wake up time in ticks 74 | 75 | int16_t rtc_get_mcu_wake_up_time(void); 76 | 77 | //! @brief converts time in ms to time in ticks 78 | //! @param [IN] time in milliseconds 79 | //! @retval returns time in timer ticks 80 | 81 | uint32_t rtc_ms2tick(TimerTime_t timeMilliSec); 82 | 83 | //! @brief converts time in ticks to time in ms 84 | //! @param [IN] time in timer ticks 85 | //! @retval returns time in timer milliseconds 86 | 87 | TimerTime_t rtc_tick2ms(uint32_t tick); 88 | 89 | //! @brief Computes the temperature compensation for a period of time on a specific temperature. 90 | //! @param [IN] period Time period to compensate 91 | //! @param [IN] temperature Current temperature 92 | //! @retval Compensated time period 93 | 94 | TimerTime_t rtc_temperature_compensation(TimerTime_t period, float temperature); 95 | 96 | //! @brief Get system time 97 | //! @param [IN] subSeconds in ms 98 | //! @retval 99 | 100 | uint32_t rtc_get_calendar_time(uint16_t *subSeconds); 101 | 102 | //! @brief Read from backup registers 103 | //! @param [IN] Data 0 104 | //! @param [IN] Data 1 105 | 106 | void rtc_read_backup_registers(uint32_t *Data0, uint32_t *Data1); 107 | 108 | //! @brief Write in backup registers 109 | //! @param [IN] Data 0 110 | //! @param [IN] Data 1 111 | 112 | void rtc_write_backup_registers(uint32_t Data0, uint32_t Data1); 113 | 114 | #endif // _HW_RTC_H 115 | -------------------------------------------------------------------------------- /src/spi.c: -------------------------------------------------------------------------------- 1 | #include "spi.h" 2 | #include "halt.h" 3 | 4 | 5 | static uint32_t calc_divisor_for_frequency(uint32_t hz) 6 | { 7 | uint32_t divisor = 0; 8 | uint32_t SysClkTmp = SystemCoreClock; 9 | uint32_t baudRate; 10 | 11 | while (SysClkTmp > hz) { 12 | divisor++; 13 | SysClkTmp = (SysClkTmp >> 1); 14 | if (divisor >= 7) break; 15 | } 16 | 17 | baudRate = (((divisor & 0x4) == 0) ? 0x0 : SPI_CR1_BR_2) | 18 | (((divisor & 0x2) == 0) ? 0x0 : SPI_CR1_BR_1) | 19 | (((divisor & 0x1) == 0) ? 0x0 : SPI_CR1_BR_0); 20 | 21 | return baudRate; 22 | } 23 | 24 | 25 | void spi_init(Spi_t *spi, uint32_t speed) 26 | { 27 | spi->hspi.Instance = SPI1; 28 | 29 | spi->hspi.Init.BaudRatePrescaler = calc_divisor_for_frequency(speed); 30 | spi->hspi.Init.Direction = SPI_DIRECTION_2LINES; 31 | spi->hspi.Init.Mode = SPI_MODE_MASTER; 32 | spi->hspi.Init.CLKPolarity = SPI_POLARITY_LOW; 33 | spi->hspi.Init.CLKPhase = SPI_PHASE_1EDGE; 34 | spi->hspi.Init.DataSize = SPI_DATASIZE_8BIT; 35 | spi->hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; 36 | spi->hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; 37 | spi->hspi.Init.NSS = SPI_NSS_SOFT; 38 | spi->hspi.Init.TIMode = SPI_TIMODE_DISABLE; 39 | 40 | spi->Nss.port = GPIOA; 41 | spi->Nss.pinIndex = GPIO_PIN_15; 42 | 43 | spi->miso.port = GPIOA; 44 | spi->miso.pinIndex = GPIO_PIN_6; 45 | 46 | spi->mosi.port = GPIOA; 47 | spi->mosi.pinIndex = GPIO_PIN_7; 48 | 49 | spi->sclk.port = GPIOB; 50 | spi->sclk.pinIndex = GPIO_PIN_3; 51 | 52 | __HAL_RCC_SPI1_CLK_ENABLE(); 53 | 54 | if (HAL_SPI_Init(&spi->hspi) != HAL_OK) 55 | halt("Error while initializing SPI subsystem"); 56 | 57 | spi_io_init(spi); 58 | 59 | } 60 | 61 | 62 | void spi_deinit(Spi_t *spi) 63 | { 64 | HAL_SPI_DeInit(&spi->hspi); 65 | 66 | // Reset peripherals 67 | __HAL_RCC_SPI1_FORCE_RESET(); 68 | __HAL_RCC_SPI1_RELEASE_RESET(); 69 | 70 | spi_io_deinit(spi); 71 | } 72 | 73 | 74 | void spi_io_init(Spi_t *spi) 75 | { 76 | GPIO_InitTypeDef cfg = { 77 | .Mode = GPIO_MODE_AF_PP, 78 | .Pull = GPIO_NOPULL, 79 | .Speed = GPIO_SPEED_HIGH, 80 | .Alternate = GPIO_AF0_SPI1 81 | }; 82 | 83 | gpio_init(spi->sclk.port, spi->sclk.pinIndex, &cfg); 84 | gpio_init(spi->mosi.port, spi->mosi.pinIndex, &cfg); 85 | 86 | cfg.Pull = GPIO_PULLDOWN; 87 | gpio_init(spi->miso.port, spi->miso.pinIndex, &cfg); 88 | 89 | cfg.Mode = GPIO_MODE_OUTPUT_PP; 90 | cfg.Pull = GPIO_NOPULL; 91 | gpio_init(spi->Nss.port, spi->Nss.pinIndex, &cfg); 92 | gpio_write(spi->Nss.port, spi->Nss.pinIndex, 1); 93 | } 94 | 95 | 96 | void spi_io_deinit(Spi_t *spi) 97 | { 98 | GPIO_InitTypeDef cfg = { 99 | .Mode = GPIO_MODE_OUTPUT_PP, 100 | .Pull = GPIO_NOPULL 101 | }; 102 | 103 | gpio_init(spi->mosi.port, spi->mosi.pinIndex, &cfg); 104 | gpio_write(spi->mosi.port, spi->mosi.pinIndex, 0); 105 | 106 | gpio_init(spi->sclk.port, spi->sclk.pinIndex, &cfg); 107 | gpio_write(spi->sclk.port, spi->sclk.pinIndex, 0); 108 | 109 | gpio_init(spi->Nss.port, spi->Nss.pinIndex, &cfg); 110 | gpio_write(spi->Nss.port, spi->Nss.pinIndex, 1); 111 | 112 | cfg.Mode = GPIO_MODE_INPUT; 113 | cfg.Pull = GPIO_PULLDOWN; 114 | gpio_write(spi->miso.port, spi->miso.pinIndex, 0); 115 | gpio_init(spi->miso.port, spi->miso.pinIndex, &cfg); 116 | } 117 | 118 | 119 | uint16_t SpiInOut(Spi_t *obj, uint16_t outData) 120 | { 121 | uint8_t rx, tx = outData; 122 | HAL_SPI_TransmitReceive(&obj->hspi, &tx, &rx, 1, HAL_MAX_DELAY); 123 | return rx; 124 | } 125 | -------------------------------------------------------------------------------- /src/spi.h: -------------------------------------------------------------------------------- 1 | #ifndef _HW_SPI_H 2 | #define _HW_SPI_H 3 | 4 | #include 5 | #include "gpio.h" 6 | 7 | 8 | typedef struct 9 | { 10 | SPI_HandleTypeDef hspi; 11 | Gpio_t Nss; // First character is upper-case for compatiblity with LoRaMac-node 12 | Gpio_t mosi; 13 | Gpio_t miso; 14 | Gpio_t sclk; 15 | } Spi_t; 16 | 17 | 18 | //! @brief Initialize SPI channel 19 | //! @param[in] speed SPI communication speed [hz] 20 | 21 | void spi_init(Spi_t *spi, uint32_t speed); 22 | 23 | //! @brief Deinitialize SPI channel 24 | 25 | void spi_deinit(Spi_t *spi); 26 | 27 | //! @brief Initialize the SPI IOs 28 | 29 | void spi_io_init(Spi_t *spi); 30 | 31 | //! @brief Deinitialize the SPI IOs 32 | 33 | void spi_io_deinit(Spi_t *spi); 34 | 35 | 36 | uint16_t SpiInOut(Spi_t *obj, uint16_t outData); 37 | 38 | #endif // _HW_SPI_H 39 | -------------------------------------------------------------------------------- /src/sx1276-board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx1276-board.h 3 | * 4 | * \brief Target board SX1276 driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __SX1276_BOARD_H__ 24 | #define __SX1276_BOARD_H__ 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | /*! 36 | * \brief Radio hardware registers initialization definition 37 | * 38 | * \remark Can be automatically generated by the SX1276 GUI (not yet implemented) 39 | */ 40 | #define RADIO_INIT_REGISTERS_VALUE \ 41 | { \ 42 | { MODEM_FSK , REG_LNA , 0x23 },\ 43 | { MODEM_FSK , REG_RXCONFIG , 0x1E },\ 44 | { MODEM_FSK , REG_RSSICONFIG , 0xD2 },\ 45 | { MODEM_FSK , REG_AFCFEI , 0x01 },\ 46 | { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\ 47 | { MODEM_FSK , REG_OSC , 0x07 },\ 48 | { MODEM_FSK , REG_SYNCCONFIG , 0x12 },\ 49 | { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\ 50 | { MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\ 51 | { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\ 52 | { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\ 53 | /* FIFO threshold set to 32 (31+1) */ \ 54 | { MODEM_FSK , REG_FIFOTHRESH , 0x9F },\ 55 | { MODEM_FSK , REG_IMAGECAL , 0x02 },\ 56 | { MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\ 57 | { MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\ 58 | { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\ 59 | } \ 60 | 61 | #define RF_MID_BAND_THRESH 525000000 62 | 63 | /*! 64 | * \brief Initializes the radio I/Os pins interface 65 | */ 66 | void SX1276IoInit( void ); 67 | 68 | /*! 69 | * \brief Initializes DIO IRQ handlers 70 | * 71 | * \param [IN] irqHandlers Array containing the IRQ callback functions 72 | */ 73 | void SX1276IoIrqInit( DioIrqHandler **irqHandlers ); 74 | 75 | /*! 76 | * \brief De-initializes the radio I/Os pins interface. 77 | * 78 | * \remark Useful when going in MCU low power modes 79 | */ 80 | void SX1276IoDeInit( void ); 81 | 82 | /*! 83 | * \brief Initializes the TCXO power pin. 84 | */ 85 | void SX1276IoTcxoInit( void ); 86 | 87 | /*! 88 | * \brief Initializes the radio debug pins. 89 | */ 90 | void SX1276IoDbgInit( void ); 91 | 92 | /*! 93 | * \brief Resets the radio 94 | */ 95 | void SX1276Reset( void ); 96 | 97 | /*! 98 | * \brief Sets the radio output power. 99 | * 100 | * \param [IN] power Sets the RF output power 101 | */ 102 | void SX1276SetRfTxPower( int8_t power ); 103 | 104 | /*! 105 | * \brief Set the RF Switch I/Os pins in low power mode 106 | * 107 | * \param [IN] status enable or disable 108 | */ 109 | void SX1276SetAntSwLowPower( bool status ); 110 | 111 | /*! 112 | * \brief Initializes the RF Switch I/Os pins interface 113 | */ 114 | void SX1276AntSwInit( void ); 115 | 116 | /*! 117 | * \brief De-initializes the RF Switch I/Os pins interface 118 | * 119 | * \remark Needed to decrease the power consumption in MCU low power modes 120 | */ 121 | void SX1276AntSwDeInit( void ); 122 | 123 | /*! 124 | * \brief Controls the antenna switch if necessary. 125 | * 126 | * \remark see errata note 127 | * 128 | * \param [IN] opMode Current radio operating mode 129 | */ 130 | void SX1276SetAntSw( uint8_t opMode ); 131 | 132 | /*! 133 | * \brief Checks if the given RF frequency is supported by the hardware 134 | * 135 | * \param [IN] frequency RF frequency to be checked 136 | * \retval isSupported [true: supported, false: unsupported] 137 | */ 138 | bool SX1276CheckRfFrequency( uint32_t frequency ); 139 | 140 | /*! 141 | * \brief Enables/disables the TCXO if available on board design. 142 | * 143 | * \param [IN] state TCXO enabled when true and disabled when false. 144 | */ 145 | void SX1276SetBoardTcxo( uint8_t state ); 146 | 147 | /*! 148 | * \brief Gets the Defines the time required for the TCXO to wakeup [ms]. 149 | * 150 | * \retval time Board TCXO wakeup time in ms. 151 | */ 152 | uint32_t SX1276GetBoardTcxoWakeupTime( void ); 153 | 154 | /*! 155 | * \brief Gets current state of DIO1 pin state (FifoLevel). 156 | * 157 | * \retval state DIO1 pin current state. 158 | */ 159 | uint32_t SX1276GetDio1PinState( void ); 160 | 161 | /*! 162 | * \brief Writes new Tx debug pin state 163 | * 164 | * \param [IN] state Debug pin state 165 | */ 166 | void SX1276DbgPinTxWrite( uint8_t state ); 167 | 168 | /*! 169 | * \brief Writes new Rx debug pin state 170 | * 171 | * \param [IN] state Debug pin state 172 | */ 173 | void SX1276DbgPinRxWrite( uint8_t state ); 174 | 175 | /*! 176 | * Radio hardware and global parameters 177 | */ 178 | extern SX1276_t SX1276; 179 | 180 | #ifdef __cplusplus 181 | } 182 | #endif 183 | 184 | #endif // __SX1276_BOARD_H__ 185 | -------------------------------------------------------------------------------- /src/system.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYSTEM_H 2 | #define _SYSTEM_H 3 | 4 | #include 5 | 6 | extern volatile unsigned system_stop_lock; 7 | extern volatile unsigned system_sleep_lock; 8 | 9 | //! @brief System init 10 | 11 | void system_init(void); 12 | 13 | //! @brief Get a pseudo-random seed generated using the MCU Unique ID 14 | 15 | uint32_t system_get_random_seed(void); 16 | 17 | //! @brief This function returns a unique ID 18 | //! @param[out] id Pointer to the destination buffer, size 8 bytes 19 | 20 | void system_get_unique_id(uint8_t *id); 21 | 22 | //! @brief Aait on HSI 23 | 24 | void system_wait_hsi(void); 25 | 26 | //! @brief Sleep lock and Stop mode mask 27 | typedef enum 28 | { 29 | SYSTEM_MODULE_RTC = (1 << 0), 30 | SYSTEM_MODULE_LPUART_RX = (1 << 1), 31 | SYSTEM_MODULE_LPUART_TX = (1 << 2), 32 | SYSTEM_MODULE_USART = (1 << 3), 33 | SYSTEM_MODULE_RADIO = (1 << 4), 34 | SYSTEM_MODULE_ATCI = (1 << 5), 35 | SYSTEM_MODULE_NVM = (1 << 6), 36 | SYSTEM_MODULE_LORA = (1 << 7) 37 | } system_module_t; 38 | 39 | 40 | //! @brief Go to low power, sleep mode, or stop mode. The function must be 41 | //! invoked with interrupts disabled. 42 | 43 | void system_idle(void); 44 | 45 | //! @brief This function is called on an enter to the stop mode (weak) 46 | 47 | void system_before_stop(void); 48 | 49 | //! @brief This function is called on an exit from the stop mode (weak) 50 | 51 | void system_after_stop(void); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | bool check_block_crc(const void *ptr, size_t size) 8 | { 9 | uint32_t crc; 10 | size_t len; 11 | 12 | if (ptr == NULL || size < sizeof(crc)) return false; 13 | len = size - sizeof(crc); 14 | 15 | // Read the CRC value into a local variable in case the value in the buffer 16 | // isn't properly aligned. 17 | memcpy(&crc, (uint8_t *)ptr + len, sizeof(crc)); 18 | 19 | uint32_t s = Crc32Init(); 20 | 21 | for (unsigned int i = 0; i < len;) { 22 | // Crc32Update only accepts blocks up to UINT16_MAX 23 | s = Crc32Update(s, (uint8_t *)ptr + i, (len - i) > UINT16_MAX ? UINT16_MAX : len); 24 | i += (len - i) > UINT16_MAX ? UINT16_MAX : len; 25 | } 26 | 27 | return Crc32Finalize(s) == crc; 28 | } 29 | 30 | 31 | bool update_block_crc(const void *ptr, size_t size) 32 | { 33 | uint32_t old, new; 34 | size_t len; 35 | 36 | if (ptr == NULL || size < sizeof(old)) return false; 37 | len = size - sizeof(old); 38 | 39 | memcpy(&old, (uint8_t *)ptr + len, sizeof(old)); 40 | 41 | uint32_t s = Crc32Init(); 42 | 43 | for (unsigned int i = 0; i < len;) { 44 | // Crc32Update only accepts blocks up to UINT16_MAX 45 | s = Crc32Update(s, (uint8_t *)ptr + i, (len - i) > UINT16_MAX ? UINT16_MAX : len); 46 | i += (len - i) > UINT16_MAX ? UINT16_MAX : len; 47 | } 48 | 49 | new = Crc32Finalize(s); 50 | 51 | if (old != new) { 52 | memcpy((uint8_t *)ptr + len, &new, sizeof(new)); 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | 60 | unsigned int uint2strlen(uint32_t number) 61 | { 62 | if (number < 10) return 1; 63 | if (number < 100) return 2; 64 | if (number < 1000) return 3; 65 | if (number < 10000) return 4; 66 | if (number < 100000) return 5; 67 | if (number < 1000000) return 6; 68 | if (number < 10000000) return 7; 69 | if (number < 100000000) return 8; 70 | if (number < 1000000000) return 8; 71 | return 10; 72 | } 73 | 74 | 75 | SysTime_t uart_tx_delay(unsigned baudrate, unsigned int bytes) 76 | { 77 | SysTime_t delay; 78 | 79 | // We assume one start bit, eight data bits, one stop bit, and no parity. 80 | unsigned int bits = bytes * (1 + 8 + 1); 81 | 82 | delay.Seconds = bits / baudrate; 83 | delay.SubSeconds = (bits % baudrate) * 1000 / baudrate; 84 | return delay; 85 | } 86 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0])) 9 | 10 | bool check_block_crc(const void *ptr, size_t size); 11 | 12 | // Returns true if the CRC value changed 13 | bool update_block_crc(const void *ptr, size_t size); 14 | 15 | // Calculate the length of the string representation of the given number 16 | unsigned int uint2strlen(uint32_t number); 17 | 18 | // Calculate the time it takes to transmit the given number of bytes over UART 19 | // with given baud rate 20 | SysTime_t uart_tx_delay(unsigned speed, unsigned int bytes); 21 | 22 | #endif // _UTILS_H_ 23 | -------------------------------------------------------------------------------- /tools/jlink/flash.jlink: -------------------------------------------------------------------------------- 1 | si 1 2 | speed 4000 3 | r 4 | loadbin firmware.bin,0x08000000 5 | r 6 | exit 7 | -------------------------------------------------------------------------------- /tools/ozone/ozone.jdebug: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * 3 | * OnProjectLoad 4 | * 5 | * Function description 6 | * Project load routine. Required. 7 | * 8 | ********************************************************************** 9 | */ 10 | void OnProjectLoad (void) { 11 | 12 | Project.SetDevice ("STM32L072CZ"); 13 | Project.SetHostIF ("USB", ""); 14 | Project.SetTargetIF ("SWD"); 15 | Project.SetTIFSpeed ("1 MHz"); 16 | Project.SetRootPath("./"); 17 | Project.AddSvdFile ("Cortex-M0.svd"); 18 | Project.AddSvdFile ("tools/ozone/stm32l0x3.svd"); 19 | File.Open ("out/debug/firmware.elf"); 20 | Debug.Start (); 21 | } 22 | 23 | /********************************************************************* 24 | * 25 | * TargetReset 26 | * 27 | * Function description 28 | * Replaces the default target device reset routine. Optional. 29 | * 30 | * Notes 31 | * This example demonstrates the usage when 32 | * debugging a RAM program on a Cortex-M target device 33 | * 34 | ********************************************************************** 35 | */ 36 | /* 37 | void TargetReset (void) { 38 | 39 | unsigned int SP; 40 | unsigned int PC; 41 | unsigned int VectorTableAddr; 42 | 43 | Exec.Reset(); 44 | 45 | VectorTableAddr = Elf.GetBaseAddr(); 46 | 47 | if (VectorTableAddr != 0xFFFFFFFF) { 48 | 49 | Util.Log("Resetting Program."); 50 | 51 | SP = Target.ReadU32(VectorTableAddr); 52 | Target.SetReg("SP", SP); 53 | 54 | PC = Target.ReadU32(VectorTableAddr + 4); 55 | Target.SetReg("PC", PC); 56 | } 57 | } 58 | */ 59 | 60 | /********************************************************************* 61 | * 62 | * BeforeTargetReset 63 | * 64 | * Function description 65 | * Event handler routine. Optional. 66 | * 67 | ********************************************************************** 68 | */ 69 | /* 70 | void BeforeTargetReset (void) { 71 | } 72 | */ 73 | 74 | /********************************************************************* 75 | * 76 | * AfterTargetReset 77 | * 78 | * Function description 79 | * Event handler routine. Optional. 80 | * 81 | ********************************************************************** 82 | */ 83 | /* 84 | void AfterTargetReset (void) { 85 | } 86 | */ 87 | 88 | /********************************************************************* 89 | * 90 | * DebugStart 91 | * 92 | * Function description 93 | * Replaces the default debug session startup routine. Optional. 94 | * 95 | ********************************************************************** 96 | */ 97 | /* 98 | void DebugStart (void) { 99 | } 100 | */ 101 | 102 | /********************************************************************* 103 | * 104 | * TargetConnect 105 | * 106 | * Function description 107 | * Replaces the default target device connect routine. Optional. 108 | * 109 | ********************************************************************** 110 | */ 111 | /* 112 | void TargetConnect (void) { 113 | } 114 | */ 115 | 116 | /********************************************************************* 117 | * 118 | * BeforeTargetConnect 119 | * 120 | * Function description 121 | * Event handler routine. Optional. 122 | * 123 | ********************************************************************** 124 | */ 125 | /* 126 | void BeforeTargetConnect (void) { 127 | } 128 | */ 129 | 130 | /********************************************************************* 131 | * 132 | * AfterTargetConnect 133 | * 134 | * Function description 135 | * Event handler routine. Optional. 136 | * 137 | ********************************************************************** 138 | */ 139 | /* 140 | void AfterTargetConnect (void) { 141 | } 142 | */ 143 | 144 | /********************************************************************* 145 | * 146 | * TargetDownload 147 | * 148 | * Function description 149 | * Replaces the default program download routine. Optional. 150 | * 151 | ********************************************************************** 152 | */ 153 | /* 154 | void TargetDownload (void) { 155 | } 156 | */ 157 | 158 | /********************************************************************* 159 | * 160 | * BeforeTargetDownload 161 | * 162 | * Function description 163 | * Event handler routine. Optional. 164 | * 165 | ********************************************************************** 166 | */ 167 | void BeforeTargetDownload (void) { 168 | Debug.Halt(); 169 | } 170 | 171 | /********************************************************************* 172 | * 173 | * AfterTargetDownload 174 | * 175 | * Function description 176 | * Event handler routine. 177 | * 178 | * Notes 179 | * This sample implementation demonstrates the application 180 | * initialization on a Cortex-M target. 181 | * If no initialization can be done, Target.Reset() may be called. 182 | * 183 | ********************************************************************** 184 | */ 185 | /* 186 | void AfterTargetDownload (void) { 187 | } 188 | */ 189 | 190 | /********************************************************************* 191 | * 192 | * BeforeTargetDisconnect 193 | * 194 | * Function description 195 | * Event handler routine. Optional. 196 | * 197 | ********************************************************************** 198 | */ 199 | /* 200 | void BeforeTargetDisconnect (void) { 201 | } 202 | */ 203 | 204 | /********************************************************************* 205 | * 206 | * AfterTargetDisconnect 207 | * 208 | * Function description 209 | * Event handler routine. Optional. 210 | * 211 | ********************************************************************** 212 | */ 213 | /* 214 | void AfterTargetDisconnect (void) { 215 | } 216 | */ 217 | 218 | /********************************************************************* 219 | * 220 | * AfterTargetHalt 221 | * 222 | * Function description 223 | * Event handler routine. Optional. 224 | * 225 | ********************************************************************** 226 | */ 227 | /* 228 | void AfterTargetHalt (void) { 229 | } 230 | */ 231 | 232 | /********************************************************************* 233 | * 234 | * BeforeTargetResume 235 | * 236 | * Function description 237 | * Event handler routine. Optional. 238 | * 239 | ********************************************************************** 240 | */ 241 | /* 242 | void BeforeTargetResume (void) { 243 | } 244 | */ 245 | --------------------------------------------------------------------------------