From bb3b6ada069c3d0b51fdd82abb67620077904ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C5=BDaitl=C3=ADk?= Date: Thu, 21 Oct 2021 22:45:22 +0200 Subject: [PATCH] Moved the old firmware for STM32L011 to fw_old and migrated the firmware to STM32L031 in fw. I2C and TIM21 seem functional. USART2 is receiving correctly, but the modbus test is not receiving messages. --- fw/.cproject | 583 +- fw/.mxproject | 6 +- fw/.project | 1 - fw/.settings/stm32cubeide.project.prefs | 5 +- fw/Core/Inc/main.h | 12 +- fw/Core/Inc/stm32l0xx_it.h | 2 +- fw/Core/Src/i2c.c | 2 +- fw/Core/Src/main.c | 243 +- fw/Core/Src/stm32l0xx_it.c | 53 +- fw/Core/Startup/startup_stm32l031g6ux.s | 261 + .../Device/ST/STM32L0xx/Include/stm32l031xx.h | 6094 +++++++++++ .../Device/ST/STM32L0xx/Include/stm32l0xx.h | 42 +- .../Inc/stm32l0xx_ll_cortex.h | 2 +- .../Inc/stm32l0xx_ll_i2c.h | 231 +- .../Inc/stm32l0xx_ll_tim.h | 103 +- .../Inc/stm32l0xx_ll_usart.h | 3751 +++++++ .../Src/stm32l0xx_ll_i2c.c | 6 +- .../Src/stm32l0xx_ll_rcc.c | 20 +- .../Src/stm32l0xx_ll_tim.c | 21 +- .../Src/stm32l0xx_ll_usart.c | 420 + fw/STM32L031G6UX_FLASH.ld | 186 + fw/iaq_wired_sensor Debug.launch | 21 +- fw/iaq_wired_sensor.ioc | 100 +- fw_old/.cproject | 396 + fw_old/.mxproject | 24 + fw_old/.project | 33 + .../org.eclipse.cdt.codan.core.prefs | 72 + fw_old/.settings/org.eclipse.cdt.core.prefs | 6 + fw_old/.settings/stm32cubeide.project.prefs | 3 + fw_old/Core/Inc/config.h | 145 + fw_old/Core/Inc/crc8.h | 22 + fw_old/Core/Inc/i2c.h | 46 + fw_old/Core/Inc/main.h | 120 + fw_old/Core/Inc/modbus.h | 181 + fw_old/Core/Inc/scd4x.h | 57 + fw_old/Core/Inc/sht4x.h | 57 + fw_old/Core/Inc/sps30.h | 78 + fw_old/Core/Inc/stm32_assert.h | 53 + fw_old/Core/Inc/stm32l0xx_it.h | 65 + fw_old/Core/Src/config.c | 243 + fw_old/Core/Src/crc8.c | 28 + fw_old/Core/Src/i2c.c | 78 + fw_old/Core/Src/main.c | 827 ++ fw_old/Core/Src/modbus.c | 265 + fw_old/Core/Src/scd4x.c | 106 + fw_old/Core/Src/sht4x.c | 58 + fw_old/Core/Src/sps30.c | 193 + fw_old/Core/Src/stm32l0xx_it.c | 208 + fw_old/Core/Src/syscalls.c | 159 + fw_old/Core/Src/sysmem.c | 80 + fw_old/Core/Src/system_stm32l0xx.c | 275 + .../Core/Startup/startup_stm32l011f4ux.s | 0 fw_old/Debug/Core/Src/config.d | 24 + fw_old/Debug/Core/Src/config.o | Bin 0 -> 292872 bytes fw_old/Debug/Core/Src/config.su | 7 + fw_old/Debug/Core/Src/crc8.d | 3 + fw_old/Debug/Core/Src/crc8.o | Bin 0 -> 30196 bytes fw_old/Debug/Core/Src/crc8.su | 1 + fw_old/Debug/Core/Src/i2c.d | 30 + fw_old/Debug/Core/Src/i2c.o | Bin 0 -> 300872 bytes fw_old/Debug/Core/Src/i2c.su | 11 + fw_old/Debug/Core/Src/main.d | 80 + fw_old/Debug/Core/Src/main.o | Bin 0 -> 387780 bytes fw_old/Debug/Core/Src/main.su | 63 + fw_old/Debug/Core/Src/modbus.d | 3 + fw_old/Debug/Core/Src/modbus.o | Bin 0 -> 39052 bytes fw_old/Debug/Core/Src/modbus.su | 4 + fw_old/Debug/Core/Src/scd4x.d | 82 + fw_old/Debug/Core/Src/scd4x.o | Bin 0 -> 347920 bytes fw_old/Debug/Core/Src/scd4x.su | 6 + fw_old/Debug/Core/Src/sht4x.d | 82 + fw_old/Debug/Core/Src/sht4x.o | Bin 0 -> 346532 bytes fw_old/Debug/Core/Src/sht4x.su | 3 + fw_old/Debug/Core/Src/sps30.d | 35 + fw_old/Debug/Core/Src/sps30.o | Bin 0 -> 298684 bytes fw_old/Debug/Core/Src/sps30.su | 11 + fw_old/Debug/Core/Src/stm32l0xx_it.d | 84 + fw_old/Debug/Core/Src/stm32l0xx_it.o | Bin 0 -> 351700 bytes fw_old/Debug/Core/Src/stm32l0xx_it.su | 15 + fw_old/Debug/Core/Src/subdir.mk | 53 + fw_old/Debug/Core/Src/syscalls.d | 1 + fw_old/Debug/Core/Src/syscalls.o | Bin 0 -> 81416 bytes fw_old/Debug/Core/Src/syscalls.su | 18 + fw_old/Debug/Core/Src/sysmem.d | 1 + fw_old/Debug/Core/Src/sysmem.o | Bin 0 -> 51396 bytes fw_old/Debug/Core/Src/sysmem.su | 1 + fw_old/Debug/Core/Src/system_stm32l0xx.d | 22 + fw_old/Debug/Core/Src/system_stm32l0xx.o | Bin 0 -> 286892 bytes fw_old/Debug/Core/Src/system_stm32l0xx.su | 2 + .../Core/Startup/startup_stm32l011f4ux.d | 2 + .../Core/Startup/startup_stm32l011f4ux.o | Bin 0 -> 4072 bytes fw_old/Debug/Core/Startup/subdir.mk | 20 + .../Src/stm32l0xx_ll_dma.d | 29 + .../Src/stm32l0xx_ll_dma.o | Bin 0 -> 303204 bytes .../Src/stm32l0xx_ll_dma.su | 15 + .../Src/stm32l0xx_ll_exti.d | 26 + .../Src/stm32l0xx_ll_exti.o | Bin 0 -> 292532 bytes .../Src/stm32l0xx_ll_exti.su | 11 + .../Src/stm32l0xx_ll_gpio.d | 29 + .../Src/stm32l0xx_ll_gpio.o | Bin 0 -> 296692 bytes .../Src/stm32l0xx_ll_gpio.su | 11 + .../Src/stm32l0xx_ll_i2c.d | 29 + .../Src/stm32l0xx_ll_i2c.o | Bin 0 -> 299816 bytes .../Src/stm32l0xx_ll_i2c.su | 14 + .../Src/stm32l0xx_ll_lpuart.d | 32 + .../Src/stm32l0xx_ll_lpuart.o | Bin 0 -> 306288 bytes .../Src/stm32l0xx_ll_lpuart.su | 9 + .../Src/stm32l0xx_ll_pwr.d | 29 + .../Src/stm32l0xx_ll_pwr.o | Bin 0 -> 289952 bytes .../Src/stm32l0xx_ll_pwr.su | 3 + .../Src/stm32l0xx_ll_rcc.d | 26 + .../Src/stm32l0xx_ll_rcc.o | Bin 0 -> 310784 bytes .../Src/stm32l0xx_ll_rcc.su | 35 + .../Src/stm32l0xx_ll_tim.d | 29 + .../Src/stm32l0xx_ll_tim.o | Bin 0 -> 320384 bytes .../Src/stm32l0xx_ll_tim.su | 29 + .../Src/stm32l0xx_ll_utils.d | 35 + .../Src/stm32l0xx_ll_utils.o | Bin 0 -> 316372 bytes .../Src/stm32l0xx_ll_utils.su | 27 + .../STM32L0xx_HAL_Driver/Src/subdir.mk | 44 + fw_old/Debug/iaq_wired_sensor.bin | Bin 0 -> 14172 bytes fw_old/Debug/iaq_wired_sensor.elf | Bin 0 -> 532828 bytes fw_old/Debug/iaq_wired_sensor.list | 9342 +++++++++++++++++ fw_old/Debug/iaq_wired_sensor.map | 2389 +++++ fw_old/Debug/makefile | 100 + fw_old/Debug/objects.list | 22 + fw_old/Debug/objects.mk | 9 + fw_old/Debug/sources.mk | 26 + .../Device/ST/STM32L0xx/Include/stm32l011xx.h | 0 .../Device/ST/STM32L0xx/Include/stm32l0xx.h | 235 + .../ST/STM32L0xx/Include/system_stm32l0xx.h | 109 + fw_old/Drivers/CMSIS/Include/cmsis_armcc.h | 865 ++ fw_old/Drivers/CMSIS/Include/cmsis_armclang.h | 1869 ++++ fw_old/Drivers/CMSIS/Include/cmsis_compiler.h | 266 + fw_old/Drivers/CMSIS/Include/cmsis_gcc.h | 2085 ++++ fw_old/Drivers/CMSIS/Include/cmsis_iccarm.h | 935 ++ fw_old/Drivers/CMSIS/Include/cmsis_version.h | 39 + fw_old/Drivers/CMSIS/Include/core_armv8mbl.h | 1918 ++++ fw_old/Drivers/CMSIS/Include/core_armv8mml.h | 2927 ++++++ fw_old/Drivers/CMSIS/Include/core_cm0.h | 949 ++ fw_old/Drivers/CMSIS/Include/core_cm0plus.h | 1083 ++ fw_old/Drivers/CMSIS/Include/core_cm1.h | 976 ++ fw_old/Drivers/CMSIS/Include/core_cm23.h | 1993 ++++ fw_old/Drivers/CMSIS/Include/core_cm3.h | 1941 ++++ fw_old/Drivers/CMSIS/Include/core_cm33.h | 3002 ++++++ fw_old/Drivers/CMSIS/Include/core_cm4.h | 2129 ++++ fw_old/Drivers/CMSIS/Include/core_cm7.h | 2671 +++++ fw_old/Drivers/CMSIS/Include/core_sc000.h | 1022 ++ fw_old/Drivers/CMSIS/Include/core_sc300.h | 1915 ++++ fw_old/Drivers/CMSIS/Include/mpu_armv7.h | 270 + fw_old/Drivers/CMSIS/Include/mpu_armv8.h | 333 + fw_old/Drivers/CMSIS/Include/tz_context.h | 70 + .../Inc/stm32l0xx_ll_bus.h | 1171 +++ .../Inc/stm32l0xx_ll_cortex.h | 590 ++ .../Inc/stm32l0xx_ll_crs.h | 798 ++ .../Inc/stm32l0xx_ll_dma.h | 2129 ++++ .../Inc/stm32l0xx_ll_exti.h | 1016 ++ .../Inc/stm32l0xx_ll_gpio.h | 945 ++ .../Inc/stm32l0xx_ll_i2c.h | 2230 ++++ .../Inc/stm32l0xx_ll_lpuart.h | 0 .../Inc/stm32l0xx_ll_pwr.h | 746 ++ .../Inc/stm32l0xx_ll_rcc.h | 2497 +++++ .../Inc/stm32l0xx_ll_system.h | 1089 ++ .../Inc/stm32l0xx_ll_tim.h | 3289 ++++++ .../Inc/stm32l0xx_ll_utils.h | 269 + .../Src/stm32l0xx_ll_dma.c | 379 + .../Src/stm32l0xx_ll_exti.c | 214 + .../Src/stm32l0xx_ll_gpio.c | 263 + .../Src/stm32l0xx_ll_i2c.c | 239 + .../Src/stm32l0xx_ll_lpuart.c | 0 .../Src/stm32l0xx_ll_pwr.c | 85 + .../Src/stm32l0xx_ll_rcc.c | 698 ++ .../Src/stm32l0xx_ll_tim.c | 847 ++ .../Src/stm32l0xx_ll_utils.c | 591 ++ {fw => fw_old}/STM32L011F4UX_FLASH.ld | 0 fw_old/iaq_wired_sensor Debug.launch | 73 + fw_old/iaq_wired_sensor.ioc | 150 + 177 files changed, 78202 insertions(+), 765 deletions(-) create mode 100644 fw/Core/Startup/startup_stm32l031g6ux.s create mode 100644 fw/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l031xx.h create mode 100644 fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h create mode 100644 fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c create mode 100644 fw/STM32L031G6UX_FLASH.ld create mode 100644 fw_old/.cproject create mode 100644 fw_old/.mxproject create mode 100644 fw_old/.project create mode 100644 fw_old/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 fw_old/.settings/org.eclipse.cdt.core.prefs create mode 100644 fw_old/.settings/stm32cubeide.project.prefs create mode 100644 fw_old/Core/Inc/config.h create mode 100644 fw_old/Core/Inc/crc8.h create mode 100644 fw_old/Core/Inc/i2c.h create mode 100644 fw_old/Core/Inc/main.h create mode 100644 fw_old/Core/Inc/modbus.h create mode 100644 fw_old/Core/Inc/scd4x.h create mode 100644 fw_old/Core/Inc/sht4x.h create mode 100644 fw_old/Core/Inc/sps30.h create mode 100644 fw_old/Core/Inc/stm32_assert.h create mode 100644 fw_old/Core/Inc/stm32l0xx_it.h create mode 100644 fw_old/Core/Src/config.c create mode 100644 fw_old/Core/Src/crc8.c create mode 100644 fw_old/Core/Src/i2c.c create mode 100644 fw_old/Core/Src/main.c create mode 100644 fw_old/Core/Src/modbus.c create mode 100644 fw_old/Core/Src/scd4x.c create mode 100644 fw_old/Core/Src/sht4x.c create mode 100644 fw_old/Core/Src/sps30.c create mode 100644 fw_old/Core/Src/stm32l0xx_it.c create mode 100644 fw_old/Core/Src/syscalls.c create mode 100644 fw_old/Core/Src/sysmem.c create mode 100644 fw_old/Core/Src/system_stm32l0xx.c rename {fw => fw_old}/Core/Startup/startup_stm32l011f4ux.s (100%) create mode 100644 fw_old/Debug/Core/Src/config.d create mode 100644 fw_old/Debug/Core/Src/config.o create mode 100644 fw_old/Debug/Core/Src/config.su create mode 100644 fw_old/Debug/Core/Src/crc8.d create mode 100644 fw_old/Debug/Core/Src/crc8.o create mode 100644 fw_old/Debug/Core/Src/crc8.su create mode 100644 fw_old/Debug/Core/Src/i2c.d create mode 100644 fw_old/Debug/Core/Src/i2c.o create mode 100644 fw_old/Debug/Core/Src/i2c.su create mode 100644 fw_old/Debug/Core/Src/main.d create mode 100644 fw_old/Debug/Core/Src/main.o create mode 100644 fw_old/Debug/Core/Src/main.su create mode 100644 fw_old/Debug/Core/Src/modbus.d create mode 100644 fw_old/Debug/Core/Src/modbus.o create mode 100644 fw_old/Debug/Core/Src/modbus.su create mode 100644 fw_old/Debug/Core/Src/scd4x.d create mode 100644 fw_old/Debug/Core/Src/scd4x.o create mode 100644 fw_old/Debug/Core/Src/scd4x.su create mode 100644 fw_old/Debug/Core/Src/sht4x.d create mode 100644 fw_old/Debug/Core/Src/sht4x.o create mode 100644 fw_old/Debug/Core/Src/sht4x.su create mode 100644 fw_old/Debug/Core/Src/sps30.d create mode 100644 fw_old/Debug/Core/Src/sps30.o create mode 100644 fw_old/Debug/Core/Src/sps30.su create mode 100644 fw_old/Debug/Core/Src/stm32l0xx_it.d create mode 100644 fw_old/Debug/Core/Src/stm32l0xx_it.o create mode 100644 fw_old/Debug/Core/Src/stm32l0xx_it.su create mode 100644 fw_old/Debug/Core/Src/subdir.mk create mode 100644 fw_old/Debug/Core/Src/syscalls.d create mode 100644 fw_old/Debug/Core/Src/syscalls.o create mode 100644 fw_old/Debug/Core/Src/syscalls.su create mode 100644 fw_old/Debug/Core/Src/sysmem.d create mode 100644 fw_old/Debug/Core/Src/sysmem.o create mode 100644 fw_old/Debug/Core/Src/sysmem.su create mode 100644 fw_old/Debug/Core/Src/system_stm32l0xx.d create mode 100644 fw_old/Debug/Core/Src/system_stm32l0xx.o create mode 100644 fw_old/Debug/Core/Src/system_stm32l0xx.su create mode 100644 fw_old/Debug/Core/Startup/startup_stm32l011f4ux.d create mode 100644 fw_old/Debug/Core/Startup/startup_stm32l011f4ux.o create mode 100644 fw_old/Debug/Core/Startup/subdir.mk create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.d create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.o create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.su create mode 100644 fw_old/Debug/Drivers/STM32L0xx_HAL_Driver/Src/subdir.mk create mode 100755 fw_old/Debug/iaq_wired_sensor.bin create mode 100755 fw_old/Debug/iaq_wired_sensor.elf create mode 100644 fw_old/Debug/iaq_wired_sensor.list create mode 100644 fw_old/Debug/iaq_wired_sensor.map create mode 100644 fw_old/Debug/makefile create mode 100644 fw_old/Debug/objects.list create mode 100644 fw_old/Debug/objects.mk create mode 100644 fw_old/Debug/sources.mk rename {fw => fw_old}/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h (100%) create mode 100644 fw_old/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h create mode 100644 fw_old/Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_armcc.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_armclang.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_compiler.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_gcc.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_iccarm.h create mode 100644 fw_old/Drivers/CMSIS/Include/cmsis_version.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_armv8mbl.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_armv8mml.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm0.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm0plus.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm1.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm23.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm3.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm33.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm4.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_cm7.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_sc000.h create mode 100644 fw_old/Drivers/CMSIS/Include/core_sc300.h create mode 100644 fw_old/Drivers/CMSIS/Include/mpu_armv7.h create mode 100644 fw_old/Drivers/CMSIS/Include/mpu_armv8.h create mode 100644 fw_old/Drivers/CMSIS/Include/tz_context.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h rename {fw => fw_old}/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h (100%) create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c rename {fw => fw_old}/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c (100%) create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c create mode 100644 fw_old/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c rename {fw => fw_old}/STM32L011F4UX_FLASH.ld (100%) create mode 100644 fw_old/iaq_wired_sensor Debug.launch create mode 100644 fw_old/iaq_wired_sensor.ioc diff --git a/fw/.cproject b/fw/.cproject index 30a87ca..0005a9c 100644 --- a/fw/.cproject +++ b/fw/.cproject @@ -1,396 +1,191 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fw/.mxproject b/fw/.mxproject index 4d4db74..13a39f9 100644 --- a/fw/.mxproject +++ b/fw/.mxproject @@ -1,10 +1,10 @@ [PreviousLibFiles] -LibFiles=Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/core_cm3.h; +LibFiles=Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l031xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/core_cm3.h; [PreviousUsedCubeIDEFiles] -SourceFiles=Core/Src/main.c;Core/Src/stm32l0xx_it.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Core/Src/system_stm32l0xx.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Core/Src/system_stm32l0xx.c;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;; +SourceFiles=Core/Src/main.c;Core/Src/stm32l0xx_it.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;Core/Src/system_stm32l0xx.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;Core/Src/system_stm32l0xx.c;;; HeaderPath=Drivers/STM32L0xx_HAL_Driver/Inc;Drivers/CMSIS/Device/ST/STM32L0xx/Include;Drivers/CMSIS/Include;Core/Inc; -CDefines=USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1;STM32L011xx;USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1; +CDefines=USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1;STM32L031xx;USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1; [PreviousGenFiles] AdvancedFolderStructure=true diff --git a/fw/.project b/fw/.project index 6232ccb..17919b4 100644 --- a/fw/.project +++ b/fw/.project @@ -24,7 +24,6 @@ org.eclipse.cdt.core.cnature com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAev2ProjectNature com.st.stm32cube.ide.mcu.MCUAdvancedStructureProjectNature - com.st.stm32cube.ide.mcu.MCUEndUserDisabledTrustZoneProjectNature com.st.stm32cube.ide.mcu.MCUSingleCpuProjectNature com.st.stm32cube.ide.mcu.MCURootProjectNature org.eclipse.cdt.managedbuilder.core.managedBuildNature diff --git a/fw/.settings/stm32cubeide.project.prefs b/fw/.settings/stm32cubeide.project.prefs index ae186d6..2a751da 100644 --- a/fw/.settings/stm32cubeide.project.prefs +++ b/fw/.settings/stm32cubeide.project.prefs @@ -1,3 +1,4 @@ -8DF89ED150041C4CBC7CB9A9CAA90856=295E78E9D51884086204F31037537306 -DC22A860405A8BF2F2C095E5B6529F12=295E78E9D51884086204F31037537306 +66BE74F758C12D739921AEA421D593D3=11 +8DF89ED150041C4CBC7CB9A9CAA90856=807411C90E25B050C1E13646B7FEB5AA +DC22A860405A8BF2F2C095E5B6529F12=807411C90E25B050C1E13646B7FEB5AA eclipse.preferences.version=1 diff --git a/fw/Core/Inc/main.h b/fw/Core/Inc/main.h index a144a49..dd3504d 100644 --- a/fw/Core/Inc/main.h +++ b/fw/Core/Inc/main.h @@ -29,9 +29,8 @@ extern "C" { /* Includes ------------------------------------------------------------------*/ #include "stm32l0xx_ll_i2c.h" -#include "stm32l0xx_ll_lpuart.h" -#include "stm32l0xx_ll_rcc.h" #include "stm32l0xx_ll_crs.h" +#include "stm32l0xx_ll_rcc.h" #include "stm32l0xx_ll_bus.h" #include "stm32l0xx_ll_system.h" #include "stm32l0xx_ll_exti.h" @@ -40,6 +39,7 @@ extern "C" { #include "stm32l0xx_ll_pwr.h" #include "stm32l0xx_ll_dma.h" #include "stm32l0xx_ll_tim.h" +#include "stm32l0xx_ll_usart.h" #include "stm32l0xx_ll_gpio.h" #if defined(USE_FULL_ASSERT) @@ -102,10 +102,10 @@ int8_t uart_enable_interrupts(void); /* USER CODE BEGIN Private defines */ #define MEASUREMENT_PERIOD_MS 600000 -extern uint16_t lpuart1_rx_message_index; -extern uint16_t lpuart1_rx_message_len; -extern uint8_t lpuart1_rx_done; -extern uint8_t lpuart1_rx_message_too_long; +extern uint16_t usart2_rx_message_index; +extern uint16_t usart2_rx_message_len; +extern uint8_t usart2_rx_done; +extern uint8_t usart2_rx_message_too_long; extern uint8_t tim21_elapsed_period; diff --git a/fw/Core/Inc/stm32l0xx_it.h b/fw/Core/Inc/stm32l0xx_it.h index e4fecd6..c2f720d 100644 --- a/fw/Core/Inc/stm32l0xx_it.h +++ b/fw/Core/Inc/stm32l0xx_it.h @@ -52,7 +52,7 @@ void SVC_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void TIM21_IRQHandler(void); -void LPUART1_IRQHandler(void); +void USART2_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/fw/Core/Src/i2c.c b/fw/Core/Src/i2c.c index 07aeaaf..b0991b8 100644 --- a/fw/Core/Src/i2c.c +++ b/fw/Core/Src/i2c.c @@ -6,7 +6,7 @@ */ #include "i2c.h" -#include "stm32l0xx_ll_lpuart.h" +#include "stm32l0xx_ll_usart.h" i2c_context_t *i2c_context; diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c index 23f6270..930de14 100644 --- a/fw/Core/Src/main.c +++ b/fw/Core/Src/main.c @@ -118,10 +118,10 @@ uint8_t co2_valid = 0; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); -static void MX_LPUART1_UART_Init(void); +static void MX_USART2_UART_Init(void); static void MX_TIM21_Init(void); /* USER CODE BEGIN PFP */ -void LPUART1_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len); +void USART2_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ @@ -147,6 +147,8 @@ int main(void) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); /* System interrupt init*/ + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, 3); /* USER CODE BEGIN Init */ @@ -174,7 +176,7 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); - MX_LPUART1_UART_Init(); + MX_USART2_UART_Init(); MX_TIM21_Init(); /* USER CODE BEGIN 2 */ @@ -191,7 +193,7 @@ int main(void) modbus_slave_set_address(sensor_config.modbus_addr); /* Enable UART for RS485 */ - LL_LPUART_Enable(LPUART1); + LL_USART_Enable(USART2); /* Start the timer for measurement triggering */ LL_TIM_EnableCounter(TIM21); @@ -202,6 +204,8 @@ int main(void) i2c_context.i2c = I2C1; i2c_init(&i2c_context); + LL_mDelay(2000); + scd4x_start_periodic_measurement(); uint8_t scd4x_is_connected = 1; uint8_t sps30_is_connected = 0; @@ -227,34 +231,34 @@ int main(void) /* SHT4x Init Time: max 1 ms (datasheet pg. 8) */ /* SCD4x Init Time: max 1000 ms (datasheet pg. 6) */ /* SPS30 Init Time: max 30000 ms (datasheet pg. 2) */ - LL_mDelay(1000); + LL_mDelay(5000); static uint32_t new_baud; /* Enter the main loop */ while (1) { - if (lpuart1_rx_done == 1) + if (usart2_rx_done == 1) { /* Process the message */ - if (lpuart1_rx_message_too_long) + if (usart2_rx_message_too_long) { /* Do nothing, just delete the buffer and set the flag back to zero*/ - lpuart1_rx_message_too_long = 0; + usart2_rx_message_too_long = 0; } else { /* Process the message: * message is stored in modbus_buffer[], no copying necessary; * but we need to make sure that modbus_buffer[] will not be used while * processing the message: this can be done by disabling RX interrupt */ - LL_LPUART_DisableIT_RXNE(LPUART1); - modbus_slave_process_msg(modbus_buffer, lpuart1_rx_message_len); + LL_USART_DisableIT_RXNE(USART2); + modbus_slave_process_msg(modbus_buffer, usart2_rx_message_len); /* Reset the RX DONE flag */ - lpuart1_rx_done = 0; - LL_LPUART_EnableIT_RXNE(LPUART1); + usart2_rx_done = 0; + LL_USART_EnableIT_RXNE(USART2); } /* Reset the RX DONE flag */ - lpuart1_rx_done = 0; + usart2_rx_done = 0; } /* if config changed (MODBUS write), reflect changes to EEPROM */ if (sensor_config_pending_write) { @@ -268,23 +272,16 @@ int main(void) } if (baudrate_changed) { - while (!LL_LPUART_IsActiveFlag_TXE(LPUART1)); + while (!LL_USART_IsActiveFlag_TXE(USART2)); uart_disable_interrupts(); -// LL_LPUART_Disable(LPUART1); -// LL_LPUART_DisableIT_IDLE(LPUART1); -// LL_LPUART_EnableIT_RXNE(LPUART1); - LL_LPUART_SetBaudRate(LPUART1, SYSTICK_FREQ_HZ, config_baudrates[sensor_config.baudrate_index]); - -// LL_LPUART_Enable(LPUART1); -// LL_LPUART_EnableIT_IDLE(LPUART1); -// LL_LPUART_EnableIT_RXNE(LPUART1); + LL_USART_SetBaudRate(USART2, SYSTICK_FREQ_HZ, LL_USART_OVERSAMPLING_16, config_baudrates[sensor_config.baudrate_index]); uart_enable_interrupts(); - LL_LPUART_EnableDirectionRx(LPUART1); - LL_LPUART_EnableDirectionTx(LPUART1); + LL_USART_EnableDirectionRx(USART2); + LL_USART_EnableDirectionTx(USART2); baudrate_changed = 0; - new_baud = LL_LPUART_GetBaudRate(LPUART1, SYSTICK_FREQ_HZ); + new_baud = LL_USART_GetBaudRate(USART2, SYSTICK_FREQ_HZ, LL_USART_OVERSAMPLING_16); } /* It is time for measurement */ @@ -399,7 +396,7 @@ void SystemClock_Config(void) LL_Init1msTick(12000000); LL_SetSystemCoreClock(12000000); - LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1); + LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_PCLK1); LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1); } @@ -466,89 +463,6 @@ static void MX_I2C1_Init(void) } -/** - * @brief LPUART1 Initialization Function - * @param None - * @retval None - */ -static void MX_LPUART1_UART_Init(void) -{ - - /* USER CODE BEGIN LPUART1_Init 0 */ - - /* USER CODE END LPUART1_Init 0 */ - - LL_LPUART_InitTypeDef LPUART_InitStruct = {0}; - - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - - /* Peripheral clock enable */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPUART1); - - LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); - LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); - /**LPUART1 GPIO Configuration - PA0-CK_IN ------> LPUART1_RX - PA1 ------> LPUART1_TX - PB1 ------> LPUART1_DE - */ - GPIO_InitStruct.Pin = LL_GPIO_PIN_0; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; - GPIO_InitStruct.Alternate = LL_GPIO_AF_6; - LL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = LL_GPIO_PIN_1; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; - GPIO_InitStruct.Alternate = LL_GPIO_AF_6; - LL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = LL_GPIO_PIN_1; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_4; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - /* LPUART1 interrupt Init */ - NVIC_SetPriority(LPUART1_IRQn, 0); - NVIC_EnableIRQ(LPUART1_IRQn); - - /* USER CODE BEGIN LPUART1_Init 1 */ - - /* USER CODE END LPUART1_Init 1 */ - LPUART_InitStruct.BaudRate = config_baudrates[sensor_config.baudrate_index]; - LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_9B; - LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1; - LPUART_InitStruct.Parity = LL_LPUART_PARITY_EVEN; - LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX; - LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; - LL_LPUART_Init(LPUART1, &LPUART_InitStruct); - LL_LPUART_EnableDEMode(LPUART1); - LL_LPUART_SetDESignalPolarity(LPUART1, LL_LPUART_DE_POLARITY_HIGH); - LL_LPUART_SetDEAssertionTime(LPUART1, 0); - LL_LPUART_SetDEDeassertionTime(LPUART1, 0); - /* USER CODE BEGIN LPUART1_Init 2 */ - - /* Enable IDLE Interrupt */ - LL_LPUART_EnableIT_IDLE(LPUART1); - - /* Enable RX Not Empty Interrupt */ - LL_LPUART_EnableIT_RXNE(LPUART1); - - LL_LPUART_EnableDirectionRx(LPUART1); - LL_LPUART_EnableDirectionTx(LPUART1); - LL_LPUART_Enable(LPUART1); - /* USER CODE END LPUART1_Init 2 */ - -} - /** * @brief TIM21 Initialization Function * @param None @@ -588,6 +502,91 @@ static void MX_TIM21_Init(void) } +/** + * @brief USART2 Initialization Function + * @param None + * @retval None + */ +static void MX_USART2_UART_Init(void) +{ + + /* USER CODE BEGIN USART2_Init 0 */ + + /* USER CODE END USART2_Init 0 */ + + LL_USART_InitTypeDef USART_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); + + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + /**USART2 GPIO Configuration + PA1 ------> USART2_DE + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_1; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_2; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART2 interrupt Init */ + NVIC_SetPriority(USART2_IRQn, 0); + NVIC_EnableIRQ(USART2_IRQn); + + /* USER CODE BEGIN USART2_Init 1 */ + + /* USER CODE END USART2_Init 1 */ + USART_InitStruct.BaudRate = config_baudrates[sensor_config.baudrate_index]; + USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_9B; + USART_InitStruct.StopBits = LL_USART_STOPBITS_1; + USART_InitStruct.Parity = LL_USART_PARITY_EVEN; + USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; + LL_USART_Init(USART2, &USART_InitStruct); + LL_USART_EnableDEMode(USART2); + LL_USART_SetDESignalPolarity(USART2, LL_USART_DE_POLARITY_HIGH); + LL_USART_SetDEAssertionTime(USART2, 0); + LL_USART_SetDEDeassertionTime(USART2, 0); + LL_USART_ConfigAsyncMode(USART2); + LL_USART_Enable(USART2); + /* USER CODE BEGIN USART2_Init 2 */ + + /* Enable IDLE Interrupt */ + LL_USART_EnableIT_IDLE(USART2); + + /* Enable RX Not Empty Interrupt */ + LL_USART_EnableIT_RXNE(USART2); + + LL_USART_EnableDirectionRx(USART2); + LL_USART_EnableDirectionTx(USART2); + LL_USART_Enable(USART2); + /* USER CODE END USART2_Init 2 */ + +} + /** * @brief GPIO Initialization Function * @param None @@ -601,13 +600,13 @@ static void MX_GPIO_Init(void) LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); /**/ - LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin); /**/ - LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin); /**/ - LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin); /**/ GPIO_InitStruct.Pin = LED_B_Pin; @@ -636,31 +635,31 @@ static void MX_GPIO_Init(void) } /* USER CODE BEGIN 4 */ -void LPUART1_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len) +void USART2_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len) { __disable_irq(); for (uint16_t i = 0; i < buffer_tx_len; i++) { - LL_LPUART_TransmitData9(LPUART1, buffer_tx[i]); - while (!LL_LPUART_IsActiveFlag_TXE(LPUART1)); + LL_USART_TransmitData9(USART2, buffer_tx[i]); + while (!LL_USART_IsActiveFlag_TXE(USART2)); } __enable_irq(); } int8_t uart_disable_interrupts(void) { - LL_LPUART_Disable(LPUART1); - LL_LPUART_DisableIT_IDLE(LPUART1); - LL_LPUART_EnableIT_RXNE(LPUART1); + LL_USART_Disable(USART2); + LL_USART_DisableIT_IDLE(USART2); + LL_USART_EnableIT_RXNE(USART2); return 0; } int8_t uart_enable_interrupts(void) { - LL_LPUART_Enable(LPUART1); - LL_LPUART_EnableIT_IDLE(LPUART1); - LL_LPUART_EnableIT_RXNE(LPUART1); + LL_USART_Enable(USART2); + LL_USART_EnableIT_IDLE(USART2); + LL_USART_EnableIT_RXNE(USART2); return 0; } @@ -787,7 +786,7 @@ int8_t modbus_slave_callback(modbus_transaction_t *transaction) int8_t modbus_transmit_function(uint8_t *buffer, uint16_t data_len) { /* TODO */ - LPUART1_TX_Buffer(buffer, data_len); + USART2_TX_Buffer(buffer, data_len); return MODBUS_OK; } /* USER CODE END 4 */ diff --git a/fw/Core/Src/stm32l0xx_it.c b/fw/Core/Src/stm32l0xx_it.c index 504a5a5..5eb65f3 100644 --- a/fw/Core/Src/stm32l0xx_it.c +++ b/fw/Core/Src/stm32l0xx_it.c @@ -43,17 +43,17 @@ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ -uint16_t lpuart1_rx_message_index = 0; -uint16_t lpuart1_rx_message_len = 0; -uint8_t lpuart1_rx_done = 0; -uint8_t lpuart1_rx_message_too_long = 0; +uint16_t usart2_rx_message_index = 0; +uint16_t usart2_rx_message_len = 0; +uint8_t usart2_rx_done = 0; +uint8_t usart2_rx_message_too_long = 0; uint8_t tim21_elapsed_period = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ -void LPUART1_CharReception_Callback( void ); +void USART2_CharReception_Callback( void ); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ @@ -71,7 +71,7 @@ void LPUART1_CharReception_Callback( void ); /* Cortex-M0+ Processor Interruption and Exception Handlers */ /******************************************************************************/ /** - * @brief This function handles Non maskable interrupt. + * @brief This function handles Non maskable Interrupt. */ void NMI_Handler(void) { @@ -154,7 +154,6 @@ void TIM21_IRQHandler(void) /* USER CODE BEGIN TIM21_IRQn 0 */ LL_TIM_ClearFlag_UPDATE(TIM21); tim21_elapsed_period = 1; - /* USER CODE END TIM21_IRQn 0 */ /* USER CODE BEGIN TIM21_IRQn 1 */ @@ -162,47 +161,47 @@ void TIM21_IRQHandler(void) } /** - * @brief This function handles LPUART1 global interrupt / LPUART1 wake-up interrupt through EXTI line 28. + * @brief This function handles USART2 global interrupt / USART2 wake-up interrupt through EXTI line 26. */ -void LPUART1_IRQHandler(void) +void USART2_IRQHandler(void) { - /* USER CODE BEGIN LPUART1_IRQn 0 */ + /* USER CODE BEGIN USART2_IRQn 0 */ /* Check RXNE flag value in SR register */ - if(LL_LPUART_IsActiveFlag_RXNE(LPUART1) && LL_LPUART_IsEnabledIT_RXNE(LPUART1)) + if(LL_USART_IsActiveFlag_RXNE(USART2) && LL_USART_IsEnabledIT_RXNE(USART2)) { /* RXNE flag will be cleared by reading of DR register (done in call) */ /* Call function in charge of handling Character reception */ - LPUART1_CharReception_Callback(); + USART2_CharReception_Callback(); } - /* USER CODE END LPUART1_IRQn 0 */ - /* USER CODE BEGIN LPUART1_IRQn 1 */ + /* USER CODE END USART2_IRQn 0 */ + /* USER CODE BEGIN USART2_IRQn 1 */ /* If the IDLE flag is active */ - if (LL_LPUART_IsActiveFlag_IDLE(LPUART1) && LL_LPUART_IsEnabledIT_IDLE(LPUART1)) + if (LL_USART_IsActiveFlag_IDLE(USART2) && LL_USART_IsEnabledIT_IDLE(USART2)) { /* Clear the IDLE flag */ - LL_LPUART_ClearFlag_IDLE(LPUART1); + LL_USART_ClearFlag_IDLE(USART2); /* Reset the buffer index */ - lpuart1_rx_message_len = lpuart1_rx_message_index; - lpuart1_rx_message_index = 0; - lpuart1_rx_done = 1; - if (lpuart1_rx_message_len > MODBUS_MAX_RTU_FRAME_SIZE) + usart2_rx_message_len = usart2_rx_message_index; + usart2_rx_message_index = 0; + usart2_rx_done = 1; + if (usart2_rx_message_len > MODBUS_MAX_RTU_FRAME_SIZE) { - lpuart1_rx_message_too_long = 1; + usart2_rx_message_too_long = 1; } } - /* USER CODE END LPUART1_IRQn 1 */ + /* USER CODE END USART2_IRQn 1 */ } /* USER CODE BEGIN 1 */ -void LPUART1_CharReception_Callback( void ) +void USART2_CharReception_Callback( void ) { - uint16_t lpuart1_rx_bit = LL_LPUART_ReceiveData9(LPUART1); - if (lpuart1_rx_message_index < MODBUS_MAX_RTU_FRAME_SIZE) + uint16_t usart2_rx_bit = LL_USART_ReceiveData9(USART2); + if (usart2_rx_message_index < MODBUS_MAX_RTU_FRAME_SIZE) { - modbus_buffer[lpuart1_rx_message_index] = (uint8_t)lpuart1_rx_bit; + modbus_buffer[usart2_rx_message_index] = (uint8_t)usart2_rx_bit; } - lpuart1_rx_message_index++; + usart2_rx_message_index++; } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw/Core/Startup/startup_stm32l031g6ux.s b/fw/Core/Startup/startup_stm32l031g6ux.s new file mode 100644 index 0000000..62608af --- /dev/null +++ b/fw/Core/Startup/startup_stm32l031g6ux.s @@ -0,0 +1,261 @@ +/** + ****************************************************************************** + * @file startup_stm32l031xx.s + * @author MCD Application Team + * @brief STM32L031xx Devices vector table for GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M0+ processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m0plus + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M0. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word 0 + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word RTC_IRQHandler /* RTC through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ + .word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ + .word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */ + .word 0 /* Reserved */ + .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ + .word DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */ + .word DMA1_Channel4_5_6_7_IRQHandler /* DMA1 Channel 4, Channel 5, Channel 6 and Channel 7*/ + .word ADC1_COMP_IRQHandler /* ADC1, COMP1 and COMP2 */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word 0 /* Reserved */ + .word TIM2_IRQHandler /* TIM2 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word TIM21_IRQHandler /* TIM21 */ + .word 0 /* Reserved */ + .word TIM22_IRQHandler /* TIM22 */ + .word I2C1_IRQHandler /* I2C1 */ + .word 0 /* Reserved */ + .word SPI1_IRQHandler /* SPI1 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word USART2_IRQHandler /* USART2 */ + .word LPUART1_IRQHandler /* LPUART1 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_1_IRQHandler + .thumb_set EXTI0_1_IRQHandler,Default_Handler + + .weak EXTI2_3_IRQHandler + .thumb_set EXTI2_3_IRQHandler,Default_Handler + + .weak EXTI4_15_IRQHandler + .thumb_set EXTI4_15_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_3_IRQHandler + .thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_5_6_7_IRQHandler + .thumb_set DMA1_Channel4_5_6_7_IRQHandler,Default_Handler + + .weak ADC1_COMP_IRQHandler + .thumb_set ADC1_COMP_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM21_IRQHandler + .thumb_set TIM21_IRQHandler,Default_Handler + + .weak TIM22_IRQHandler + .thumb_set TIM22_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/fw/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l031xx.h b/fw/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l031xx.h new file mode 100644 index 0000000..9ee7ac8 --- /dev/null +++ b/fw/Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l031xx.h @@ -0,0 +1,6094 @@ +/** + ****************************************************************************** + * @file stm32l031xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer Header File. + * This file contains all the peripheral register's definitions, bits + * definitions and memory mapping for stm32l031xx devices. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l031xx + * @{ + */ + +#ifndef __STM32L031xx_H +#define __STM32L031xx_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ +/** + * @brief Configuration of the Cortex-M0+ Processor and Core Peripherals + */ +#define __CM0PLUS_REV 0U /*!< Core Revision r0p0 */ +#define __MPU_PRESENT 0U /*!< STM32L0xx provides no MPU */ +#define __VTOR_PRESENT 1U /*!< Vector Table Register supported */ +#define __NVIC_PRIO_BITS 2U /*!< STM32L0xx uses 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0U /*!< Set to 1 if different SysTick Config is used */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief stm32l031xx Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ + +/*!< Interrupt Number Definition */ +typedef enum +{ +/****** Cortex-M0 Processor Exceptions Numbers ******************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0+ Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0+ SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0+ Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0+ System Tick Interrupt */ + +/****** STM32L-0 specific Interrupt Numbers *********************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detect Interrupt */ + RTC_IRQn = 2, /*!< RTC through EXTI Line Interrupt */ + FLASH_IRQn = 3, /*!< FLASH Interrupt */ + RCC_IRQn = 4, /*!< RCC Interrupt */ + EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupts */ + EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupts */ + EXTI4_15_IRQn = 7, /*!< EXTI Line 4 to 15 Interrupts */ + DMA1_Channel1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_Channel2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_Channel4_5_6_7_IRQn = 11, /*!< DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1, COMP1 and COMP2 Interrupts */ + LPTIM1_IRQn = 13, /*!< LPTIM1 Interrupt */ + TIM2_IRQn = 15, /*!< TIM2 Interrupt */ + TIM21_IRQn = 20, /*!< TIM21 Interrupt */ + TIM22_IRQn = 22, /*!< TIM22 Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 Interrupt */ + USART2_IRQn = 28, /*!< USART2 Interrupt */ + LPUART1_IRQn = 29, /*!< LPUART1 Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm0plus.h" +#include "system_stm32l0xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status register, Address offset:0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable register, Address offset:0x04 */ + __IO uint32_t CR; /*!< ADC Control register, Address offset:0x08 */ + __IO uint32_t CFGR1; /*!< ADC Configuration register 1, Address offset:0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset:0x10 */ + __IO uint32_t SMPR; /*!< ADC Sampling time register, Address offset:0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t TR; /*!< ADC watchdog threshold register, Address offset:0x20 */ + uint32_t RESERVED3; /*!< Reserved, 0x24 */ + __IO uint32_t CHSELR; /*!< ADC channel selection register, Address offset:0x28 */ + uint32_t RESERVED4[5]; /*!< Reserved, 0x2C */ + __IO uint32_t DR; /*!< ADC data register, Address offset:0x40 */ + uint32_t RESERVED5[28]; /*!< Reserved, 0x44 - 0xB0 */ + __IO uint32_t CALFACT; /*!< ADC data register, Address offset:0xB4 */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; +} ADC_Common_TypeDef; + + +/** + * @brief Comparator + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP comparator control and status register, Address offset: 0x18 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; + + +/** +* @brief CRC calculation unit +*/ + +typedef struct +{ +__IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ +__IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ +uint8_t RESERVED0; /*!< Reserved, 0x05 */ +uint16_t RESERVED1; /*!< Reserved, 0x06 */ +__IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ +uint32_t RESERVED2; /*!< Reserved, 0x0C */ +__IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ +__IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CSELR; /*!< DMA channel selection register, Address offset: 0xA8 */ +} DMA_Request_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!TIMEOUTR, (I2C_TIMEOUTR_TIMOUTEN | I2C_TIMEOUTR_TEXTEN)) == (ClockTimeout)) ? 1UL : 0UL); + return ((READ_BIT(I2Cx->TIMEOUTR, (I2C_TIMEOUTR_TIMOUTEN | I2C_TIMEOUTR_TEXTEN)) == \ + (ClockTimeout)) ? 1UL : 0UL); } /** @@ -1443,7 +1485,7 @@ __STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TC(I2C_TypeDef *I2Cx) /** * @brief Enable Error interrupts. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @note Any of these errors will generate interrupt : * Arbitration Loss (ARLO) @@ -1463,7 +1505,7 @@ __STATIC_INLINE void LL_I2C_EnableIT_ERR(I2C_TypeDef *I2Cx) /** * @brief Disable Error interrupts. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @note Any of these errors will generate interrupt : * Arbitration Loss (ARLO) @@ -1645,7 +1687,7 @@ __STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_OVR(I2C_TypeDef *I2Cx) /** * @brief Indicate the status of SMBus PEC error flag in reception. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @note RESET: Clear default value. * SET: When the received PEC does not match with the PEC register content. @@ -1660,7 +1702,7 @@ __STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_PECERR(I2C_TypeDef *I2Cx) /** * @brief Indicate the status of SMBus Timeout detection flag. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @note RESET: Clear default value. * SET: When a timeout or extended clock timeout occurs. @@ -1675,7 +1717,7 @@ __STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx) /** * @brief Indicate the status of SMBus alert flag. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @note RESET: Clear default value. * SET: When SMBus host configuration, SMBus alert enabled and @@ -1782,7 +1824,7 @@ __STATIC_INLINE void LL_I2C_ClearFlag_OVR(I2C_TypeDef *I2Cx) /** * @brief Clear SMBus PEC error flag. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @rmtoll ICR PECCF LL_I2C_ClearSMBusFlag_PECERR * @param I2Cx I2C Instance. @@ -1795,7 +1837,7 @@ __STATIC_INLINE void LL_I2C_ClearSMBusFlag_PECERR(I2C_TypeDef *I2Cx) /** * @brief Clear SMBus Timeout detection flag. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @rmtoll ICR TIMOUTCF LL_I2C_ClearSMBusFlag_TIMEOUT * @param I2Cx I2C Instance. @@ -1808,7 +1850,7 @@ __STATIC_INLINE void LL_I2C_ClearSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx) /** * @brief Clear SMBus Alert flag. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @rmtoll ICR ALERTCF LL_I2C_ClearSMBusFlag_ALERT * @param I2Cx I2C Instance. @@ -1923,7 +1965,8 @@ __STATIC_INLINE uint32_t LL_I2C_GetTransferSize(I2C_TypeDef *I2Cx) } /** - * @brief Prepare the generation of a ACKnowledge or Non ACKnowledge condition after the address receive match code or next received byte. + * @brief Prepare the generation of a ACKnowledge or Non ACKnowledge condition after the address receive match code + or next received byte. * @note Usage in Slave mode only. * @rmtoll CR2 NACK LL_I2C_AcknowledgeNextData * @param I2Cx I2C Instance. @@ -1964,7 +2007,8 @@ __STATIC_INLINE void LL_I2C_GenerateStopCondition(I2C_TypeDef *I2Cx) /** * @brief Enable automatic RESTART Read request condition for 10bit address header (master mode). * @note The master sends the complete 10bit slave address read sequence : - * Start + 2 bytes 10bit address in Write direction + Restart + first 7 bits of 10bit address in Read direction. + * Start + 2 bytes 10bit address in Write direction + Restart + first 7 bits of 10bit address + in Read direction. * @rmtoll CR2 HEAD10R LL_I2C_EnableAuto10BitRead * @param I2Cx I2C Instance. * @retval None @@ -2125,9 +2169,10 @@ __STATIC_INLINE uint32_t LL_I2C_GetAddressMatchCode(I2C_TypeDef *I2Cx) /** * @brief Enable internal comparison of the SMBus Packet Error byte (transmission or reception mode). - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. - * @note This feature is cleared by hardware when the PEC byte is transferred, or when a STOP condition or an Address Matched is received. + * @note This feature is cleared by hardware when the PEC byte is transferred, or when a STOP condition + or an Address Matched is received. * This bit has no effect when RELOAD bit is set. * This bit has no effect in device mode when SBC bit is not set. * @rmtoll CR2 PECBYTE LL_I2C_EnableSMBusPECCompare @@ -2141,7 +2186,7 @@ __STATIC_INLINE void LL_I2C_EnableSMBusPECCompare(I2C_TypeDef *I2Cx) /** * @brief Check if the SMBus Packet Error byte internal comparison is requested or not. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @rmtoll CR2 PECBYTE LL_I2C_IsEnabledSMBusPECCompare * @param I2Cx I2C Instance. @@ -2154,7 +2199,7 @@ __STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPECCompare(I2C_TypeDef *I2Cx) /** * @brief Get the SMBus Packet Error byte calculated. - * @note Macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not + * @note The macro IS_SMBUS_INSTANCE(I2Cx) can be used to check whether or not * SMBus feature is supported by the I2Cx Instance. * @rmtoll PECR PEC LL_I2C_GetSMBusPEC * @param I2Cx I2C Instance. diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h b/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h index 74d4271..1c4e241 100644 --- a/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h @@ -150,24 +150,29 @@ typedef struct uint16_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. This parameter can be a number between Min_Data=0x0000 and Max_Data=0xFFFF. - This feature can be modified afterwards using unitary function @ref LL_TIM_SetPrescaler().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetPrescaler().*/ uint32_t CounterMode; /*!< Specifies the counter mode. This parameter can be a value of @ref TIM_LL_EC_COUNTERMODE. - This feature can be modified afterwards using unitary function @ref LL_TIM_SetCounterMode().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetCounterMode().*/ uint32_t Autoreload; /*!< Specifies the auto reload value to be loaded into the active Auto-Reload Register at the next update event. This parameter must be a number between Min_Data=0x0000 and Max_Data=0xFFFF. - Some timer instances may support 32 bits counters. In that case this parameter must be a number between 0x0000 and 0xFFFFFFFF. + Some timer instances may support 32 bits counters. In that case this parameter must + be a number between 0x0000 and 0xFFFFFFFF. - This feature can be modified afterwards using unitary function @ref LL_TIM_SetAutoReload().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetAutoReload().*/ uint32_t ClockDivision; /*!< Specifies the clock division. This parameter can be a value of @ref TIM_LL_EC_CLOCKDIVISION. - This feature can be modified afterwards using unitary function @ref LL_TIM_SetClockDivision().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetClockDivision().*/ } LL_TIM_InitTypeDef; /** @@ -178,22 +183,26 @@ typedef struct uint32_t OCMode; /*!< Specifies the output mode. This parameter can be a value of @ref TIM_LL_EC_OCMODE. - This feature can be modified afterwards using unitary function @ref LL_TIM_OC_SetMode().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetMode().*/ uint32_t OCState; /*!< Specifies the TIM Output Compare state. This parameter can be a value of @ref TIM_LL_EC_OCSTATE. - This feature can be modified afterwards using unitary functions @ref LL_TIM_CC_EnableChannel() or @ref LL_TIM_CC_DisableChannel().*/ + This feature can be modified afterwards using unitary functions + @ref LL_TIM_CC_EnableChannel() or @ref LL_TIM_CC_DisableChannel().*/ uint32_t CompareValue; /*!< Specifies the Compare value to be loaded into the Capture Compare Register. This parameter can be a number between Min_Data=0x0000 and Max_Data=0xFFFF. - This feature can be modified afterwards using unitary function LL_TIM_OC_SetCompareCHx (x=1..6).*/ + This feature can be modified afterwards using unitary function + LL_TIM_OC_SetCompareCHx (x=1..6).*/ uint32_t OCPolarity; /*!< Specifies the output polarity. This parameter can be a value of @ref TIM_LL_EC_OCPOLARITY. - This feature can be modified afterwards using unitary function @ref LL_TIM_OC_SetPolarity().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetPolarity().*/ } LL_TIM_OC_InitTypeDef; @@ -208,22 +217,26 @@ typedef struct uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPolarity().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ uint32_t ICActiveInput; /*!< Specifies the input. This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetActiveInput().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler. This parameter can be a value of @ref TIM_LL_EC_ICPSC. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPrescaler().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ uint32_t ICFilter; /*!< Specifies the input capture filter. This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetFilter().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ } LL_TIM_IC_InitTypeDef; @@ -235,47 +248,56 @@ typedef struct uint32_t EncoderMode; /*!< Specifies the encoder resolution (x2 or x4). This parameter can be a value of @ref TIM_LL_EC_ENCODERMODE. - This feature can be modified afterwards using unitary function @ref LL_TIM_SetEncoderMode().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetEncoderMode().*/ uint32_t IC1Polarity; /*!< Specifies the active edge of TI1 input. This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPolarity().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ uint32_t IC1ActiveInput; /*!< Specifies the TI1 input source This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetActiveInput().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ uint32_t IC1Prescaler; /*!< Specifies the TI1 input prescaler value. This parameter can be a value of @ref TIM_LL_EC_ICPSC. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPrescaler().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ uint32_t IC1Filter; /*!< Specifies the TI1 input filter. This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetFilter().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ uint32_t IC2Polarity; /*!< Specifies the active edge of TI2 input. This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPolarity().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ uint32_t IC2ActiveInput; /*!< Specifies the TI2 input source This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetActiveInput().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ uint32_t IC2Prescaler; /*!< Specifies the TI2 input prescaler value. This parameter can be a value of @ref TIM_LL_EC_ICPSC. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetPrescaler().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ uint32_t IC2Filter; /*!< Specifies the TI2 input filter. This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. - This feature can be modified afterwards using unitary function @ref LL_TIM_IC_SetFilter().*/ + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ } LL_TIM_ENCODER_InitTypeDef; @@ -334,8 +356,8 @@ typedef struct /** @defgroup TIM_LL_EC_ONEPULSEMODE One Pulse Mode * @{ */ -#define LL_TIM_ONEPULSEMODE_SINGLE TIM_CR1_OPM /*!< Counter is not stopped at update event */ -#define LL_TIM_ONEPULSEMODE_REPETITIVE 0x00000000U /*!< Counter stops counting at the next update event */ +#define LL_TIM_ONEPULSEMODE_SINGLE TIM_CR1_OPM /*!< Counter stops counting at the next update event */ +#define LL_TIM_ONEPULSEMODE_REPETITIVE 0x00000000U /*!< Counter is not stopped at update event */ /** * @} */ @@ -822,7 +844,8 @@ typedef struct ((((__TIMCLK__)/((__PSC__) + 1U)) >= (__FREQ__)) ? (((__TIMCLK__)/((__FREQ__) * ((__PSC__) + 1U))) - 1U) : 0U) /** - * @brief HELPER macro calculating the compare value required to achieve the required timer output compare active/inactive delay. + * @brief HELPER macro calculating the compare value required to achieve the required timer output compare + * active/inactive delay. * @note ex: @ref __LL_TIM_CALC_DELAY (1000000, @ref LL_TIM_GetPrescaler (), 10); * @param __TIMCLK__ timer input clock frequency (in Hz) * @param __PSC__ prescaler @@ -834,7 +857,8 @@ typedef struct / ((uint64_t)1000000U * (uint64_t)((__PSC__) + 1U)))) /** - * @brief HELPER macro calculating the auto-reload value to achieve the required pulse duration (when the timer operates in one pulse mode). + * @brief HELPER macro calculating the auto-reload value to achieve the required pulse duration + * (when the timer operates in one pulse mode). * @note ex: @ref __LL_TIM_CALC_PULSE (1000000, @ref LL_TIM_GetPrescaler (), 10, 20); * @param __TIMCLK__ timer input clock frequency (in Hz) * @param __PSC__ prescaler @@ -1091,7 +1115,8 @@ __STATIC_INLINE uint32_t LL_TIM_IsEnabledARRPreload(TIM_TypeDef *TIMx) } /** - * @brief Set the division ratio between the timer clock and the sampling clock used by the dead-time generators (when supported) and the digital filters. + * @brief Set the division ratio between the timer clock and the sampling clock used by the dead-time generators + * (when supported) and the digital filters. * @note Macro IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) can be used to check * whether or not the clock division feature is supported by the timer * instance. @@ -1109,7 +1134,8 @@ __STATIC_INLINE void LL_TIM_SetClockDivision(TIM_TypeDef *TIMx, uint32_t ClockDi } /** - * @brief Get the actual division ratio between the timer clock and the sampling clock used by the dead-time generators (when supported) and the digital filters. + * @brief Get the actual division ratio between the timer clock and the sampling clock used by the dead-time + * generators (when supported) and the digital filters. * @note Macro IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) can be used to check * whether or not the clock division feature is supported by the timer * instance. @@ -1368,7 +1394,7 @@ __STATIC_INLINE void LL_TIM_OC_SetMode(TIM_TypeDef *TIMx, uint32_t Channel, uint { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); - MODIFY_REG(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel]), Mode << SHIFT_TAB_OCxx[iChannel]); + MODIFY_REG(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel]), Mode << SHIFT_TAB_OCxx[iChannel]); } /** @@ -1397,7 +1423,7 @@ __STATIC_INLINE uint32_t LL_TIM_OC_GetMode(TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); const __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); - return (READ_BIT(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel])) >> SHIFT_TAB_OCxx[iChannel]); + return (READ_BIT(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel])) >> SHIFT_TAB_OCxx[iChannel]); } /** @@ -1804,7 +1830,8 @@ __STATIC_INLINE void LL_TIM_IC_Config(TIM_TypeDef *TIMx, uint32_t Channel, uint3 uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); MODIFY_REG(*pReg, ((TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC | TIM_CCMR1_CC1S) << SHIFT_TAB_ICxx[iChannel]), - ((Configuration >> 16U) & (TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC | TIM_CCMR1_CC1S)) << SHIFT_TAB_ICxx[iChannel]); + ((Configuration >> 16U) & (TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC | TIM_CCMR1_CC1S)) \ + << SHIFT_TAB_ICxx[iChannel]); MODIFY_REG(TIMx->CCER, ((TIM_CCER_CC1NP | TIM_CCER_CC1P) << SHIFT_TAB_CCxP[iChannel]), (Configuration & (TIM_CCER_CC1NP | TIM_CCER_CC1P)) << SHIFT_TAB_CCxP[iChannel]); } @@ -2685,7 +2712,8 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC1OVR(TIM_TypeDef *TIMx) } /** - * @brief Indicate whether Capture/Compare 1 over-capture interrupt flag (CC1OF) is set (Capture/Compare 1 interrupt is pending). + * @brief Indicate whether Capture/Compare 1 over-capture interrupt flag (CC1OF) is set + * (Capture/Compare 1 interrupt is pending). * @rmtoll SR CC1OF LL_TIM_IsActiveFlag_CC1OVR * @param TIMx Timer instance * @retval State of bit (1 or 0). @@ -2707,7 +2735,8 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC2OVR(TIM_TypeDef *TIMx) } /** - * @brief Indicate whether Capture/Compare 2 over-capture interrupt flag (CC2OF) is set (Capture/Compare 2 over-capture interrupt is pending). + * @brief Indicate whether Capture/Compare 2 over-capture interrupt flag (CC2OF) is set + * (Capture/Compare 2 over-capture interrupt is pending). * @rmtoll SR CC2OF LL_TIM_IsActiveFlag_CC2OVR * @param TIMx Timer instance * @retval State of bit (1 or 0). @@ -2729,7 +2758,8 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC3OVR(TIM_TypeDef *TIMx) } /** - * @brief Indicate whether Capture/Compare 3 over-capture interrupt flag (CC3OF) is set (Capture/Compare 3 over-capture interrupt is pending). + * @brief Indicate whether Capture/Compare 3 over-capture interrupt flag (CC3OF) is set + * (Capture/Compare 3 over-capture interrupt is pending). * @rmtoll SR CC3OF LL_TIM_IsActiveFlag_CC3OVR * @param TIMx Timer instance * @retval State of bit (1 or 0). @@ -2751,7 +2781,8 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC4OVR(TIM_TypeDef *TIMx) } /** - * @brief Indicate whether Capture/Compare 4 over-capture interrupt flag (CC4OF) is set (Capture/Compare 4 over-capture interrupt is pending). + * @brief Indicate whether Capture/Compare 4 over-capture interrupt flag (CC4OF) is set + * (Capture/Compare 4 over-capture interrupt is pending). * @rmtoll SR CC4OF LL_TIM_IsActiveFlag_CC4OVR * @param TIMx Timer instance * @retval State of bit (1 or 0). @@ -2970,7 +3001,7 @@ __STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_TRIG(TIM_TypeDef *TIMx) * @} */ -/** @defgroup TIM_LL_EF_DMA_Management DMA-Management +/** @defgroup TIM_LL_EF_DMA_Management DMA Management * @{ */ /** diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h b/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h new file mode 100644 index 0000000..c4887f5 --- /dev/null +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_usart.h @@ -0,0 +1,3751 @@ +/** + ****************************************************************************** + * @file stm32l0xx_ll_usart.h + * @author MCD Application Team + * @brief Header file of USART LL module. + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32L0xx_LL_USART_H +#define STM32L0xx_LL_USART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l0xx.h" + +/** @addtogroup STM32L0xx_LL_Driver + * @{ + */ + +#if defined (USART1) || defined (USART2) || defined (USART4) || defined (USART5) + +/** @defgroup USART_LL USART + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_Private_Macros USART Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_ES_INIT USART Exported Init structures + * @{ + */ + +/** + * @brief LL USART Init Structure definition + */ +typedef struct +{ + + uint32_t BaudRate; /*!< This field defines expected Usart communication baud rate. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetBaudRate().*/ + + uint32_t DataWidth; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref USART_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetDataWidth().*/ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_LL_EC_STOPBITS. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetStopBitsLength().*/ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref USART_LL_EC_PARITY. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetParity().*/ + + uint32_t TransferDirection; /*!< Specifies whether the Receive and/or Transmit mode is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_DIRECTION. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetTransferDirection().*/ + + uint32_t HardwareFlowControl; /*!< Specifies whether the hardware flow control mode is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_HWCONTROL. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetHWFlowCtrl().*/ + + uint32_t OverSampling; /*!< Specifies whether USART oversampling mode is 16 or 8. + This parameter can be a value of @ref USART_LL_EC_OVERSAMPLING. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetOverSampling().*/ + +} LL_USART_InitTypeDef; + +/** + * @brief LL USART Clock Init Structure definition + */ +typedef struct +{ + uint32_t ClockOutput; /*!< Specifies whether the USART clock is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_CLOCK. + + USART HW configuration can be modified afterwards using unitary functions + @ref LL_USART_EnableSCLKOutput() or @ref LL_USART_DisableSCLKOutput(). + For more details, refer to description of this function. */ + + uint32_t ClockPolarity; /*!< Specifies the steady state of the serial clock. + This parameter can be a value of @ref USART_LL_EC_POLARITY. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetClockPolarity(). + For more details, refer to description of this function. */ + + uint32_t ClockPhase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_LL_EC_PHASE. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetClockPhase(). + For more details, refer to description of this function. */ + + uint32_t LastBitClockPulse; /*!< Specifies whether the clock pulse corresponding to the last transmitted + data bit (MSB) has to be output on the SCLK pin in synchronous mode. + This parameter can be a value of @ref USART_LL_EC_LASTCLKPULSE. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetLastClkPulseOutput(). + For more details, refer to description of this function. */ + +} LL_USART_ClockInitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup USART_LL_Exported_Constants USART Exported Constants + * @{ + */ + +/** @defgroup USART_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_USART_WriteReg function + * @{ + */ +#define LL_USART_ICR_PECF USART_ICR_PECF /*!< Parity error clear flag */ +#define LL_USART_ICR_FECF USART_ICR_FECF /*!< Framing error clear flag */ +#define LL_USART_ICR_NCF USART_ICR_NCF /*!< Noise error detected clear flag */ +#define LL_USART_ICR_ORECF USART_ICR_ORECF /*!< Overrun error clear flag */ +#define LL_USART_ICR_IDLECF USART_ICR_IDLECF /*!< Idle line detected clear flag */ +#define LL_USART_ICR_TCCF USART_ICR_TCCF /*!< Transmission complete clear flag */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_ICR_TCBGTCF USART_ICR_TCBGTCF /*!< Transmission completed before guard time clear flag */ +#endif /* USART_TCBGT_SUPPORT */ +#define LL_USART_ICR_LBDCF USART_ICR_LBDCF /*!< LIN break detection clear flag */ +#define LL_USART_ICR_CTSCF USART_ICR_CTSCF /*!< CTS clear flag */ +#define LL_USART_ICR_RTOCF USART_ICR_RTOCF /*!< Receiver timeout clear flag */ +#define LL_USART_ICR_EOBCF USART_ICR_EOBCF /*!< End of block clear flag */ +#define LL_USART_ICR_CMCF USART_ICR_CMCF /*!< Character match clear flag */ +#define LL_USART_ICR_WUCF USART_ICR_WUCF /*!< Wakeup from Stop mode clear flag */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_USART_ReadReg function + * @{ + */ +#define LL_USART_ISR_PE USART_ISR_PE /*!< Parity error flag */ +#define LL_USART_ISR_FE USART_ISR_FE /*!< Framing error flag */ +#define LL_USART_ISR_NE USART_ISR_NE /*!< Noise detected flag */ +#define LL_USART_ISR_ORE USART_ISR_ORE /*!< Overrun error flag */ +#define LL_USART_ISR_IDLE USART_ISR_IDLE /*!< Idle line detected flag */ +#define LL_USART_ISR_RXNE USART_ISR_RXNE /*!< Read data register not empty flag */ +#define LL_USART_ISR_TC USART_ISR_TC /*!< Transmission complete flag */ +#define LL_USART_ISR_TXE USART_ISR_TXE /*!< Transmit data register empty flag */ +#define LL_USART_ISR_LBDF USART_ISR_LBDF /*!< LIN break detection flag */ +#define LL_USART_ISR_CTSIF USART_ISR_CTSIF /*!< CTS interrupt flag */ +#define LL_USART_ISR_CTS USART_ISR_CTS /*!< CTS flag */ +#define LL_USART_ISR_RTOF USART_ISR_RTOF /*!< Receiver timeout flag */ +#define LL_USART_ISR_EOBF USART_ISR_EOBF /*!< End of block flag */ +#define LL_USART_ISR_ABRE USART_ISR_ABRE /*!< Auto baud rate error flag */ +#define LL_USART_ISR_ABRF USART_ISR_ABRF /*!< Auto baud rate flag */ +#define LL_USART_ISR_BUSY USART_ISR_BUSY /*!< Busy flag */ +#define LL_USART_ISR_CMF USART_ISR_CMF /*!< Character match flag */ +#define LL_USART_ISR_SBKF USART_ISR_SBKF /*!< Send break flag */ +#define LL_USART_ISR_RWU USART_ISR_RWU /*!< Receiver wakeup from Mute mode flag */ +#define LL_USART_ISR_WUF USART_ISR_WUF /*!< Wakeup from Stop mode flag */ +#define LL_USART_ISR_TEACK USART_ISR_TEACK /*!< Transmit enable acknowledge flag */ +#define LL_USART_ISR_REACK USART_ISR_REACK /*!< Receive enable acknowledge flag */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_ISR_TCBGT USART_ISR_TCBGT /*!< Transmission complete before guard time completion flag */ +#endif /* USART_TCBGT_SUPPORT */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_USART_ReadReg and LL_USART_WriteReg functions + * @{ + */ +#define LL_USART_CR1_IDLEIE USART_CR1_IDLEIE /*!< IDLE interrupt enable */ +#define LL_USART_CR1_RXNEIE USART_CR1_RXNEIE /*!< Read data register not empty interrupt enable */ +#define LL_USART_CR1_TCIE USART_CR1_TCIE /*!< Transmission complete interrupt enable */ +#define LL_USART_CR1_TXEIE USART_CR1_TXEIE /*!< Transmit data register empty interrupt enable */ +#define LL_USART_CR1_PEIE USART_CR1_PEIE /*!< Parity error */ +#define LL_USART_CR1_CMIE USART_CR1_CMIE /*!< Character match interrupt enable */ +#define LL_USART_CR1_RTOIE USART_CR1_RTOIE /*!< Receiver timeout interrupt enable */ +#define LL_USART_CR1_EOBIE USART_CR1_EOBIE /*!< End of Block interrupt enable */ +#define LL_USART_CR2_LBDIE USART_CR2_LBDIE /*!< LIN break detection interrupt enable */ +#define LL_USART_CR3_EIE USART_CR3_EIE /*!< Error interrupt enable */ +#define LL_USART_CR3_CTSIE USART_CR3_CTSIE /*!< CTS interrupt enable */ +#define LL_USART_CR3_WUFIE USART_CR3_WUFIE /*!< Wakeup from Stop mode interrupt enable */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_CR3_TCBGTIE USART_CR3_TCBGTIE /*!< Transmission complete before guard time interrupt enable */ +#endif /* USART_TCBGT_SUPPORT */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DIRECTION Communication Direction + * @{ + */ +#define LL_USART_DIRECTION_NONE 0x00000000U /*!< Transmitter and Receiver are disabled */ +#define LL_USART_DIRECTION_RX USART_CR1_RE /*!< Transmitter is disabled and Receiver is enabled */ +#define LL_USART_DIRECTION_TX USART_CR1_TE /*!< Transmitter is enabled and Receiver is disabled */ +#define LL_USART_DIRECTION_TX_RX (USART_CR1_TE |USART_CR1_RE) /*!< Transmitter and Receiver are enabled */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_PARITY Parity Control + * @{ + */ +#define LL_USART_PARITY_NONE 0x00000000U /*!< Parity control disabled */ +#define LL_USART_PARITY_EVEN USART_CR1_PCE /*!< Parity control enabled and Even Parity is selected */ +#define LL_USART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) /*!< Parity control enabled and Odd Parity is selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_WAKEUP Wakeup + * @{ + */ +#define LL_USART_WAKEUP_IDLELINE 0x00000000U /*!< USART wake up from Mute mode on Idle Line */ +#define LL_USART_WAKEUP_ADDRESSMARK USART_CR1_WAKE /*!< USART wake up from Mute mode on Address Mark */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_USART_DATAWIDTH_7B USART_CR1_M1 /*!< 7 bits word length : Start bit, 7 data bits, n stop bits */ +#define LL_USART_DATAWIDTH_8B 0x00000000U /*!< 8 bits word length : Start bit, 8 data bits, n stop bits */ +#define LL_USART_DATAWIDTH_9B USART_CR1_M0 /*!< 9 bits word length : Start bit, 9 data bits, n stop bits */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_OVERSAMPLING Oversampling + * @{ + */ +#define LL_USART_OVERSAMPLING_16 0x00000000U /*!< Oversampling by 16 */ +#define LL_USART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EC_CLOCK Clock Signal + * @{ + */ + +#define LL_USART_CLOCK_DISABLE 0x00000000U /*!< Clock signal not provided */ +#define LL_USART_CLOCK_ENABLE USART_CR2_CLKEN /*!< Clock signal provided */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/** @defgroup USART_LL_EC_LASTCLKPULSE Last Clock Pulse + * @{ + */ +#define LL_USART_LASTCLKPULSE_NO_OUTPUT 0x00000000U /*!< The clock pulse of the last data bit is not output to the SCLK pin */ +#define LL_USART_LASTCLKPULSE_OUTPUT USART_CR2_LBCL /*!< The clock pulse of the last data bit is output to the SCLK pin */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_USART_PHASE_1EDGE 0x00000000U /*!< The first clock transition is the first data capture edge */ +#define LL_USART_PHASE_2EDGE USART_CR2_CPHA /*!< The second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_USART_POLARITY_LOW 0x00000000U /*!< Steady low value on SCLK pin outside transmission window*/ +#define LL_USART_POLARITY_HIGH USART_CR2_CPOL /*!< Steady high value on SCLK pin outside transmission window */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_STOPBITS Stop Bits + * @{ + */ +#define LL_USART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< 0.5 stop bit */ +#define LL_USART_STOPBITS_1 0x00000000U /*!< 1 stop bit */ +#define LL_USART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< 1.5 stop bits */ +#define LL_USART_STOPBITS_2 USART_CR2_STOP_1 /*!< 2 stop bits */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_TXRX TX RX Pins Swap + * @{ + */ +#define LL_USART_TXRX_STANDARD 0x00000000U /*!< TX/RX pins are used as defined in standard pinout */ +#define LL_USART_TXRX_SWAPPED (USART_CR2_SWAP) /*!< TX and RX pins functions are swapped. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_RXPIN_LEVEL RX Pin Active Level Inversion + * @{ + */ +#define LL_USART_RXPIN_LEVEL_STANDARD 0x00000000U /*!< RX pin signal works using the standard logic levels */ +#define LL_USART_RXPIN_LEVEL_INVERTED (USART_CR2_RXINV) /*!< RX pin signal values are inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_TXPIN_LEVEL TX Pin Active Level Inversion + * @{ + */ +#define LL_USART_TXPIN_LEVEL_STANDARD 0x00000000U /*!< TX pin signal works using the standard logic levels */ +#define LL_USART_TXPIN_LEVEL_INVERTED (USART_CR2_TXINV) /*!< TX pin signal values are inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_BINARY_LOGIC Binary Data Inversion + * @{ + */ +#define LL_USART_BINARY_LOGIC_POSITIVE 0x00000000U /*!< Logical data from the data register are send/received in positive/direct logic. (1=H, 0=L) */ +#define LL_USART_BINARY_LOGIC_NEGATIVE USART_CR2_DATAINV /*!< Logical data from the data register are send/received in negative/inverse logic. (1=L, 0=H). The parity bit is also inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_BITORDER Bit Order + * @{ + */ +#define LL_USART_BITORDER_LSBFIRST 0x00000000U /*!< data is transmitted/received with data bit 0 first, following the start bit */ +#define LL_USART_BITORDER_MSBFIRST USART_CR2_MSBFIRST /*!< data is transmitted/received with the MSB first, following the start bit */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_AUTOBAUD_DETECT_ON Autobaud Detection + * @{ + */ +#define LL_USART_AUTOBAUD_DETECT_ON_STARTBIT 0x00000000U /*!< Measurement of the start bit is used to detect the baud rate */ +#define LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE USART_CR2_ABRMODE_0 /*!< Falling edge to falling edge measurement. Received frame must start with a single bit = 1 -> Frame = Start10xxxxxx */ +#define LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME USART_CR2_ABRMODE_1 /*!< 0x7F frame detection */ +#define LL_USART_AUTOBAUD_DETECT_ON_55_FRAME (USART_CR2_ABRMODE_1 | USART_CR2_ABRMODE_0) /*!< 0x55 frame detection */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_ADDRESS_DETECT Address Length Detection + * @{ + */ +#define LL_USART_ADDRESS_DETECT_4B 0x00000000U /*!< 4-bit address detection method selected */ +#define LL_USART_ADDRESS_DETECT_7B USART_CR2_ADDM7 /*!< 7-bit address detection (in 8-bit data mode) method selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_HWCONTROL Hardware Control + * @{ + */ +#define LL_USART_HWCONTROL_NONE 0x00000000U /*!< CTS and RTS hardware flow control disabled */ +#define LL_USART_HWCONTROL_RTS USART_CR3_RTSE /*!< RTS output enabled, data is only requested when there is space in the receive buffer */ +#define LL_USART_HWCONTROL_CTS USART_CR3_CTSE /*!< CTS mode enabled, data is only transmitted when the nCTS input is asserted (tied to 0) */ +#define LL_USART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) /*!< CTS and RTS hardware flow control enabled */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_WAKEUP_ON Wakeup Activation + * @{ + */ +#define LL_USART_WAKEUP_ON_ADDRESS 0x00000000U /*!< Wake up active on address match */ +#define LL_USART_WAKEUP_ON_STARTBIT USART_CR3_WUS_1 /*!< Wake up active on Start bit detection */ +#define LL_USART_WAKEUP_ON_RXNE (USART_CR3_WUS_0 | USART_CR3_WUS_1) /*!< Wake up active on RXNE */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_IRDA_POWER IrDA Power + * @{ + */ +#define LL_USART_IRDA_POWER_NORMAL 0x00000000U /*!< IrDA normal power mode */ +#define LL_USART_IRDA_POWER_LOW USART_CR3_IRLP /*!< IrDA low power mode */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_LINBREAK_DETECT LIN Break Detection Length + * @{ + */ +#define LL_USART_LINBREAK_DETECT_10B 0x00000000U /*!< 10-bit break detection method selected */ +#define LL_USART_LINBREAK_DETECT_11B USART_CR2_LBDL /*!< 11-bit break detection method selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DE_POLARITY Driver Enable Polarity + * @{ + */ +#define LL_USART_DE_POLARITY_HIGH 0x00000000U /*!< DE signal is active high */ +#define LL_USART_DE_POLARITY_LOW USART_CR3_DEP /*!< DE signal is active low */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DMA_REG_DATA DMA Register Data + * @{ + */ +#define LL_USART_DMA_REG_DATA_TRANSMIT 0x00000000U /*!< Get address of data register used for transmission */ +#define LL_USART_DMA_REG_DATA_RECEIVE 0x00000001U /*!< Get address of data register used for reception */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup USART_LL_Exported_Macros USART Exported Macros + * @{ + */ + +/** @defgroup USART_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in USART register + * @param __INSTANCE__ USART Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_USART_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in USART register + * @param __INSTANCE__ USART Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_USART_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup USART_LL_EM_Exported_Macros_Helper Exported_Macros_Helper + * @{ + */ + +/** + * @brief Compute USARTDIV value according to Peripheral Clock and + * expected Baud Rate in 8 bits sampling mode (32 bits value of USARTDIV is returned) + * @param __PERIPHCLK__ Peripheral Clock frequency used for USART instance + * @param __BAUDRATE__ Baud rate value to achieve + * @retval USARTDIV value to be used for BRR register filling in OverSampling_8 case + */ +#define __LL_USART_DIV_SAMPLING8(__PERIPHCLK__, __BAUDRATE__) ((((__PERIPHCLK__)*2U)\ + + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) + +/** + * @brief Compute USARTDIV value according to Peripheral Clock and + * expected Baud Rate in 16 bits sampling mode (32 bits value of USARTDIV is returned) + * @param __PERIPHCLK__ Peripheral Clock frequency used for USART instance + * @param __BAUDRATE__ Baud rate value to achieve + * @retval USARTDIV value to be used for BRR register filling in OverSampling_16 case + */ +#define __LL_USART_DIV_SAMPLING16(__PERIPHCLK__, __BAUDRATE__) (((__PERIPHCLK__) + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup USART_LL_Exported_Functions USART Exported Functions + * @{ + */ + +/** @defgroup USART_LL_EF_Configuration Configuration functions + * @{ + */ + +/** + * @brief USART Enable + * @rmtoll CR1 UE LL_USART_Enable + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_Enable(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR1, USART_CR1_UE); +} + +/** + * @brief USART Disable (all USART prescalers and outputs are disabled) + * @note When USART is disabled, USART prescalers and outputs are stopped immediately, + * and current operations are discarded. The configuration of the USART is kept, but all the status + * flags, in the USARTx_ISR are set to their default values. + * @rmtoll CR1 UE LL_USART_Disable + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_Disable(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR1, USART_CR1_UE); +} + +/** + * @brief Indicate if USART is enabled + * @rmtoll CR1 UE LL_USART_IsEnabled + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabled(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_UE) == (USART_CR1_UE)) ? 1UL : 0UL); +} + +/** + * @brief USART enabled in STOP Mode. + * @note When this function is enabled, USART is able to wake up the MCU from Stop mode, provided that + * USART clock selection is HSI or LSE in RCC. + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_EnableInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_UESM); +} + +/** + * @brief USART disabled in STOP Mode. + * @note When this function is disabled, USART is not able to wake up the MCU from Stop mode + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_DisableInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_UESM); +} + +/** + * @brief Indicate if USART is enabled in STOP Mode (able to wake up MCU from Stop mode or not) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_IsEnabledInStopMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledInStopMode(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_UESM) == (USART_CR1_UESM)) ? 1UL : 0UL); +} + +/** + * @brief USART Clock enabled in STOP Mode + * @note When this function is called, USART Clock is enabled while in STOP mode + * @rmtoll CR3 UCESM LL_USART_EnableClockInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableClockInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_UCESM); +} + +/** + * @brief USART clock disabled in STOP Mode + * @note When this function is called, USART Clock is disabled while in STOP mode + * @rmtoll CR3 UCESM LL_USART_DisableClockInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableClockInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_UCESM); +} + +/** + * @brief Indicate if USART clock is enabled in STOP Mode + * @rmtoll CR3 UCESM LL_USART_IsClockEnabledInStopMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsClockEnabledInStopMode(USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_UCESM) == (USART_CR3_UCESM)); +} + +/** + * @brief Receiver Enable (Receiver is enabled and begins searching for a start bit) + * @rmtoll CR1 RE LL_USART_EnableDirectionRx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDirectionRx(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RE); +} + +/** + * @brief Receiver Disable + * @rmtoll CR1 RE LL_USART_DisableDirectionRx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDirectionRx(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RE); +} + +/** + * @brief Transmitter Enable + * @rmtoll CR1 TE LL_USART_EnableDirectionTx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDirectionTx(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TE); +} + +/** + * @brief Transmitter Disable + * @rmtoll CR1 TE LL_USART_DisableDirectionTx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDirectionTx(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TE); +} + +/** + * @brief Configure simultaneously enabled/disabled states + * of Transmitter and Receiver + * @rmtoll CR1 RE LL_USART_SetTransferDirection\n + * CR1 TE LL_USART_SetTransferDirection + * @param USARTx USART Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_USART_DIRECTION_NONE + * @arg @ref LL_USART_DIRECTION_RX + * @arg @ref LL_USART_DIRECTION_TX + * @arg @ref LL_USART_DIRECTION_TX_RX + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTransferDirection(USART_TypeDef *USARTx, uint32_t TransferDirection) +{ + ATOMIC_MODIFY_REG(USARTx->CR1, USART_CR1_RE | USART_CR1_TE, TransferDirection); +} + +/** + * @brief Return enabled/disabled states of Transmitter and Receiver + * @rmtoll CR1 RE LL_USART_GetTransferDirection\n + * CR1 TE LL_USART_GetTransferDirection + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DIRECTION_NONE + * @arg @ref LL_USART_DIRECTION_RX + * @arg @ref LL_USART_DIRECTION_TX + * @arg @ref LL_USART_DIRECTION_TX_RX + */ +__STATIC_INLINE uint32_t LL_USART_GetTransferDirection(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_RE | USART_CR1_TE)); +} + +/** + * @brief Configure Parity (enabled/disabled and parity mode if enabled). + * @note This function selects if hardware parity control (generation and detection) is enabled or disabled. + * When the parity control is enabled (Odd or Even), computed parity bit is inserted at the MSB position + * (9th or 8th bit depending on data width) and parity is checked on the received data. + * @rmtoll CR1 PS LL_USART_SetParity\n + * CR1 PCE LL_USART_SetParity + * @param USARTx USART Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_USART_PARITY_NONE + * @arg @ref LL_USART_PARITY_EVEN + * @arg @ref LL_USART_PARITY_ODD + * @retval None + */ +__STATIC_INLINE void LL_USART_SetParity(USART_TypeDef *USARTx, uint32_t Parity) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_PS | USART_CR1_PCE, Parity); +} + +/** + * @brief Return Parity configuration (enabled/disabled and parity mode if enabled) + * @rmtoll CR1 PS LL_USART_GetParity\n + * CR1 PCE LL_USART_GetParity + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_PARITY_NONE + * @arg @ref LL_USART_PARITY_EVEN + * @arg @ref LL_USART_PARITY_ODD + */ +__STATIC_INLINE uint32_t LL_USART_GetParity(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_PS | USART_CR1_PCE)); +} + +/** + * @brief Set Receiver Wake Up method from Mute mode. + * @rmtoll CR1 WAKE LL_USART_SetWakeUpMethod + * @param USARTx USART Instance + * @param Method This parameter can be one of the following values: + * @arg @ref LL_USART_WAKEUP_IDLELINE + * @arg @ref LL_USART_WAKEUP_ADDRESSMARK + * @retval None + */ +__STATIC_INLINE void LL_USART_SetWakeUpMethod(USART_TypeDef *USARTx, uint32_t Method) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_WAKE, Method); +} + +/** + * @brief Return Receiver Wake Up method from Mute mode + * @rmtoll CR1 WAKE LL_USART_GetWakeUpMethod + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_WAKEUP_IDLELINE + * @arg @ref LL_USART_WAKEUP_ADDRESSMARK + */ +__STATIC_INLINE uint32_t LL_USART_GetWakeUpMethod(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_WAKE)); +} + +/** + * @brief Set Word length (i.e. nb of data bits, excluding start and stop bits) + * @rmtoll CR1 M0 LL_USART_SetDataWidth\n + * CR1 M1 LL_USART_SetDataWidth + * @param USARTx USART Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDataWidth(USART_TypeDef *USARTx, uint32_t DataWidth) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_M, DataWidth); +} + +/** + * @brief Return Word length (i.e. nb of data bits, excluding start and stop bits) + * @rmtoll CR1 M0 LL_USART_GetDataWidth\n + * CR1 M1 LL_USART_GetDataWidth + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + */ +__STATIC_INLINE uint32_t LL_USART_GetDataWidth(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_M)); +} + +/** + * @brief Allow switch between Mute Mode and Active mode + * @rmtoll CR1 MME LL_USART_EnableMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableMuteMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_MME); +} + +/** + * @brief Prevent Mute Mode use. Set Receiver in active mode permanently. + * @rmtoll CR1 MME LL_USART_DisableMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableMuteMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_MME); +} + +/** + * @brief Indicate if switch between Mute Mode and Active mode is allowed + * @rmtoll CR1 MME LL_USART_IsEnabledMuteMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledMuteMode(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_MME) == (USART_CR1_MME)) ? 1UL : 0UL); +} + +/** + * @brief Set Oversampling to 8-bit or 16-bit mode + * @rmtoll CR1 OVER8 LL_USART_SetOverSampling + * @param USARTx USART Instance + * @param OverSampling This parameter can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetOverSampling(USART_TypeDef *USARTx, uint32_t OverSampling) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_OVER8, OverSampling); +} + +/** + * @brief Return Oversampling mode + * @rmtoll CR1 OVER8 LL_USART_GetOverSampling + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + */ +__STATIC_INLINE uint32_t LL_USART_GetOverSampling(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_OVER8)); +} + +/** + * @brief Configure if Clock pulse of the last data bit is output to the SCLK pin or not + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 LBCL LL_USART_SetLastClkPulseOutput + * @param USARTx USART Instance + * @param LastBitClockPulse This parameter can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_USART_SetLastClkPulseOutput(USART_TypeDef *USARTx, uint32_t LastBitClockPulse) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_LBCL, LastBitClockPulse); +} + +/** + * @brief Retrieve Clock pulse of the last data bit output configuration + * (Last bit Clock pulse output to the SCLK pin or not) + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 LBCL LL_USART_GetLastClkPulseOutput + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + */ +__STATIC_INLINE uint32_t LL_USART_GetLastClkPulseOutput(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_LBCL)); +} + +/** + * @brief Select the phase of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPHA LL_USART_SetClockPhase + * @param USARTx USART Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetClockPhase(USART_TypeDef *USARTx, uint32_t ClockPhase) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPHA, ClockPhase); +} + +/** + * @brief Return phase of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPHA LL_USART_GetClockPhase + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_USART_GetClockPhase(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_CPHA)); +} + +/** + * @brief Select the polarity of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPOL LL_USART_SetClockPolarity + * @param USARTx USART Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_USART_SetClockPolarity(USART_TypeDef *USARTx, uint32_t ClockPolarity) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPOL, ClockPolarity); +} + +/** + * @brief Return polarity of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPOL LL_USART_GetClockPolarity + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_USART_GetClockPolarity(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_CPOL)); +} + +/** + * @brief Configure Clock signal format (Phase Polarity and choice about output of last bit clock pulse) + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clock Phase configuration using @ref LL_USART_SetClockPhase() function + * - Clock Polarity configuration using @ref LL_USART_SetClockPolarity() function + * - Output of Last bit Clock pulse configuration using @ref LL_USART_SetLastClkPulseOutput() function + * @rmtoll CR2 CPHA LL_USART_ConfigClock\n + * CR2 CPOL LL_USART_ConfigClock\n + * CR2 LBCL LL_USART_ConfigClock + * @param USARTx USART Instance + * @param Phase This parameter can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + * @param LBCPOutput This parameter can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigClock(USART_TypeDef *USARTx, uint32_t Phase, uint32_t Polarity, uint32_t LBCPOutput) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL, Phase | Polarity | LBCPOutput); +} + +/** + * @brief Enable Clock output on SCLK pin + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_EnableSCLKOutput + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSCLKOutput(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Disable Clock output on SCLK pin + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_DisableSCLKOutput + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSCLKOutput(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Indicate if Clock output on SCLK pin is enabled + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_IsEnabledSCLKOutput + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSCLKOutput(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_CLKEN) == (USART_CR2_CLKEN)) ? 1UL : 0UL); +} + +/** + * @brief Set the length of the stop bits + * @rmtoll CR2 STOP LL_USART_SetStopBitsLength + * @param USARTx USART Instance + * @param StopBits This parameter can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetStopBitsLength(USART_TypeDef *USARTx, uint32_t StopBits) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_STOP, StopBits); +} + +/** + * @brief Retrieve the length of the stop bits + * @rmtoll CR2 STOP LL_USART_GetStopBitsLength + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + */ +__STATIC_INLINE uint32_t LL_USART_GetStopBitsLength(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_STOP)); +} + +/** + * @brief Configure Character frame format (Datawidth, Parity control, Stop Bits) + * @note Call of this function is equivalent to following function call sequence : + * - Data Width configuration using @ref LL_USART_SetDataWidth() function + * - Parity Control and mode configuration using @ref LL_USART_SetParity() function + * - Stop bits configuration using @ref LL_USART_SetStopBitsLength() function + * @rmtoll CR1 PS LL_USART_ConfigCharacter\n + * CR1 PCE LL_USART_ConfigCharacter\n + * CR1 M0 LL_USART_ConfigCharacter\n + * CR1 M1 LL_USART_ConfigCharacter\n + * CR2 STOP LL_USART_ConfigCharacter + * @param USARTx USART Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_USART_PARITY_NONE + * @arg @ref LL_USART_PARITY_EVEN + * @arg @ref LL_USART_PARITY_ODD + * @param StopBits This parameter can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigCharacter(USART_TypeDef *USARTx, uint32_t DataWidth, uint32_t Parity, + uint32_t StopBits) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_PS | USART_CR1_PCE | USART_CR1_M, Parity | DataWidth); + MODIFY_REG(USARTx->CR2, USART_CR2_STOP, StopBits); +} + +/** + * @brief Configure TX/RX pins swapping setting. + * @rmtoll CR2 SWAP LL_USART_SetTXRXSwap + * @param USARTx USART Instance + * @param SwapConfig This parameter can be one of the following values: + * @arg @ref LL_USART_TXRX_STANDARD + * @arg @ref LL_USART_TXRX_SWAPPED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTXRXSwap(USART_TypeDef *USARTx, uint32_t SwapConfig) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_SWAP, SwapConfig); +} + +/** + * @brief Retrieve TX/RX pins swapping configuration. + * @rmtoll CR2 SWAP LL_USART_GetTXRXSwap + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_TXRX_STANDARD + * @arg @ref LL_USART_TXRX_SWAPPED + */ +__STATIC_INLINE uint32_t LL_USART_GetTXRXSwap(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_SWAP)); +} + +/** + * @brief Configure RX pin active level logic + * @rmtoll CR2 RXINV LL_USART_SetRXPinLevel + * @param USARTx USART Instance + * @param PinInvMethod This parameter can be one of the following values: + * @arg @ref LL_USART_RXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_RXPIN_LEVEL_INVERTED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetRXPinLevel(USART_TypeDef *USARTx, uint32_t PinInvMethod) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_RXINV, PinInvMethod); +} + +/** + * @brief Retrieve RX pin active level logic configuration + * @rmtoll CR2 RXINV LL_USART_GetRXPinLevel + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_RXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_RXPIN_LEVEL_INVERTED + */ +__STATIC_INLINE uint32_t LL_USART_GetRXPinLevel(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_RXINV)); +} + +/** + * @brief Configure TX pin active level logic + * @rmtoll CR2 TXINV LL_USART_SetTXPinLevel + * @param USARTx USART Instance + * @param PinInvMethod This parameter can be one of the following values: + * @arg @ref LL_USART_TXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_TXPIN_LEVEL_INVERTED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTXPinLevel(USART_TypeDef *USARTx, uint32_t PinInvMethod) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_TXINV, PinInvMethod); +} + +/** + * @brief Retrieve TX pin active level logic configuration + * @rmtoll CR2 TXINV LL_USART_GetTXPinLevel + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_TXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_TXPIN_LEVEL_INVERTED + */ +__STATIC_INLINE uint32_t LL_USART_GetTXPinLevel(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_TXINV)); +} + +/** + * @brief Configure Binary data logic. + * @note Allow to define how Logical data from the data register are send/received : + * either in positive/direct logic (1=H, 0=L) or in negative/inverse logic (1=L, 0=H) + * @rmtoll CR2 DATAINV LL_USART_SetBinaryDataLogic + * @param USARTx USART Instance + * @param DataLogic This parameter can be one of the following values: + * @arg @ref LL_USART_BINARY_LOGIC_POSITIVE + * @arg @ref LL_USART_BINARY_LOGIC_NEGATIVE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBinaryDataLogic(USART_TypeDef *USARTx, uint32_t DataLogic) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_DATAINV, DataLogic); +} + +/** + * @brief Retrieve Binary data configuration + * @rmtoll CR2 DATAINV LL_USART_GetBinaryDataLogic + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_BINARY_LOGIC_POSITIVE + * @arg @ref LL_USART_BINARY_LOGIC_NEGATIVE + */ +__STATIC_INLINE uint32_t LL_USART_GetBinaryDataLogic(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_DATAINV)); +} + +/** + * @brief Configure transfer bit order (either Less or Most Significant Bit First) + * @note MSB First means data is transmitted/received with the MSB first, following the start bit. + * LSB First means data is transmitted/received with data bit 0 first, following the start bit. + * @rmtoll CR2 MSBFIRST LL_USART_SetTransferBitOrder + * @param USARTx USART Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_USART_BITORDER_LSBFIRST + * @arg @ref LL_USART_BITORDER_MSBFIRST + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTransferBitOrder(USART_TypeDef *USARTx, uint32_t BitOrder) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_MSBFIRST, BitOrder); +} + +/** + * @brief Return transfer bit order (either Less or Most Significant Bit First) + * @note MSB First means data is transmitted/received with the MSB first, following the start bit. + * LSB First means data is transmitted/received with data bit 0 first, following the start bit. + * @rmtoll CR2 MSBFIRST LL_USART_GetTransferBitOrder + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_BITORDER_LSBFIRST + * @arg @ref LL_USART_BITORDER_MSBFIRST + */ +__STATIC_INLINE uint32_t LL_USART_GetTransferBitOrder(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_MSBFIRST)); +} + +/** + * @brief Enable Auto Baud-Rate Detection + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_EnableAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableAutoBaudRate(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_ABREN); +} + +/** + * @brief Disable Auto Baud-Rate Detection + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_DisableAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableAutoBaudRate(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_ABREN); +} + +/** + * @brief Indicate if Auto Baud-Rate Detection mechanism is enabled + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_IsEnabledAutoBaud + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledAutoBaud(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_ABREN) == (USART_CR2_ABREN)) ? 1UL : 0UL); +} + +/** + * @brief Set Auto Baud-Rate mode bits + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABRMODE LL_USART_SetAutoBaudRateMode + * @param USARTx USART Instance + * @param AutoBaudRateMode This parameter can be one of the following values: + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_STARTBIT + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_55_FRAME + * @retval None + */ +__STATIC_INLINE void LL_USART_SetAutoBaudRateMode(USART_TypeDef *USARTx, uint32_t AutoBaudRateMode) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_ABRMODE, AutoBaudRateMode); +} + +/** + * @brief Return Auto Baud-Rate mode + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABRMODE LL_USART_GetAutoBaudRateMode + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_STARTBIT + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_55_FRAME + */ +__STATIC_INLINE uint32_t LL_USART_GetAutoBaudRateMode(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ABRMODE)); +} + +/** + * @brief Enable Receiver Timeout + * @rmtoll CR2 RTOEN LL_USART_EnableRxTimeout + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableRxTimeout(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_RTOEN); +} + +/** + * @brief Disable Receiver Timeout + * @rmtoll CR2 RTOEN LL_USART_DisableRxTimeout + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableRxTimeout(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_RTOEN); +} + +/** + * @brief Indicate if Receiver Timeout feature is enabled + * @rmtoll CR2 RTOEN LL_USART_IsEnabledRxTimeout + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledRxTimeout(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_RTOEN) == (USART_CR2_RTOEN)) ? 1UL : 0UL); +} + +/** + * @brief Set Address of the USART node. + * @note This is used in multiprocessor communication during Mute mode or Stop mode, + * for wake up with address mark detection. + * @note 4bits address node is used when 4-bit Address Detection is selected in ADDM7. + * (b7-b4 should be set to 0) + * 8bits address node is used when 7-bit Address Detection is selected in ADDM7. + * (This is used in multiprocessor communication during Mute mode or Stop mode, + * for wake up with 7-bit address mark detection. + * The MSB of the character sent by the transmitter should be equal to 1. + * It may also be used for character detection during normal reception, + * Mute mode inactive (for example, end of block detection in ModBus protocol). + * In this case, the whole received character (8-bit) is compared to the ADD[7:0] + * value and CMF flag is set on match) + * @rmtoll CR2 ADD LL_USART_ConfigNodeAddress\n + * CR2 ADDM7 LL_USART_ConfigNodeAddress + * @param USARTx USART Instance + * @param AddressLen This parameter can be one of the following values: + * @arg @ref LL_USART_ADDRESS_DETECT_4B + * @arg @ref LL_USART_ADDRESS_DETECT_7B + * @param NodeAddress 4 or 7 bit Address of the USART node. + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigNodeAddress(USART_TypeDef *USARTx, uint32_t AddressLen, uint32_t NodeAddress) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_ADD | USART_CR2_ADDM7, + (uint32_t)(AddressLen | (NodeAddress << USART_CR2_ADD_Pos))); +} + +/** + * @brief Return 8 bit Address of the USART node as set in ADD field of CR2. + * @note If 4-bit Address Detection is selected in ADDM7, + * only 4bits (b3-b0) of returned value are relevant (b31-b4 are not relevant) + * If 7-bit Address Detection is selected in ADDM7, + * only 8bits (b7-b0) of returned value are relevant (b31-b8 are not relevant) + * @rmtoll CR2 ADD LL_USART_GetNodeAddress + * @param USARTx USART Instance + * @retval Address of the USART node (Value between Min_Data=0 and Max_Data=255) + */ +__STATIC_INLINE uint32_t LL_USART_GetNodeAddress(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ADD) >> USART_CR2_ADD_Pos); +} + +/** + * @brief Return Length of Node Address used in Address Detection mode (7-bit or 4-bit) + * @rmtoll CR2 ADDM7 LL_USART_GetNodeAddressLen + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_ADDRESS_DETECT_4B + * @arg @ref LL_USART_ADDRESS_DETECT_7B + */ +__STATIC_INLINE uint32_t LL_USART_GetNodeAddressLen(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ADDM7)); +} + +/** + * @brief Enable RTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_EnableRTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableRTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_RTSE); +} + +/** + * @brief Disable RTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_DisableRTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableRTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_RTSE); +} + +/** + * @brief Enable CTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSE LL_USART_EnableCTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableCTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_CTSE); +} + +/** + * @brief Disable CTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSE LL_USART_DisableCTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableCTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_CTSE); +} + +/** + * @brief Configure HW Flow Control mode (both CTS and RTS) + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_SetHWFlowCtrl\n + * CR3 CTSE LL_USART_SetHWFlowCtrl + * @param USARTx USART Instance + * @param HardwareFlowControl This parameter can be one of the following values: + * @arg @ref LL_USART_HWCONTROL_NONE + * @arg @ref LL_USART_HWCONTROL_RTS + * @arg @ref LL_USART_HWCONTROL_CTS + * @arg @ref LL_USART_HWCONTROL_RTS_CTS + * @retval None + */ +__STATIC_INLINE void LL_USART_SetHWFlowCtrl(USART_TypeDef *USARTx, uint32_t HardwareFlowControl) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_RTSE | USART_CR3_CTSE, HardwareFlowControl); +} + +/** + * @brief Return HW Flow Control configuration (both CTS and RTS) + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_GetHWFlowCtrl\n + * CR3 CTSE LL_USART_GetHWFlowCtrl + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_HWCONTROL_NONE + * @arg @ref LL_USART_HWCONTROL_RTS + * @arg @ref LL_USART_HWCONTROL_CTS + * @arg @ref LL_USART_HWCONTROL_RTS_CTS + */ +__STATIC_INLINE uint32_t LL_USART_GetHWFlowCtrl(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_RTSE | USART_CR3_CTSE)); +} + +/** + * @brief Enable One bit sampling method + * @rmtoll CR3 ONEBIT LL_USART_EnableOneBitSamp + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableOneBitSamp(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_ONEBIT); +} + +/** + * @brief Disable One bit sampling method + * @rmtoll CR3 ONEBIT LL_USART_DisableOneBitSamp + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableOneBitSamp(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_ONEBIT); +} + +/** + * @brief Indicate if One bit sampling method is enabled + * @rmtoll CR3 ONEBIT LL_USART_IsEnabledOneBitSamp + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledOneBitSamp(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_ONEBIT) == (USART_CR3_ONEBIT)) ? 1UL : 0UL); +} + +/** + * @brief Enable Overrun detection + * @rmtoll CR3 OVRDIS LL_USART_EnableOverrunDetect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableOverrunDetect(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_OVRDIS); +} + +/** + * @brief Disable Overrun detection + * @rmtoll CR3 OVRDIS LL_USART_DisableOverrunDetect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableOverrunDetect(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_OVRDIS); +} + +/** + * @brief Indicate if Overrun detection is enabled + * @rmtoll CR3 OVRDIS LL_USART_IsEnabledOverrunDetect + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledOverrunDetect(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_OVRDIS) != USART_CR3_OVRDIS) ? 1UL : 0UL); +} + +/** + * @brief Select event type for Wake UP Interrupt Flag (WUS[1:0] bits) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUS LL_USART_SetWKUPType + * @param USARTx USART Instance + * @param Type This parameter can be one of the following values: + * @arg @ref LL_USART_WAKEUP_ON_ADDRESS + * @arg @ref LL_USART_WAKEUP_ON_STARTBIT + * @arg @ref LL_USART_WAKEUP_ON_RXNE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetWKUPType(USART_TypeDef *USARTx, uint32_t Type) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_WUS, Type); +} + +/** + * @brief Return event type for Wake UP Interrupt Flag (WUS[1:0] bits) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUS LL_USART_GetWKUPType + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_WAKEUP_ON_ADDRESS + * @arg @ref LL_USART_WAKEUP_ON_STARTBIT + * @arg @ref LL_USART_WAKEUP_ON_RXNE + */ +__STATIC_INLINE uint32_t LL_USART_GetWKUPType(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_WUS)); +} + +/** + * @brief Configure USART BRR register for achieving expected Baud Rate value. + * @note Compute and set USARTDIV value in BRR Register (full BRR content) + * according to used Peripheral Clock, Oversampling mode, and expected Baud Rate values + * @note Peripheral clock and Baud rate values provided as function parameters should be valid + * (Baud rate value != 0) + * @note In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. + * @rmtoll BRR BRR LL_USART_SetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + * @param OverSampling This parameter can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + * @param BaudRate Baud Rate + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBaudRate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t OverSampling, + uint32_t BaudRate) +{ + uint32_t usartdiv; + uint32_t brrtemp; + + if (OverSampling == LL_USART_OVERSAMPLING_8) + { + usartdiv = (uint16_t)(__LL_USART_DIV_SAMPLING8(PeriphClk, BaudRate)); + brrtemp = usartdiv & 0xFFF0U; + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + USARTx->BRR = brrtemp; + } + else + { + USARTx->BRR = (uint16_t)(__LL_USART_DIV_SAMPLING16(PeriphClk, BaudRate)); + } +} + +/** + * @brief Return current Baud Rate value, according to USARTDIV present in BRR register + * (full BRR content), and to used Peripheral Clock and Oversampling mode values + * @note In case of non-initialized or invalid value stored in BRR register, value 0 will be returned. + * @note In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. + * @rmtoll BRR BRR LL_USART_GetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + * @param OverSampling This parameter can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + * @retval Baud Rate + */ +__STATIC_INLINE uint32_t LL_USART_GetBaudRate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t OverSampling) +{ + uint32_t usartdiv; + uint32_t brrresult = 0x0U; + + usartdiv = USARTx->BRR; + + if (usartdiv == 0U) + { + /* Do not perform a division by 0 */ + } + else if (OverSampling == LL_USART_OVERSAMPLING_8) + { + usartdiv = (uint16_t)((usartdiv & 0xFFF0U) | ((usartdiv & 0x0007U) << 1U)) ; + if (usartdiv != 0U) + { + brrresult = (PeriphClk * 2U) / usartdiv; + } + } + else + { + if ((usartdiv & 0xFFFFU) != 0U) + { + brrresult = PeriphClk / usartdiv; + } + } + return (brrresult); +} + +/** + * @brief Set Receiver Time Out Value (expressed in nb of bits duration) + * @rmtoll RTOR RTO LL_USART_SetRxTimeout + * @param USARTx USART Instance + * @param Timeout Value between Min_Data=0x00 and Max_Data=0x00FFFFFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetRxTimeout(USART_TypeDef *USARTx, uint32_t Timeout) +{ + MODIFY_REG(USARTx->RTOR, USART_RTOR_RTO, Timeout); +} + +/** + * @brief Get Receiver Time Out Value (expressed in nb of bits duration) + * @rmtoll RTOR RTO LL_USART_GetRxTimeout + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x00FFFFFF + */ +__STATIC_INLINE uint32_t LL_USART_GetRxTimeout(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->RTOR, USART_RTOR_RTO)); +} + +/** + * @brief Set Block Length value in reception + * @rmtoll RTOR BLEN LL_USART_SetBlockLength + * @param USARTx USART Instance + * @param BlockLength Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBlockLength(USART_TypeDef *USARTx, uint32_t BlockLength) +{ + MODIFY_REG(USARTx->RTOR, USART_RTOR_BLEN, BlockLength << USART_RTOR_BLEN_Pos); +} + +/** + * @brief Get Block Length value in reception + * @rmtoll RTOR BLEN LL_USART_GetBlockLength + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_USART_GetBlockLength(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->RTOR, USART_RTOR_BLEN) >> USART_RTOR_BLEN_Pos); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_IRDA Configuration functions related to Irda feature + * @{ + */ + +/** + * @brief Enable IrDA mode + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_EnableIrda + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIrda(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Disable IrDA mode + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_DisableIrda + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIrda(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Indicate if IrDA mode is enabled + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_IsEnabledIrda + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIrda(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_IREN) == (USART_CR3_IREN)) ? 1UL : 0UL); +} + +/** + * @brief Configure IrDA Power Mode (Normal or Low Power) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IRLP LL_USART_SetIrdaPowerMode + * @param USARTx USART Instance + * @param PowerMode This parameter can be one of the following values: + * @arg @ref LL_USART_IRDA_POWER_NORMAL + * @arg @ref LL_USART_IRDA_POWER_LOW + * @retval None + */ +__STATIC_INLINE void LL_USART_SetIrdaPowerMode(USART_TypeDef *USARTx, uint32_t PowerMode) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_IRLP, PowerMode); +} + +/** + * @brief Retrieve IrDA Power Mode configuration (Normal or Low Power) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IRLP LL_USART_GetIrdaPowerMode + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_IRDA_POWER_NORMAL + * @arg @ref LL_USART_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_USART_GetIrdaPowerMode(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_IRLP)); +} + +/** + * @brief Set Irda prescaler value, used for dividing the USART clock source + * to achieve the Irda Low Power frequency (8 bits value) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_SetIrdaPrescaler + * @param USARTx USART Instance + * @param PrescalerValue Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetIrdaPrescaler(USART_TypeDef *USARTx, uint32_t PrescalerValue) +{ + MODIFY_REG(USARTx->GTPR, (uint16_t)USART_GTPR_PSC, (uint16_t)PrescalerValue); +} + +/** + * @brief Return Irda prescaler value, used for dividing the USART clock source + * to achieve the Irda Low Power frequency (8 bits value) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_GetIrdaPrescaler + * @param USARTx USART Instance + * @retval Irda prescaler value (Value between Min_Data=0x00 and Max_Data=0xFF) + */ +__STATIC_INLINE uint32_t LL_USART_GetIrdaPrescaler(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_PSC)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_Smartcard Configuration functions related to Smartcard feature + * @{ + */ + +/** + * @brief Enable Smartcard NACK transmission + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_EnableSmartcardNACK + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSmartcardNACK(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_NACK); +} + +/** + * @brief Disable Smartcard NACK transmission + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_DisableSmartcardNACK + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSmartcardNACK(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_NACK); +} + +/** + * @brief Indicate if Smartcard NACK transmission is enabled + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_IsEnabledSmartcardNACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSmartcardNACK(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_NACK) == (USART_CR3_NACK)) ? 1UL : 0UL); +} + +/** + * @brief Enable Smartcard mode + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_EnableSmartcard + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSmartcard(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Disable Smartcard mode + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_DisableSmartcard + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSmartcard(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Indicate if Smartcard mode is enabled + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_IsEnabledSmartcard + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSmartcard(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_SCEN) == (USART_CR3_SCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set Smartcard Auto-Retry Count value (SCARCNT[2:0] bits) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @note This bit-field specifies the number of retries in transmit and receive, in Smartcard mode. + * In transmission mode, it specifies the number of automatic retransmission retries, before + * generating a transmission error (FE bit set). + * In reception mode, it specifies the number or erroneous reception trials, before generating a + * reception error (RXNE and PE bits set) + * @rmtoll CR3 SCARCNT LL_USART_SetSmartcardAutoRetryCount + * @param USARTx USART Instance + * @param AutoRetryCount Value between Min_Data=0 and Max_Data=7 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardAutoRetryCount(USART_TypeDef *USARTx, uint32_t AutoRetryCount) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_SCARCNT, AutoRetryCount << USART_CR3_SCARCNT_Pos); +} + +/** + * @brief Return Smartcard Auto-Retry Count value (SCARCNT[2:0] bits) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCARCNT LL_USART_GetSmartcardAutoRetryCount + * @param USARTx USART Instance + * @retval Smartcard Auto-Retry Count value (Value between Min_Data=0 and Max_Data=7) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardAutoRetryCount(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_SCARCNT) >> USART_CR3_SCARCNT_Pos); +} + +/** + * @brief Set Smartcard prescaler value, used for dividing the USART clock + * source to provide the SMARTCARD Clock (5 bits value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_SetSmartcardPrescaler + * @param USARTx USART Instance + * @param PrescalerValue Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardPrescaler(USART_TypeDef *USARTx, uint32_t PrescalerValue) +{ + MODIFY_REG(USARTx->GTPR, (uint16_t)USART_GTPR_PSC, (uint16_t)PrescalerValue); +} + +/** + * @brief Return Smartcard prescaler value, used for dividing the USART clock + * source to provide the SMARTCARD Clock (5 bits value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_GetSmartcardPrescaler + * @param USARTx USART Instance + * @retval Smartcard prescaler value (Value between Min_Data=0 and Max_Data=31) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardPrescaler(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_PSC)); +} + +/** + * @brief Set Smartcard Guard time value, expressed in nb of baud clocks periods + * (GT[7:0] bits : Guard time value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR GT LL_USART_SetSmartcardGuardTime + * @param USARTx USART Instance + * @param GuardTime Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardGuardTime(USART_TypeDef *USARTx, uint32_t GuardTime) +{ + MODIFY_REG(USARTx->GTPR, (uint16_t)USART_GTPR_GT, (uint16_t)(GuardTime << USART_GTPR_GT_Pos)); +} + +/** + * @brief Return Smartcard Guard time value, expressed in nb of baud clocks periods + * (GT[7:0] bits : Guard time value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR GT LL_USART_GetSmartcardGuardTime + * @param USARTx USART Instance + * @retval Smartcard Guard time value (Value between Min_Data=0x00 and Max_Data=0xFF) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardGuardTime(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_GT) >> USART_GTPR_GT_Pos); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_HalfDuplex Configuration functions related to Half Duplex feature + * @{ + */ + +/** + * @brief Enable Single Wire Half-Duplex mode + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_EnableHalfDuplex + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableHalfDuplex(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Disable Single Wire Half-Duplex mode + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_DisableHalfDuplex + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableHalfDuplex(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Indicate if Single Wire Half-Duplex mode is enabled + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_IsEnabledHalfDuplex + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledHalfDuplex(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_HDSEL) == (USART_CR3_HDSEL)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_LIN Configuration functions related to LIN feature + * @{ + */ + +/** + * @brief Set LIN Break Detection Length + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDL LL_USART_SetLINBrkDetectionLen + * @param USARTx USART Instance + * @param LINBDLength This parameter can be one of the following values: + * @arg @ref LL_USART_LINBREAK_DETECT_10B + * @arg @ref LL_USART_LINBREAK_DETECT_11B + * @retval None + */ +__STATIC_INLINE void LL_USART_SetLINBrkDetectionLen(USART_TypeDef *USARTx, uint32_t LINBDLength) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_LBDL, LINBDLength); +} + +/** + * @brief Return LIN Break Detection Length + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDL LL_USART_GetLINBrkDetectionLen + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_LINBREAK_DETECT_10B + * @arg @ref LL_USART_LINBREAK_DETECT_11B + */ +__STATIC_INLINE uint32_t LL_USART_GetLINBrkDetectionLen(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_LBDL)); +} + +/** + * @brief Enable LIN mode + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_EnableLIN + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableLIN(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Disable LIN mode + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_DisableLIN + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableLIN(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Indicate if LIN mode is enabled + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_IsEnabledLIN + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledLIN(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_LINEN) == (USART_CR2_LINEN)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_DE Configuration functions related to Driver Enable feature + * @{ + */ + +/** + * @brief Set DEDT (Driver Enable De-Assertion Time), Time value expressed on 5 bits ([4:0] bits). + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEDT LL_USART_SetDEDeassertionTime + * @param USARTx USART Instance + * @param Time Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDEDeassertionTime(USART_TypeDef *USARTx, uint32_t Time) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_DEDT, Time << USART_CR1_DEDT_Pos); +} + +/** + * @brief Return DEDT (Driver Enable De-Assertion Time) + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEDT LL_USART_GetDEDeassertionTime + * @param USARTx USART Instance + * @retval Time value expressed on 5 bits ([4:0] bits) : Value between Min_Data=0 and Max_Data=31 + */ +__STATIC_INLINE uint32_t LL_USART_GetDEDeassertionTime(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_DEDT) >> USART_CR1_DEDT_Pos); +} + +/** + * @brief Set DEAT (Driver Enable Assertion Time), Time value expressed on 5 bits ([4:0] bits). + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEAT LL_USART_SetDEAssertionTime + * @param USARTx USART Instance + * @param Time Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDEAssertionTime(USART_TypeDef *USARTx, uint32_t Time) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_DEAT, Time << USART_CR1_DEAT_Pos); +} + +/** + * @brief Return DEAT (Driver Enable Assertion Time) + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEAT LL_USART_GetDEAssertionTime + * @param USARTx USART Instance + * @retval Time value expressed on 5 bits ([4:0] bits) : Value between Min_Data=0 and Max_Data=31 + */ +__STATIC_INLINE uint32_t LL_USART_GetDEAssertionTime(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_DEAT) >> USART_CR1_DEAT_Pos); +} + +/** + * @brief Enable Driver Enable (DE) Mode + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_EnableDEMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDEMode(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_DEM); +} + +/** + * @brief Disable Driver Enable (DE) Mode + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_DisableDEMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDEMode(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_DEM); +} + +/** + * @brief Indicate if Driver Enable (DE) Mode is enabled + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_IsEnabledDEMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDEMode(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DEM) == (USART_CR3_DEM)) ? 1UL : 0UL); +} + +/** + * @brief Select Driver Enable Polarity + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEP LL_USART_SetDESignalPolarity + * @param USARTx USART Instance + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_USART_DE_POLARITY_HIGH + * @arg @ref LL_USART_DE_POLARITY_LOW + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDESignalPolarity(USART_TypeDef *USARTx, uint32_t Polarity) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_DEP, Polarity); +} + +/** + * @brief Return Driver Enable Polarity + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEP LL_USART_GetDESignalPolarity + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DE_POLARITY_HIGH + * @arg @ref LL_USART_DE_POLARITY_LOW + */ +__STATIC_INLINE uint32_t LL_USART_GetDESignalPolarity(USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_DEP)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_AdvancedConfiguration Advanced Configurations services + * @{ + */ + +/** + * @brief Perform basic configuration of USART for enabling use in Asynchronous Mode (UART) + * @note In UART mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * @note Other remaining configurations items related to Asynchronous Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigAsyncMode\n + * CR2 CLKEN LL_USART_ConfigAsyncMode\n + * CR3 SCEN LL_USART_ConfigAsyncMode\n + * CR3 IREN LL_USART_ConfigAsyncMode\n + * CR3 HDSEL LL_USART_ConfigAsyncMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigAsyncMode(USART_TypeDef *USARTx) +{ + /* In Asynchronous mode, the following bits must be kept cleared: + - LINEN, CLKEN bits in the USART_CR2 register, + - SCEN, IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN | USART_CR3_HDSEL)); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Synchronous Mode + * @note In Synchronous mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also sets the USART in Synchronous mode. + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Set CLKEN in CR2 using @ref LL_USART_EnableSCLKOutput() function + * @note Other remaining configurations items related to Synchronous Mode + * (as Baud Rate, Word length, Parity, Clock Polarity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigSyncMode\n + * CR2 CLKEN LL_USART_ConfigSyncMode\n + * CR3 SCEN LL_USART_ConfigSyncMode\n + * CR3 IREN LL_USART_ConfigSyncMode\n + * CR3 HDSEL LL_USART_ConfigSyncMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigSyncMode(USART_TypeDef *USARTx) +{ + /* In Synchronous mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register, + - SCEN, IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN | USART_CR3_HDSEL)); + /* set the UART/USART in Synchronous mode */ + SET_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in LIN Mode + * @note In LIN mode, the following bits must be kept cleared: + * - STOP and CLKEN bits in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also set the UART/USART in LIN mode. + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Set LINEN in CR2 using @ref LL_USART_EnableLIN() function + * @note Other remaining configurations items related to LIN Mode + * (as Baud Rate, Word length, LIN Break Detection Length, ...) should be set using + * dedicated functions + * @rmtoll CR2 CLKEN LL_USART_ConfigLINMode\n + * CR2 STOP LL_USART_ConfigLINMode\n + * CR2 LINEN LL_USART_ConfigLINMode\n + * CR3 IREN LL_USART_ConfigLINMode\n + * CR3 SCEN LL_USART_ConfigLINMode\n + * CR3 HDSEL LL_USART_ConfigLINMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigLINMode(USART_TypeDef *USARTx) +{ + /* In LIN mode, the following bits must be kept cleared: + - STOP and CLKEN bits in the USART_CR2 register, + - IREN, SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_CLKEN | USART_CR2_STOP)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_IREN | USART_CR3_SCEN | USART_CR3_HDSEL)); + /* Set the UART/USART in LIN mode */ + SET_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Half Duplex Mode + * @note In Half Duplex mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * This function also sets the UART/USART in Half Duplex mode. + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Set HDSEL in CR3 using @ref LL_USART_EnableHalfDuplex() function + * @note Other remaining configurations items related to Half Duplex Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigHalfDuplexMode\n + * CR2 CLKEN LL_USART_ConfigHalfDuplexMode\n + * CR3 HDSEL LL_USART_ConfigHalfDuplexMode\n + * CR3 SCEN LL_USART_ConfigHalfDuplexMode\n + * CR3 IREN LL_USART_ConfigHalfDuplexMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigHalfDuplexMode(USART_TypeDef *USARTx) +{ + /* In Half Duplex mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN)); + /* set the UART/USART in Half Duplex mode */ + SET_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Smartcard Mode + * @note In Smartcard mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also configures Stop bits to 1.5 bits and + * sets the USART in Smartcard mode (SCEN bit). + * Clock Output is also enabled (CLKEN). + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Configure STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Set CLKEN in CR2 using @ref LL_USART_EnableSCLKOutput() function + * - Set SCEN in CR3 using @ref LL_USART_EnableSmartcard() function + * @note Other remaining configurations items related to Smartcard Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigSmartcardMode\n + * CR2 STOP LL_USART_ConfigSmartcardMode\n + * CR2 CLKEN LL_USART_ConfigSmartcardMode\n + * CR3 HDSEL LL_USART_ConfigSmartcardMode\n + * CR3 SCEN LL_USART_ConfigSmartcardMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigSmartcardMode(USART_TypeDef *USARTx) +{ + /* In Smartcard mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register, + - IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_IREN | USART_CR3_HDSEL)); + /* Configure Stop bits to 1.5 bits */ + /* Synchronous mode is activated by default */ + SET_BIT(USARTx->CR2, (USART_CR2_STOP_0 | USART_CR2_STOP_1 | USART_CR2_CLKEN)); + /* set the UART/USART in Smartcard mode */ + SET_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Irda Mode + * @note In IRDA mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - STOP and CLKEN bits in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also sets the UART/USART in IRDA mode (IREN bit). + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Configure STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Set IREN in CR3 using @ref LL_USART_EnableIrda() function + * @note Other remaining configurations items related to Irda Mode + * (as Baud Rate, Word length, Power mode, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigIrdaMode\n + * CR2 CLKEN LL_USART_ConfigIrdaMode\n + * CR2 STOP LL_USART_ConfigIrdaMode\n + * CR3 SCEN LL_USART_ConfigIrdaMode\n + * CR3 HDSEL LL_USART_ConfigIrdaMode\n + * CR3 IREN LL_USART_ConfigIrdaMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigIrdaMode(USART_TypeDef *USARTx) +{ + /* In IRDA mode, the following bits must be kept cleared: + - LINEN, STOP and CLKEN bits in the USART_CR2 register, + - SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN | USART_CR2_STOP)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL)); + /* set the UART/USART in IRDA mode */ + SET_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Multi processor Mode + * (several USARTs connected in a network, one of the USARTs can be the master, + * its TX output connected to the RX inputs of the other slaves USARTs). + * @note In MultiProcessor mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * @note Other remaining configurations items related to Multi processor Mode + * (as Baud Rate, Wake Up Method, Node address, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigMultiProcessMode\n + * CR2 CLKEN LL_USART_ConfigMultiProcessMode\n + * CR3 SCEN LL_USART_ConfigMultiProcessMode\n + * CR3 HDSEL LL_USART_ConfigMultiProcessMode\n + * CR3 IREN LL_USART_ConfigMultiProcessMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigMultiProcessMode(USART_TypeDef *USARTx) +{ + /* In Multi Processor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - IREN, SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Check if the USART Parity Error Flag is set or not + * @rmtoll ISR PE LL_USART_IsActiveFlag_PE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_PE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_PE) == (USART_ISR_PE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Framing Error Flag is set or not + * @rmtoll ISR FE LL_USART_IsActiveFlag_FE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_FE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_FE) == (USART_ISR_FE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Noise error detected Flag is set or not + * @rmtoll ISR NE LL_USART_IsActiveFlag_NE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_NE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_NE) == (USART_ISR_NE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART OverRun Error Flag is set or not + * @rmtoll ISR ORE LL_USART_IsActiveFlag_ORE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ORE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ORE) == (USART_ISR_ORE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART IDLE line detected Flag is set or not + * @rmtoll ISR IDLE LL_USART_IsActiveFlag_IDLE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_IDLE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_IDLE) == (USART_ISR_IDLE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Read Data Register Not Empty Flag is set or not + * @rmtoll ISR RXNE LL_USART_IsActiveFlag_RXNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXNE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RXNE) == (USART_ISR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Transmission Complete Flag is set or not + * @rmtoll ISR TC LL_USART_IsActiveFlag_TC + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TC(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TC) == (USART_ISR_TC)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Transmit Data Register Empty Flag is set or not + * @rmtoll ISR TXE LL_USART_IsActiveFlag_TXE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TXE) == (USART_ISR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART LIN Break Detection Flag is set or not + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll ISR LBDF LL_USART_IsActiveFlag_LBD + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_LBD(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_LBDF) == (USART_ISR_LBDF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS interrupt Flag is set or not + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ISR CTSIF LL_USART_IsActiveFlag_nCTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_nCTS(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CTSIF) == (USART_ISR_CTSIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS Flag is set or not + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ISR CTS LL_USART_IsActiveFlag_CTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_CTS(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CTS) == (USART_ISR_CTS)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receiver Time Out Flag is set or not + * @rmtoll ISR RTOF LL_USART_IsActiveFlag_RTO + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RTO(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RTOF) == (USART_ISR_RTOF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART End Of Block Flag is set or not + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll ISR EOBF LL_USART_IsActiveFlag_EOB + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_EOB(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_EOBF) == (USART_ISR_EOBF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Auto-Baud Rate Error Flag is set or not + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll ISR ABRE LL_USART_IsActiveFlag_ABRE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ABRE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ABRE) == (USART_ISR_ABRE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Auto-Baud Rate Flag is set or not + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll ISR ABRF LL_USART_IsActiveFlag_ABR + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ABR(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ABRF) == (USART_ISR_ABRF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Busy Flag is set or not + * @rmtoll ISR BUSY LL_USART_IsActiveFlag_BUSY + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_BUSY(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_BUSY) == (USART_ISR_BUSY)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Character Match Flag is set or not + * @rmtoll ISR CMF LL_USART_IsActiveFlag_CM + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_CM(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CMF) == (USART_ISR_CMF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Send Break Flag is set or not + * @rmtoll ISR SBKF LL_USART_IsActiveFlag_SBK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_SBK(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_SBKF) == (USART_ISR_SBKF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receive Wake Up from mute mode Flag is set or not + * @rmtoll ISR RWU LL_USART_IsActiveFlag_RWU + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RWU(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RWU) == (USART_ISR_RWU)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Wake Up from stop mode Flag is set or not + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll ISR WUF LL_USART_IsActiveFlag_WKUP + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_WKUP(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_WUF) == (USART_ISR_WUF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Transmit Enable Acknowledge Flag is set or not + * @rmtoll ISR TEACK LL_USART_IsActiveFlag_TEACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TEACK(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TEACK) == (USART_ISR_TEACK)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receive Enable Acknowledge Flag is set or not + * @rmtoll ISR REACK LL_USART_IsActiveFlag_REACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_REACK(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_REACK) == (USART_ISR_REACK)) ? 1UL : 0UL); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Check if the Smartcard Transmission Complete Before Guard Time Flag is set or not + * @rmtoll ISR TCBGT LL_USART_IsActiveFlag_TCBGT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TCBGT(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TCBGT) == (USART_ISR_TCBGT)) ? 1UL : 0UL); +} + +#endif /* USART_TCBGT_SUPPORT */ +/** + * @brief Clear Parity Error Flag + * @rmtoll ICR PECF LL_USART_ClearFlag_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_PE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_PECF); +} + +/** + * @brief Clear Framing Error Flag + * @rmtoll ICR FECF LL_USART_ClearFlag_FE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_FE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_FECF); +} + +/** + * @brief Clear Noise Error detected Flag + * @rmtoll ICR NCF LL_USART_ClearFlag_NE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_NE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_NCF); +} + +/** + * @brief Clear OverRun Error Flag + * @rmtoll ICR ORECF LL_USART_ClearFlag_ORE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_ORE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_ORECF); +} + +/** + * @brief Clear IDLE line detected Flag + * @rmtoll ICR IDLECF LL_USART_ClearFlag_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_IDLE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_IDLECF); +} + +/** + * @brief Clear Transmission Complete Flag + * @rmtoll ICR TCCF LL_USART_ClearFlag_TC + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TC(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_TCCF); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Clear Smartcard Transmission Complete Before Guard Time Flag + * @rmtoll ICR TCBGTCF LL_USART_ClearFlag_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TCBGT(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_TCBGTCF); +} +#endif /* USART_TCBGT_SUPPORT */ + +/** + * @brief Clear LIN Break Detection Flag + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll ICR LBDCF LL_USART_ClearFlag_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_LBD(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_LBDCF); +} + +/** + * @brief Clear CTS Interrupt Flag + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ICR CTSCF LL_USART_ClearFlag_nCTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_nCTS(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_CTSCF); +} + +/** + * @brief Clear Receiver Time Out Flag + * @rmtoll ICR RTOCF LL_USART_ClearFlag_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_RTO(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_RTOCF); +} + +/** + * @brief Clear End Of Block Flag + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll ICR EOBCF LL_USART_ClearFlag_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_EOB(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_EOBCF); +} + +/** + * @brief Clear Character Match Flag + * @rmtoll ICR CMCF LL_USART_ClearFlag_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_CM(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_CMCF); +} + +/** + * @brief Clear Wake Up from stop mode Flag + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll ICR WUCF LL_USART_ClearFlag_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_WKUP(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_WUCF); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable IDLE Interrupt + * @rmtoll CR1 IDLEIE LL_USART_EnableIT_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_IDLE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_IDLEIE); +} + +/** + * @brief Enable RX Not Empty Interrupt + * @rmtoll CR1 RXNEIE LL_USART_EnableIT_RXNE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RXNE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RXNEIE); +} + +/** + * @brief Enable Transmission Complete Interrupt + * @rmtoll CR1 TCIE LL_USART_EnableIT_TC + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TC(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TCIE); +} + +/** + * @brief Enable TX Empty Interrupt + * @rmtoll CR1 TXEIE LL_USART_EnableIT_TXE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TXE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TXEIE); +} + +/** + * @brief Enable Parity Error Interrupt + * @rmtoll CR1 PEIE LL_USART_EnableIT_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_PE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_PEIE); +} + +/** + * @brief Enable Character Match Interrupt + * @rmtoll CR1 CMIE LL_USART_EnableIT_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_CM(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_CMIE); +} + +/** + * @brief Enable Receiver Timeout Interrupt + * @rmtoll CR1 RTOIE LL_USART_EnableIT_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RTO(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RTOIE); +} + +/** + * @brief Enable End Of Block Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_EnableIT_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_EOB(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_EOBIE); +} + +/** + * @brief Enable LIN Break Detection Interrupt + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_EnableIT_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_LBD(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_LBDIE); +} + +/** + * @brief Enable Error Interrupt + * @note When set, Error Interrupt Enable Bit is enabling interrupt generation in case of a framing + * error, overrun error or noise flag (FE=1 or ORE=1 or NF=1 in the USARTx_ISR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_ISR register. + * @rmtoll CR3 EIE LL_USART_EnableIT_ERROR + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_ERROR(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_EIE); +} + +/** + * @brief Enable CTS Interrupt + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_EnableIT_CTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_CTS(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_CTSIE); +} + +/** + * @brief Enable Wake Up from Stop Mode Interrupt + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_EnableIT_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_WKUP(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_WUFIE); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Enable Smartcard Transmission Complete Before Guard Time Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_EnableIT_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TCBGT(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_TCBGTIE); +} +#endif /* USART_TCBGT_SUPPORT */ + +/** + * @brief Disable IDLE Interrupt + * @rmtoll CR1 IDLEIE LL_USART_DisableIT_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_IDLE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_IDLEIE); +} + +/** + * @brief Disable RX Not Empty Interrupt + * @rmtoll CR1 RXNEIE LL_USART_DisableIT_RXNE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RXNE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RXNEIE); +} + +/** + * @brief Disable Transmission Complete Interrupt + * @rmtoll CR1 TCIE LL_USART_DisableIT_TC + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TC(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TCIE); +} + +/** + * @brief Disable TX Empty Interrupt + * @rmtoll CR1 TXEIE LL_USART_DisableIT_TXE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TXE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TXEIE); +} + +/** + * @brief Disable Parity Error Interrupt + * @rmtoll CR1 PEIE LL_USART_DisableIT_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_PE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_PEIE); +} + +/** + * @brief Disable Character Match Interrupt + * @rmtoll CR1 CMIE LL_USART_DisableIT_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_CM(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_CMIE); +} + +/** + * @brief Disable Receiver Timeout Interrupt + * @rmtoll CR1 RTOIE LL_USART_DisableIT_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RTO(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RTOIE); +} + +/** + * @brief Disable End Of Block Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_DisableIT_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_EOB(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_EOBIE); +} + +/** + * @brief Disable LIN Break Detection Interrupt + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_DisableIT_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_LBD(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_LBDIE); +} + +/** + * @brief Disable Error Interrupt + * @note When set, Error Interrupt Enable Bit is enabling interrupt generation in case of a framing + * error, overrun error or noise flag (FE=1 or ORE=1 or NF=1 in the USARTx_ISR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_ISR register. + * @rmtoll CR3 EIE LL_USART_DisableIT_ERROR + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_ERROR(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_EIE); +} + +/** + * @brief Disable CTS Interrupt + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_DisableIT_CTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_CTS(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_CTSIE); +} + +/** + * @brief Disable Wake Up from Stop Mode Interrupt + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_DisableIT_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_WKUP(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_WUFIE); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Disable Smartcard Transmission Complete Before Guard Time Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_DisableIT_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TCBGT(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_TCBGTIE); +} +#endif /* USART_TCBGT_SUPPORT */ + +/** + * @brief Check if the USART IDLE Interrupt source is enabled or disabled. + * @rmtoll CR1 IDLEIE LL_USART_IsEnabledIT_IDLE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_IDLE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_IDLEIE) == (USART_CR1_IDLEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART RX Not Empty Interrupt is enabled or disabled. + * @rmtoll CR1 RXNEIE LL_USART_IsEnabledIT_RXNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RXNE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_RXNEIE) == (USART_CR1_RXNEIE)) ? 1U : 0U); +} + +/** + * @brief Check if the USART Transmission Complete Interrupt is enabled or disabled. + * @rmtoll CR1 TCIE LL_USART_IsEnabledIT_TC + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TC(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_TCIE) == (USART_CR1_TCIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART TX Empty Interrupt is enabled or disabled. + * @rmtoll CR1 TXEIE LL_USART_IsEnabledIT_TXE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TXE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_TXEIE) == (USART_CR1_TXEIE)) ? 1U : 0U); +} + +/** + * @brief Check if the USART Parity Error Interrupt is enabled or disabled. + * @rmtoll CR1 PEIE LL_USART_IsEnabledIT_PE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_PE(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_PEIE) == (USART_CR1_PEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Character Match Interrupt is enabled or disabled. + * @rmtoll CR1 CMIE LL_USART_IsEnabledIT_CM + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_CM(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_CMIE) == (USART_CR1_CMIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receiver Timeout Interrupt is enabled or disabled. + * @rmtoll CR1 RTOIE LL_USART_IsEnabledIT_RTO + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RTO(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_RTOIE) == (USART_CR1_RTOIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART End Of Block Interrupt is enabled or disabled. + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_IsEnabledIT_EOB + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_EOB(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_EOBIE) == (USART_CR1_EOBIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART LIN Break Detection Interrupt is enabled or disabled. + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_IsEnabledIT_LBD + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_LBD(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_LBDIE) == (USART_CR2_LBDIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Error Interrupt is enabled or disabled. + * @rmtoll CR3 EIE LL_USART_IsEnabledIT_ERROR + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_ERROR(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_EIE) == (USART_CR3_EIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS Interrupt is enabled or disabled. + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_IsEnabledIT_CTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_CTS(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_CTSIE) == (USART_CR3_CTSIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Wake Up from Stop Mode Interrupt is enabled or disabled. + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_IsEnabledIT_WKUP + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_WKUP(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_WUFIE) == (USART_CR3_WUFIE)) ? 1UL : 0UL); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Check if the Smartcard Transmission Complete Before Guard Time Interrupt is enabled or disabled. + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_IsEnabledIT_TCBGT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TCBGT(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_TCBGTIE) == (USART_CR3_TCBGTIE)) ? 1UL : 0UL); +} +#endif /* USART_TCBGT_SUPPORT */ + +/** + * @} + */ + +/** @defgroup USART_LL_EF_DMA_Management DMA_Management + * @{ + */ + +/** + * @brief Enable DMA Mode for reception + * @rmtoll CR3 DMAR LL_USART_EnableDMAReq_RX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDMAReq_RX(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_DMAR); +} + +/** + * @brief Disable DMA Mode for reception + * @rmtoll CR3 DMAR LL_USART_DisableDMAReq_RX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDMAReq_RX(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_DMAR); +} + +/** + * @brief Check if DMA Mode is enabled for reception + * @rmtoll CR3 DMAR LL_USART_IsEnabledDMAReq_RX + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDMAReq_RX(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DMAR) == (USART_CR3_DMAR)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Mode for transmission + * @rmtoll CR3 DMAT LL_USART_EnableDMAReq_TX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDMAReq_TX(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_DMAT); +} + +/** + * @brief Disable DMA Mode for transmission + * @rmtoll CR3 DMAT LL_USART_DisableDMAReq_TX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDMAReq_TX(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_DMAT); +} + +/** + * @brief Check if DMA Mode is enabled for transmission + * @rmtoll CR3 DMAT LL_USART_IsEnabledDMAReq_TX + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDMAReq_TX(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DMAT) == (USART_CR3_DMAT)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Disabling on Reception Error + * @rmtoll CR3 DDRE LL_USART_EnableDMADeactOnRxErr + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDMADeactOnRxErr(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_DDRE); +} + +/** + * @brief Disable DMA Disabling on Reception Error + * @rmtoll CR3 DDRE LL_USART_DisableDMADeactOnRxErr + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDMADeactOnRxErr(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_DDRE); +} + +/** + * @brief Indicate if DMA Disabling on Reception Error is disabled + * @rmtoll CR3 DDRE LL_USART_IsEnabledDMADeactOnRxErr + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDMADeactOnRxErr(USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DDRE) == (USART_CR3_DDRE)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll RDR RDR LL_USART_DMA_GetRegAddr\n + * @rmtoll TDR TDR LL_USART_DMA_GetRegAddr + * @param USARTx USART Instance + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_USART_DMA_REG_DATA_TRANSMIT + * @arg @ref LL_USART_DMA_REG_DATA_RECEIVE + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_USART_DMA_GetRegAddr(USART_TypeDef *USARTx, uint32_t Direction) +{ + uint32_t data_reg_addr; + + if (Direction == LL_USART_DMA_REG_DATA_TRANSMIT) + { + /* return address of TDR register */ + data_reg_addr = (uint32_t) &(USARTx->TDR); + } + else + { + /* return address of RDR register */ + data_reg_addr = (uint32_t) &(USARTx->RDR); + } + + return data_reg_addr; +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Read Receiver Data register (Receive Data value, 8 bits) + * @rmtoll RDR RDR LL_USART_ReceiveData8 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_USART_ReceiveData8(USART_TypeDef *USARTx) +{ + return (uint8_t)(READ_BIT(USARTx->RDR, USART_RDR_RDR) & 0xFFU); +} + +/** + * @brief Read Receiver Data register (Receive Data value, 9 bits) + * @rmtoll RDR RDR LL_USART_ReceiveData9 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x1FF + */ +__STATIC_INLINE uint16_t LL_USART_ReceiveData9(USART_TypeDef *USARTx) +{ + return (uint16_t)(READ_BIT(USARTx->RDR, USART_RDR_RDR)); +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 8 bits) + * @rmtoll TDR TDR LL_USART_TransmitData8 + * @param USARTx USART Instance + * @param Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_TransmitData8(USART_TypeDef *USARTx, uint8_t Value) +{ + USARTx->TDR = Value; +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 9 bits) + * @rmtoll TDR TDR LL_USART_TransmitData9 + * @param USARTx USART Instance + * @param Value between Min_Data=0x00 and Max_Data=0x1FF + * @retval None + */ +__STATIC_INLINE void LL_USART_TransmitData9(USART_TypeDef *USARTx, uint16_t Value) +{ + USARTx->TDR = (uint16_t)(Value & 0x1FFUL); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Execution Execution + * @{ + */ + +/** + * @brief Request an Automatic Baud Rate measurement on next received data frame + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll RQR ABRRQ LL_USART_RequestAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestAutoBaudRate(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_ABRRQ); +} + +/** + * @brief Request Break sending + * @rmtoll RQR SBKRQ LL_USART_RequestBreakSending + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestBreakSending(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_SBKRQ); +} + +/** + * @brief Put USART in mute mode and set the RWU flag + * @rmtoll RQR MMRQ LL_USART_RequestEnterMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestEnterMuteMode(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_MMRQ); +} + +/** + * @brief Request a Receive Data flush + * @note Allows to discard the received data without reading them, and avoid an overrun + * condition. + * @rmtoll RQR RXFRQ LL_USART_RequestRxDataFlush + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestRxDataFlush(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_RXFRQ); +} + +/** + * @brief Request a Transmit data flush + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll RQR TXFRQ LL_USART_RequestTxDataFlush + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestTxDataFlush(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_TXFRQ); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EF_Init Initialization and de-initialization functions + * @{ + */ +ErrorStatus LL_USART_DeInit(USART_TypeDef *USARTx); +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, LL_USART_InitTypeDef *USART_InitStruct); +void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct); +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* USART1 || USART2 || USART4 || USART5 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L0xx_LL_USART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c index 58ccb6c..6d37773 100644 --- a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c @@ -25,7 +25,7 @@ #include "stm32_assert.h" #else #define assert_param(expr) ((void)0U) -#endif +#endif /* USE_FULL_ASSERT */ /** @addtogroup STM32L0xx_LL_Driver * @{ @@ -109,7 +109,7 @@ ErrorStatus LL_I2C_DeInit(I2C_TypeDef *I2Cx) LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C2); } -#endif +#endif /* I2C2 */ #if defined(I2C3) else if (I2Cx == I2C3) { @@ -119,7 +119,7 @@ ErrorStatus LL_I2C_DeInit(I2C_TypeDef *I2Cx) /* Release reset of I2C clock */ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3); } -#endif +#endif /* I2C3 */ else { status = ERROR; diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c index 2bd1b44..ca9db9a 100644 --- a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c @@ -75,11 +75,11 @@ /** @defgroup RCC_LL_Private_Functions RCC Private functions * @{ */ -uint32_t RCC_GetSystemClockFreq(void); -uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency); -uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency); -uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency); -uint32_t RCC_PLL_GetFreqDomain_SYS(void); +static uint32_t RCC_GetSystemClockFreq(void); +static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency); +static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency); +static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency); +static uint32_t RCC_PLL_GetFreqDomain_SYS(void); /** * @} */ @@ -576,7 +576,7 @@ uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource) * @brief Return SYSTEM clock frequency * @retval SYSTEM clock frequency (in Hz) */ -uint32_t RCC_GetSystemClockFreq(void) +static uint32_t RCC_GetSystemClockFreq(void) { uint32_t frequency; @@ -619,7 +619,7 @@ uint32_t RCC_GetSystemClockFreq(void) * @param SYSCLK_Frequency SYSCLK clock frequency * @retval HCLK clock frequency (in Hz) */ -uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency) +static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency) { /* HCLK clock frequency */ return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler()); @@ -630,7 +630,7 @@ uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency) * @param HCLK_Frequency HCLK clock frequency * @retval PCLK1 clock frequency (in Hz) */ -uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency) +static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency) { /* PCLK1 clock frequency */ return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler()); @@ -641,7 +641,7 @@ uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency) * @param HCLK_Frequency HCLK clock frequency * @retval PCLK2 clock frequency (in Hz) */ -uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency) +static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency) { /* PCLK2 clock frequency */ return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler()); @@ -651,7 +651,7 @@ uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency) * @brief Return PLL clock frequency used for system domain * @retval PLL clock frequency (in Hz) */ -uint32_t RCC_PLL_GetFreqDomain_SYS(void) +static uint32_t RCC_PLL_GetFreqDomain_SYS(void) { uint32_t pllinputfreq, pllsource; diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c index 08e5dca..dd5c015 100644 --- a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c @@ -214,7 +214,8 @@ void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct) /** * @brief Configure the TIMx time base unit. * @param TIMx Timer Instance - * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (TIMx time base unit configuration data structure) + * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure + * (TIMx time base unit configuration data structure) * @retval An ErrorStatus enumeration value: * - SUCCESS: TIMx registers are de-initialized * - ERROR: not applicable @@ -260,7 +261,8 @@ ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, LL_TIM_InitTypeDef *TIM_InitStruct) /** * @brief Set the fields of the TIMx output channel configuration data * structure to their default values. - * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (the output channel configuration data structure) + * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure + * (the output channel configuration data structure) * @retval None */ void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct) @@ -280,7 +282,8 @@ void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct) * @arg @ref LL_TIM_CHANNEL_CH2 * @arg @ref LL_TIM_CHANNEL_CH3 * @arg @ref LL_TIM_CHANNEL_CH4 - * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration data structure) + * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration + * data structure) * @retval An ErrorStatus enumeration value: * - SUCCESS: TIMx output channel is initialized * - ERROR: TIMx output channel is not initialized @@ -313,7 +316,8 @@ ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_OC_InitTy /** * @brief Set the fields of the TIMx input channel configuration data * structure to their default values. - * @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration data structure) + * @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration + * data structure) * @retval None */ void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) @@ -333,7 +337,8 @@ void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) * @arg @ref LL_TIM_CHANNEL_CH2 * @arg @ref LL_TIM_CHANNEL_CH3 * @arg @ref LL_TIM_CHANNEL_CH4 - * @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data structure) + * @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data + * structure) * @retval An ErrorStatus enumeration value: * - SUCCESS: TIMx output channel is initialized * - ERROR: TIMx output channel is not initialized @@ -365,7 +370,8 @@ ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_IC_InitTy /** * @brief Fills each TIM_EncoderInitStruct field with its default value - * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface configuration data structure) + * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface + * configuration data structure) * @retval None */ void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct) @@ -385,7 +391,8 @@ void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct /** * @brief Configure the encoder interface of the timer instance. * @param TIMx Timer Instance - * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface configuration data structure) + * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface + * configuration data structure) * @retval An ErrorStatus enumeration value: * - SUCCESS: TIMx registers are de-initialized * - ERROR: not applicable diff --git a/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c new file mode 100644 index 0000000..47de09d --- /dev/null +++ b/fw/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_usart.c @@ -0,0 +1,420 @@ +/** + ****************************************************************************** + * @file stm32l0xx_ll_usart.c + * @author MCD Application Team + * @brief USART LL module driver. + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l0xx_ll_usart.h" +#include "stm32l0xx_ll_rcc.h" +#include "stm32l0xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L0xx_LL_Driver + * @{ + */ + +#if defined (USART1) || defined (USART2) || defined (USART4) || defined (USART5) + +/** @addtogroup USART_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup USART_LL_Private_Macros + * @{ + */ + +/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available + * divided by the smallest oversampling used on the USART (i.e. 8) */ +#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 4000000U) + +/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */ +#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U) + +#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \ + || ((__VALUE__) == LL_USART_DIRECTION_RX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX_RX)) + +#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \ + || ((__VALUE__) == LL_USART_PARITY_EVEN) \ + || ((__VALUE__) == LL_USART_PARITY_ODD)) + +#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_7B) \ + || ((__VALUE__) == LL_USART_DATAWIDTH_8B) \ + || ((__VALUE__) == LL_USART_DATAWIDTH_9B)) + +#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \ + || ((__VALUE__) == LL_USART_OVERSAMPLING_8)) + +#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \ + || ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT)) + +#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \ + || ((__VALUE__) == LL_USART_PHASE_2EDGE)) + +#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \ + || ((__VALUE__) == LL_USART_POLARITY_HIGH)) + +#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \ + || ((__VALUE__) == LL_USART_CLOCK_ENABLE)) + +#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_1) \ + || ((__VALUE__) == LL_USART_STOPBITS_1_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_2)) + +#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_CTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS)) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup USART_LL_Exported_Functions + * @{ + */ + +/** @addtogroup USART_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize USART registers (Registers restored to their default values). + * @param USARTx USART Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are de-initialized + * - ERROR: USART registers are not de-initialized + */ +ErrorStatus LL_USART_DeInit(USART_TypeDef *USARTx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + +#if defined(USART1) + if (USARTx == USART1) + { + /* Force reset of USART clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART1); + + /* Release reset of USART clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART1); + } +#endif /* USART1 */ +#if defined(USART1) + else if (USARTx == USART2) +#else + if (USARTx == USART2) +#endif /* USART1 */ + { + /* Force reset of USART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART2); + + /* Release reset of USART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART2); + } +#if defined(USART4) + else if (USARTx == USART4) + { + /* Force reset of USART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART4); + + /* Release reset of USART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART4); + } +#endif /* USART4 */ +#if defined(USART5) + else if (USARTx == USART5) + { + /* Force reset of USART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART5); + + /* Release reset of USART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART5); + } +#endif /* USART5 */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Initialize USART registers according to the specified + * parameters in USART_InitStruct. + * @note As some bits in USART configuration registers can only be written when + * the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling + * this function. Otherwise, ERROR result will be returned. + * @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0). + * @param USARTx USART Instance + * @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure + * that contains the configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are initialized according to USART_InitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, LL_USART_InitTypeDef *USART_InitStruct) +{ + ErrorStatus status = ERROR; + uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO; +#if defined(USART4) || defined(USART5) + LL_RCC_ClocksTypeDef RCC_Clocks; +#endif /* USART4 || USART5 */ + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate)); + assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth)); + assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits)); + assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity)); + assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection)); + assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl)); + assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling)); + + /* USART needs to be in disabled state, in order to be able to configure some bits in + CRx registers */ + if (LL_USART_IsEnabled(USARTx) == 0U) + { + /*---------------------------- USART CR1 Configuration --------------------- + * Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters: + * - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value + * - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value + * - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value + * - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value. + */ + MODIFY_REG(USARTx->CR1, + (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8), + (USART_InitStruct->DataWidth | USART_InitStruct->Parity | + USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling)); + + /*---------------------------- USART CR2 Configuration --------------------- + * Configure USARTx CR2 (Stop bits) with parameters: + * - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value. + * - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit(). + */ + LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits); + + /*---------------------------- USART CR3 Configuration --------------------- + * Configure USARTx CR3 (Hardware Flow Control) with parameters: + * - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to + * USART_InitStruct->HardwareFlowControl value. + */ + LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl); + + /*---------------------------- USART BRR Configuration --------------------- + * Retrieve Clock frequency used for USART Peripheral + */ +#if defined(USART1) + if (USARTx == USART1) + { + periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE); + } +#endif /* USART1 */ +#if defined(USART1) + else if (USARTx == USART2) +#else + if (USARTx == USART2) +#endif /* USART1 */ + { + periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART2_CLKSOURCE); + } +#if defined(USART4) + else if (USARTx == USART4) + { + /* USART4 clock is PCLK1 */ + LL_RCC_GetSystemClocksFreq(&RCC_Clocks); + periphclk = RCC_Clocks.PCLK1_Frequency; + } +#endif /* USART4 */ +#if defined(USART5) + else if (USARTx == USART5) + { + /* USART5 clock is PCLK1 */ + LL_RCC_GetSystemClocksFreq(&RCC_Clocks); + periphclk = RCC_Clocks.PCLK1_Frequency; + } +#endif /* USART5 */ + else + { + /* Nothing to do, as error code is already assigned to ERROR value */ + } + + /* Configure the USART Baud Rate : + - valid baud rate value (different from 0) is required + - Peripheral clock as returned by RCC service, should be valid (different from 0). + */ + if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO) + && (USART_InitStruct->BaudRate != 0U)) + { + status = SUCCESS; + LL_USART_SetBaudRate(USARTx, + periphclk, + USART_InitStruct->OverSampling, + USART_InitStruct->BaudRate); + + /* Check BRR is greater than or equal to 16d */ + assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR)); + } + } + /* Endif (=> USART not in Disabled state => return ERROR) */ + + return (status); +} + +/** + * @brief Set each @ref LL_USART_InitTypeDef field to default value. + * @param USART_InitStruct pointer to a @ref LL_USART_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ + +void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct) +{ + /* Set USART_InitStruct fields to default values */ + USART_InitStruct->BaudRate = 9600U; + USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B; + USART_InitStruct->StopBits = LL_USART_STOPBITS_1; + USART_InitStruct->Parity = LL_USART_PARITY_NONE ; + USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16; +} + +/** + * @brief Initialize USART Clock related settings according to the + * specified parameters in the USART_ClockInitStruct. + * @note As some bits in USART configuration registers can only be written when + * the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling + * this function. Otherwise, ERROR result will be returned. + * @param USARTx USART Instance + * @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure + * that contains the Clock configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers related to Clock settings are initialized according + * to USART_ClockInitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, LL_USART_ClockInitTypeDef *USART_ClockInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check USART Instance and Clock signal output parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + assert_param(IS_LL_USART_CLOCKOUTPUT(USART_ClockInitStruct->ClockOutput)); + + /* USART needs to be in disabled state, in order to be able to configure some bits in + CRx registers */ + if (LL_USART_IsEnabled(USARTx) == 0U) + { + /* If USART Clock signal is disabled */ + if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE) + { + /* Deactivate Clock signal delivery : + * - Disable Clock Output: USART_CR2_CLKEN cleared + */ + LL_USART_DisableSCLKOutput(USARTx); + } + else + { + /* Ensure USART instance is USART capable */ + assert_param(IS_USART_INSTANCE(USARTx)); + + /* Check clock related parameters */ + assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity)); + assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase)); + assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse)); + + /*---------------------------- USART CR2 Configuration ----------------------- + * Configure USARTx CR2 (Clock signal related bits) with parameters: + * - Enable Clock Output: USART_CR2_CLKEN set + * - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value + * - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value + * - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value. + */ + MODIFY_REG(USARTx->CR2, + USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL, + USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity | + USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse); + } + } + /* Else (USART not in Disabled state => return ERROR */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Set each field of a @ref LL_USART_ClockInitTypeDef type structure to default value. + * @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct) +{ + /* Set LL_USART_ClockInitStruct fields with default values */ + USART_ClockInitStruct->ClockOutput = LL_USART_CLOCK_DISABLE; + USART_ClockInitStruct->ClockPolarity = LL_USART_POLARITY_LOW; /* Not relevant when ClockOutput = + LL_USART_CLOCK_DISABLE */ + USART_ClockInitStruct->ClockPhase = LL_USART_PHASE_1EDGE; /* Not relevant when ClockOutput = + LL_USART_CLOCK_DISABLE */ + USART_ClockInitStruct->LastBitClockPulse = LL_USART_LASTCLKPULSE_NO_OUTPUT; /* Not relevant when ClockOutput = + LL_USART_CLOCK_DISABLE */ +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* USART1 || USART2 || USART4 || USART5 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/fw/STM32L031G6UX_FLASH.ld b/fw/STM32L031G6UX_FLASH.ld new file mode 100644 index 0000000..1c2e4da --- /dev/null +++ b/fw/STM32L031G6UX_FLASH.ld @@ -0,0 +1,186 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** @brief : Linker script for STM32L031G6Ux Device from STM32L0 series +** 32Kbytes FLASH +** 8Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +**

© Copyright (c) 2021 STMicroelectronics. +** All rights reserved.

+** +** This software component is licensed by ST under BSD 3-Clause license, +** the "License"; You may not use this file except in compliance with the +** License. You may obtain a copy of the License at: +** opensource.org/licenses/BSD-3-Clause +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 0x200 ; /* required amount of heap */ +_Min_Stack_Size = 0x400 ; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/fw/iaq_wired_sensor Debug.launch b/fw/iaq_wired_sensor Debug.launch index e9df78e..420a890 100644 --- a/fw/iaq_wired_sensor Debug.launch +++ b/fw/iaq_wired_sensor Debug.launch @@ -5,6 +5,8 @@ + + @@ -14,7 +16,6 @@ - @@ -27,22 +28,28 @@ - + - + + - + + + + + + - + @@ -61,13 +68,13 @@ - + - + diff --git a/fw/iaq_wired_sensor.ioc b/fw/iaq_wired_sensor.ioc index 1e11fd8..77b23fd 100644 --- a/fw/iaq_wired_sensor.ioc +++ b/fw/iaq_wired_sensor.ioc @@ -4,77 +4,70 @@ GPIO.groupedBy=Group By Peripherals I2C1.IPParameters=Timing I2C1.Timing=0x40000A0B KeepUserPlacement=false -LPUART1.BaudRate=115200 -LPUART1.IPParameters=BaudRate,SwapParam,OneBitSampling,WordLength,Parity -LPUART1.OneBitSampling=UART_ONE_BIT_SAMPLE_ENABLE -LPUART1.Parity=UART_PARITY_EVEN -LPUART1.SwapParam=UART_ADVFEATURE_SWAP_ENABLE -LPUART1.WordLength=UART_WORDLENGTH_9B Mcu.Family=STM32L0 Mcu.IP0=I2C1 -Mcu.IP1=LPUART1 -Mcu.IP2=NVIC -Mcu.IP3=RCC -Mcu.IP4=SYS -Mcu.IP5=TIM21 +Mcu.IP1=NVIC +Mcu.IP2=RCC +Mcu.IP3=SYS +Mcu.IP4=TIM21 +Mcu.IP5=USART2 Mcu.IPNb=6 -Mcu.Name=STM32L011F(3-4)Ux -Mcu.Package=UFQFPN20 -Mcu.Pin0=PA0-CK_IN -Mcu.Pin1=PA1 -Mcu.Pin10=VP_TIM21_VS_ClockSourceINT -Mcu.Pin2=PA5 -Mcu.Pin3=PA6 -Mcu.Pin4=PA7 -Mcu.Pin5=PA9 -Mcu.Pin6=PA10 -Mcu.Pin7=PA13 -Mcu.Pin8=PA14 -Mcu.Pin9=VP_SYS_VS_Systick -Mcu.PinsNb=11 +Mcu.Name=STM32L031G(4-6)Ux +Mcu.Package=UFQFPN28 +Mcu.Pin0=PA1 +Mcu.Pin1=PA2 +Mcu.Pin10=VP_SYS_VS_Systick +Mcu.Pin11=VP_TIM21_VS_ClockSourceINT +Mcu.Pin2=PA3 +Mcu.Pin3=PA5 +Mcu.Pin4=PA6 +Mcu.Pin5=PA7 +Mcu.Pin6=PA9 +Mcu.Pin7=PA10 +Mcu.Pin8=PA13 +Mcu.Pin9=PA14 +Mcu.PinsNb=12 Mcu.ThirdPartyNb=0 Mcu.UserConstants= -Mcu.UserName=STM32L011F4Ux -MxCube.Version=6.2.1 -MxDb.Version=DB.6.0.21 +Mcu.UserName=STM32L031G6Ux +MxCube.Version=6.3.0 +MxDb.Version=DB.6.0.30 NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false -NVIC.LPUART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false -NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.SysTick_IRQn=true\:3\:0\:false\:false\:true\:false\:true NVIC.TIM21_IRQn=true\:0\:0\:false\:false\:true\:true\:true -PA0-CK_IN.GPIOParameters=GPIO_PuPd -PA0-CK_IN.GPIO_PuPd=GPIO_PULLUP -PA0-CK_IN.Mode=Asynchronous -PA0-CK_IN.Signal=LPUART1_RX -PA1.GPIOParameters=GPIO_PuPd -PA1.GPIO_PuPd=GPIO_PULLUP -PA1.Mode=Asynchronous -PA1.Signal=LPUART1_TX +NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true +PA1.Mode=Hardware Flow Control (RS485) +PA1.Signal=USART2_DE +PA10.GPIOParameters=GPIO_Pu +PA10.GPIO_Pu=GPIO_PULLUP PA10.Mode=I2C PA10.Signal=I2C1_SDA PA13.Mode=Serial_Wire PA13.Signal=SYS_SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_SWCLK -PA5.GPIOParameters=PinState,GPIO_Label +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA5.GPIOParameters=GPIO_Label PA5.GPIO_Label=LED_B PA5.Locked=true -PA5.PinState=GPIO_PIN_SET PA5.Signal=GPIO_Output -PA6.GPIOParameters=PinState,GPIO_Label +PA6.GPIOParameters=GPIO_Label PA6.GPIO_Label=LED_G PA6.Locked=true -PA6.PinState=GPIO_PIN_SET PA6.Signal=GPIO_Output -PA7.GPIOParameters=PinState,GPIO_Label +PA7.GPIOParameters=GPIO_Label PA7.GPIO_Label=LED_R PA7.Locked=true -PA7.PinState=GPIO_PIN_SET PA7.Signal=GPIO_Output -PA9.Locked=true +PA9.GPIOParameters=GPIO_Pu +PA9.GPIO_Pu=GPIO_PULLUP PA9.Mode=I2C PA9.Signal=I2C1_SCL PinOutPanel.RotationAngle=0 @@ -86,8 +79,8 @@ ProjectManager.CoupleFile=false ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true -ProjectManager.DeviceId=STM32L011F4Ux -ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.12.0 +ProjectManager.DeviceId=STM32L031G6Ux +ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.12.1 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 @@ -105,7 +98,7 @@ ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=STM32CubeIDE ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-LL-true,2-SystemClock_Config-RCC-false-LL-false,3-MX_I2C1_Init-I2C1-false-LL-true,4-MX_LPUART1_UART_Init-LPUART1-false-LL-true,5-MX_TIM21_Init-TIM21-false-LL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-LL-true,4-MX_USART2_UART_Init-USART2-false-LL-true,5-MX_TIM21_Init-TIM21-false-LL-true RCC.AHBFreq_Value=12000000 RCC.APB1Freq_Value=12000000 RCC.APB1TimFreq_Value=12000000 @@ -138,13 +131,20 @@ RCC.USART2Freq_Value=12000000 RCC.VCOOutputFreq_Value=48000000 RCC.WatchDogFreq_Value=37000 TIM21.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE -TIM21.ClockDivision=TIM_CLOCKDIVISION_DIV1 -TIM21.IPParameters=Prescaler,Period,AutoReloadPreload,ClockDivision +TIM21.IPParameters=Prescaler,Period,AutoReloadPreload TIM21.IPParametersWithoutCheck=Prescaler,Period TIM21.Period=tim21_period TIM21.Prescaler=tim21_prescaler +USART2.BaudRate=config_baudrates[sensor_config.baudrate_index] +USART2.IPParameters=VirtualMode-Asynchronous,VirtualMode-Hardware Flow Control (RS485),BaudRate,WordLength,Parity +USART2.IPParametersWithoutCheck=BaudRate +USART2.Parity=PARITY_EVEN +USART2.VirtualMode-Asynchronous=VM_ASYNC +USART2.VirtualMode-Hardware\ Flow\ Control\ (RS485)=VM_ASYNC +USART2.WordLength=WORDLENGTH_9B VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick VP_TIM21_VS_ClockSourceINT.Mode=Internal VP_TIM21_VS_ClockSourceINT.Signal=TIM21_VS_ClockSourceINT board=custom +isbadioc=false diff --git a/fw_old/.cproject b/fw_old/.cproject new file mode 100644 index 0000000..30a87ca --- /dev/null +++ b/fw_old/.cproject @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fw_old/.mxproject b/fw_old/.mxproject new file mode 100644 index 0000000..4d4db74 --- /dev/null +++ b/fw_old/.mxproject @@ -0,0 +1,24 @@ +[PreviousLibFiles] +LibFiles=Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_gpio.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_dma.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_bus.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_cortex.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_rcc.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_system.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_utils.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_exti.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_pwr.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_crs.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h;Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_tim.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/core_cm3.h; + +[PreviousUsedCubeIDEFiles] +SourceFiles=Core/Src/main.c;Core/Src/stm32l0xx_it.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Core/Src/system_stm32l0xx.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_gpio.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_i2c.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_dma.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_rcc.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_utils.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_exti.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_lpuart.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_pwr.c;Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_ll_tim.c;Core/Src/system_stm32l0xx.c;Drivers/CMSIS/Device/ST/STM32L0xx/Source/Templates/system_stm32l0xx.c;; +HeaderPath=Drivers/STM32L0xx_HAL_Driver/Inc;Drivers/CMSIS/Device/ST/STM32L0xx/Include;Drivers/CMSIS/Include;Core/Inc; +CDefines=USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1;STM32L011xx;USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:37000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1; + +[PreviousGenFiles] +AdvancedFolderStructure=true +HeaderFileListSize=3 +HeaderFiles#0=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Inc/stm32l0xx_it.h +HeaderFiles#1=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Inc/stm32_assert.h +HeaderFiles#2=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Inc/main.h +HeaderFolderListSize=1 +HeaderPath#0=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Inc +HeaderFiles=; +SourceFileListSize=2 +SourceFiles#0=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Src/stm32l0xx_it.c +SourceFiles#1=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Src/main.c +SourceFolderListSize=1 +SourcePath#0=/home/mrs/Personal/HDIoT/Smart_Household/iaq_wired_sensor/fw/Core/Src +SourceFiles=; + diff --git a/fw_old/.project b/fw_old/.project new file mode 100644 index 0000000..6232ccb --- /dev/null +++ b/fw_old/.project @@ -0,0 +1,33 @@ + + + iaq_wired_sensor + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.st.stm32cube.ide.mcu.MCUProjectNature + com.st.stm32cube.ide.mcu.MCUCubeProjectNature + org.eclipse.cdt.core.cnature + com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAev2ProjectNature + com.st.stm32cube.ide.mcu.MCUAdvancedStructureProjectNature + com.st.stm32cube.ide.mcu.MCUEndUserDisabledTrustZoneProjectNature + com.st.stm32cube.ide.mcu.MCUSingleCpuProjectNature + com.st.stm32cube.ide.mcu.MCURootProjectNature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/fw_old/.settings/org.eclipse.cdt.codan.core.prefs b/fw_old/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..19f7155 --- /dev/null +++ b/fw_old/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,72 @@ +com.st.stm32cube.ide.mcu.ide.oss.source.checker.libnano.problem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Float formatting support\\")"} +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.localvarreturn=-Warning +org.eclipse.cdt.codan.checkers.localvarreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Returning the address of a local variable\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()} +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Lack of copyright information\\")",regex\=>".*Copyright.*"} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Direct float comparison\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Goto statement used\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Avoid magic numbers\\")",checkArray\=>true,checkOperatorParen\=>true,exceptions\=>(1,0,-1,2,1.0,0.0,-1.0)} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing cases in switch\\")"} +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing default in switch\\")",defaultWithAllEnums\=>false} +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing reference return value in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing self check in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Multiple variable declaration\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Miss copy constructor or assignment operator\\")",onlynew\=>false} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Static variable in header file\\")"} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Using directive in header\\")"} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem=-Error +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Virtual method call in constructor/destructor\\")"} diff --git a/fw_old/.settings/org.eclipse.cdt.core.prefs b/fw_old/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..c8ec5df --- /dev/null +++ b/fw_old/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +doxygen/doxygen_new_line_after_brief=true +doxygen/doxygen_use_brief_tag=false +doxygen/doxygen_use_javadoc_tags=true +doxygen/doxygen_use_pre_tag=false +doxygen/doxygen_use_structural_commands=false +eclipse.preferences.version=1 diff --git a/fw_old/.settings/stm32cubeide.project.prefs b/fw_old/.settings/stm32cubeide.project.prefs new file mode 100644 index 0000000..ae186d6 --- /dev/null +++ b/fw_old/.settings/stm32cubeide.project.prefs @@ -0,0 +1,3 @@ +8DF89ED150041C4CBC7CB9A9CAA90856=295E78E9D51884086204F31037537306 +DC22A860405A8BF2F2C095E5B6529F12=295E78E9D51884086204F31037537306 +eclipse.preferences.version=1 diff --git a/fw_old/Core/Inc/config.h b/fw_old/Core/Inc/config.h new file mode 100644 index 0000000..c512299 --- /dev/null +++ b/fw_old/Core/Inc/config.h @@ -0,0 +1,145 @@ +/* + * config.h + * + * Created on: Sep 5, 2021 + * Author: david + */ + +#ifndef INC_CONFIG_H_ +#define INC_CONFIG_H_ + +/* TODO: add comments to everything */ + +/* EXAMPLE of USAGE */ +/* +config_t new_config; +new_config.led_co2_alert_limit1 = 1000; +new_config.led_co2_alert_limit2 = 2000; +new_config.led_on = 1; +new_config.modbus_addr = 0x11; +config_write(&new_config); + +config_t config; +config_read(&config); +*/ + +#include "stdint.h" +#include "stm32l0xx.h" +/* DESCRIPTION OF THE DATA STRUCTURE */ +/* + * Data are divided into two groups: + * A) DEVICE DESCRIPTION + * Can not be changed by the user. + * These data can be only read. + * These data are: + * * VENDOR NAME + * * PRODUCT CODE + * * PRODUCT NAME + * * REVISION + * * SERIAL NUMBER + * B) DEVICE CONFIGURATION + * Can be changed by the user. + * These data are: + * * MODBUS ADDRESS - Modbus Address of the device. Default is 254 + * * LED ON - Whether the CO2 Level Indication LED should be on or off + * * LED CO2 ALERT LIMIT 1 - CO2 Level when the LED color changes Green<->Yellow + * * LED CO2 ALERT LIMIT 2 - CO2 Level when the LED color changes Yellow<->Red + * + * Device description data can be accessed using direct readout from the memory + * Device configuration data can be accessed using config_t struct. + */ +#define CONFIG_DEFAULT_LED_ON 1 +#define CONFIG_DEFAULT_LED_BRIGHTNESS 100 /* TODO: set according to the timers when this will be implemented */ +#define CONFIG_DEFAULT_LED_ALERT1_LIMIT 1500 +#define CONFIG_DEFAULT_LED_ALERT2_LIMIT 3000 +#define CONFIG_DEFAULT_LED_SMOOTH 0 +#define CONFIG_DEFAULT_SCD4x_T_OFFSET 0 +#define CONFIG_DEFAULT_BAUDRATE_INDEX 0 + +#define CONFIG_MODBUS_ADDR_LENGTH 2 +#define CONFIG_BAUDRATE_INDEX_LENGTH 2 +#define CONFIG_LED_ON_LENGTH 2 +#define CONFIG_LED_BRIGHTNESS_LENGTH 2 +#define CONFIG_LED_SMOOTH_LENGTH 2 +#define CONFIG_LED_ALERT1_LENGTH 2 +#define CONFIG_LED_ALERT2_LENGTH 2 +#define CONFIG_LED_ALERT2_LENGTH 2 +#define CONFIG_SCD4x_T_OFFSET_LENGTH 2 +#define VENDOR_NAME_LENGTH 64 +#define PRODUCT_CODE_LENGTH 64 +#define PRODUCT_NAME_LENGTH 64 +#define REVISION_LENGTH 16 +#define SERIAL_NUMBER_LENGTH 64 + +#define EEPROM_EMPTY_BYTE 0x00 + +#define EEPROM_ADDR_START ((uint32_t)0x08080000) +#define EEPROM_ADDR_END ((uint32_t)0x080801FF) + +#define CONFIG_EEPROM_ADDR_MODBUS_ADDR EEPROM_ADDR_START +#define CONFIG_EEPROM_ADDR_BAUDRATE_INDEX (CONFIG_EEPROM_ADDR_MODBUS_ADDR + CONFIG_MODBUS_ADDR_LENGTH) +#define CONFIG_EEPROM_ADDR_LED_ON (CONFIG_EEPROM_ADDR_BAUDRATE_INDEX + CONFIG_BAUDRATE_INDEX_LENGTH) +#define CONFIG_EEPROM_ADDR_LED_BRIGHTNESS (CONFIG_EEPROM_ADDR_LED_ON + CONFIG_LED_ON_LENGTH) +#define CONFIG_EEPROM_ADDR_LED_SMOOTH (CONFIG_EEPROM_ADDR_LED_BRIGHTNESS + CONFIG_LED_BRIGHTNESS_LENGTH) +#define CONFIG_EEPROM_ADDR_LED_ALERT1 (CONFIG_EEPROM_ADDR_LED_SMOOTH + CONFIG_LED_SMOOTH_LENGTH) +#define CONFIG_EEPROM_ADDR_LED_ALERT2 (CONFIG_EEPROM_ADDR_LED_ALERT1 + CONFIG_LED_ALERT1_LENGTH) +#define CONFIG_EEPROM_ADDR_SCD4x_T_OFFSET (CONFIG_EEPROM_ADDR_LED_ALERT2 + CONFIG_LED_ALERT2_LENGTH) + +#define CONFIG_EEPROM_ADDR_VENDOR_NAME (CONFIG_EEPROM_ADDR_SCD4x_T_OFFSET + CONFIG_SCD4x_T_OFFSET_LENGTH) +#define CONFIG_EEPROM_ADDR_PRODUCT_CODE (CONFIG_EEPROM_ADDR_VENDOR_NAME + VENDOR_NAME_LENGTH) +#define CONFIG_EEPROM_ADDR_PRODUCT_NAME (CONFIG_EEPROM_ADDR_PRODUCT_CODE + PRODUCT_CODE_LENGTH) +#define CONFIG_EEPROM_ADDR_REVISION (CONFIG_EEPROM_ADDR_PRODUCT_NAME + PRODUCT_NAME_LENGTH) +#define CONFIG_EEPROM_ADDR_SERIAL_NUMBER (CONFIG_EEPROM_ADDR_REVISION + REVISION_LENGTH) + +#define FLASH_PEKEY1 ((uint32_t)0x89ABCDEF) +#define FLASH_PEKEY2 ((uint32_t)0x02030405) + +#define CONFIG_OK 0 +#define CONFIG_ERROR -1 + +#define EEPROM_OK 0 +#define EEPROM_ERROR -1 +#define EEPROM_UNLOCK_ERROR -2 +#define EEPROM_LOCK_ERROR -3 +#define EEPROM_WRITE_ERROR -4 +#define EEPROM_ADDR_ERROR -5 + +#define SYSTICK_FREQ_HZ 12000000 +#define EEPROM_TIMEOUT_MAX_MS_INV 200 + +/* + * Variables + */ + +extern const uint32_t config_baudrates[]; +extern const uint8_t config_baudrates_length; + +/* + * Type definitions + */ + +typedef struct +{ + /* LED CONFIG */ + uint8_t led_on; + uint16_t led_brightness; + uint8_t led_smooth; + uint16_t led_co2_alert_limit1; + uint16_t led_co2_alert_limit2; + + /* SCD4x Temperature sensor offset */ + int16_t scd4x_t_offset; + + /* MODBUS CONFIG */ + uint16_t modbus_addr; + uint32_t baudrate_index; +} config_t; + + +/* const uint32_t baudrates [] = {19200, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800, 115200}; */ + +int8_t config_read(config_t *config); +int8_t config_write(config_t *config); + +#endif /* INC_CONFIG_H_ */ + diff --git a/fw_old/Core/Inc/crc8.h b/fw_old/Core/Inc/crc8.h new file mode 100644 index 0000000..e799f7e --- /dev/null +++ b/fw_old/Core/Inc/crc8.h @@ -0,0 +1,22 @@ +/* + * crc.h + * + * Created on: Jun 9, 2021 + * Author: user + */ + +#ifndef INC_CRC8_H_ +#define INC_CRC8_H_ + +#include "stdint.h" + +/* + * Definitions & macros + */ + +#define CRC8_POLYNOMIAL 0x31 +#define CRC8_INIT 0xFF + +uint8_t crc8_calculate(const uint8_t *data, uint16_t count); + +#endif /* INC_CRC8_H_ */ diff --git a/fw_old/Core/Inc/i2c.h b/fw_old/Core/Inc/i2c.h new file mode 100644 index 0000000..f346e68 --- /dev/null +++ b/fw_old/Core/Inc/i2c.h @@ -0,0 +1,46 @@ +/* + * i2c.h + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#ifndef INC_I2C_H_ +#define INC_I2C_H_ + +#include "stdint.h" +#include "stm32l0xx_ll_i2c.h" + +/* + * Defines & macros + */ + +#define NULL 0 + +/* + * Return values for I2C functions + */ + +#define I2C_OK 0 +#define I2C_ERROR -1 // generic error +#define I2C_ERROR_NACK -2 // NACK was received during transfer +#define I2C_ERROR_TX_INCOMPLETE -3 // number of TXed bytes != buffer length +#define I2C_ERROR_RX_INCOMPLETE -4 // number of RXed bytes != buffer length + +/* + * Type definitions + */ + +typedef struct { + I2C_TypeDef *i2c; +} i2c_context_t; + +/* + * Function declarations + */ + +int i2c_init(i2c_context_t *context); +int i2c_transmit(uint8_t address, uint8_t *buffer, int len); +int i2c_receive(uint8_t address, uint8_t *buffer, int len); + +#endif /* INC_I2C_H_ */ diff --git a/fw_old/Core/Inc/main.h b/fw_old/Core/Inc/main.h new file mode 100644 index 0000000..a144a49 --- /dev/null +++ b/fw_old/Core/Inc/main.h @@ -0,0 +1,120 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l0xx_ll_i2c.h" +#include "stm32l0xx_ll_lpuart.h" +#include "stm32l0xx_ll_rcc.h" +#include "stm32l0xx_ll_crs.h" +#include "stm32l0xx_ll_bus.h" +#include "stm32l0xx_ll_system.h" +#include "stm32l0xx_ll_exti.h" +#include "stm32l0xx_ll_cortex.h" +#include "stm32l0xx_ll_utils.h" +#include "stm32l0xx_ll_pwr.h" +#include "stm32l0xx_ll_dma.h" +#include "stm32l0xx_ll_tim.h" +#include "stm32l0xx_ll_gpio.h" + +#if defined(USE_FULL_ASSERT) +#include "stm32_assert.h" +#endif /* USE_FULL_ASSERT */ + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "i2c.h" +#include "scd4x.h" +#include "sht4x.h" +#include "sps30.h" +#include "modbus.h" +#include "config.h" +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ +int8_t uart_disable_interrupts(void); +int8_t uart_enable_interrupts(void); + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define LED_B_Pin LL_GPIO_PIN_5 +#define LED_B_GPIO_Port GPIOA +#define LED_G_Pin LL_GPIO_PIN_6 +#define LED_G_GPIO_Port GPIOA +#define LED_R_Pin LL_GPIO_PIN_7 +#define LED_R_GPIO_Port GPIOA +#ifndef NVIC_PRIORITYGROUP_0 +#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority, + 4 bits for subpriority */ +#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bit for pre-emption priority, + 3 bits for subpriority */ +#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority, + 2 bits for subpriority */ +#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority, + 1 bit for subpriority */ +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority, + 0 bit for subpriority */ +#endif +/* USER CODE BEGIN Private defines */ +#define MEASUREMENT_PERIOD_MS 600000 + +extern uint16_t lpuart1_rx_message_index; +extern uint16_t lpuart1_rx_message_len; +extern uint8_t lpuart1_rx_done; +extern uint8_t lpuart1_rx_message_too_long; + +extern uint8_t tim21_elapsed_period; + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw_old/Core/Inc/modbus.h b/fw_old/Core/Inc/modbus.h new file mode 100644 index 0000000..a215328 --- /dev/null +++ b/fw_old/Core/Inc/modbus.h @@ -0,0 +1,181 @@ +/* + * modbus.h + * + * Created on: Jul 18, 2021 + * Author: user + * + * Modbus slave RTU library (does NOT support ASCII and TCP) + * + * Useful links: + * https://www.picotech.com/library/oscilloscopes/modbus-serial-protocol-decoding + * https://ipc2u.com/articles/knowledge-base/modbus-rtu-made-simple-with-detailed-descriptions-and-examples/ + * https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf + * https://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf + * + * Note that byte order is big endian. + * + * USAGE: + * + * 1) Implement functions modbus_callback_function() and modbus_uart_transmit_function() + * - modbus_uart_transmit_function() sends data via UART + * - modbus_callback_function() does the real work: read sensors, set outputs... + * note that when filling buffers (e.g. input_registers[]) user must + * ensure that all data is big-endian + * These functions are implementation-specific. + * 2) Set device address (variable modbus_device_address); you can do this either + * - setting modbus_device_address directly (modbus.h needs to be included, duh) + * - using modbus_set_device_address(uint8_t address) function + * Or you can leave address as-is (MODBUS_DEFAULT_SLAVE_ADDRESS) and set it via + * Modbus during runtime + * 3) Call modbus_process_msg() after message reception; you need to observe Modbus RTU timing: + * - pauses between chars in frame are less or equal to 1.5 char + * - pauses between frames are at least 3.5 chars (of silence) + * For more information see section 2.5.1.1 (MODBUS Message RTU Framing) + * in "MODBUS over Serial Line: Specification and Implementation Guide" + * + */ + +#ifndef SRC_MODBUS_H_ +#define SRC_MODBUS_H_ + +#include "stdint.h" + +/* + * Defines & macros + */ + +#define MODBUS_BROADCAST_ADDR 0 +#define MODBUS_DEFAULT_SLAVE_ADDRESS 254 /* 255 may be used for bridge device */ +/* minimal frame length is 4 bytes: 1 B slave address, 1 B function code, 2 B CRC */ +#define MODBUS_MINIMAL_FRAME_LEN 4 +#define MODBUS_MAX_RTU_FRAME_SIZE 256 +#define MODBUS_BUFFER_SIZE MODBUS_MAX_RTU_FRAME_SIZE /* alias */ +#define MODBUS_ERROR_FLAG 0x80 +#define MODBUS_MAX_REGISTERS 125 + +/* + * Return values + */ + +#define MODBUS_OK 0 +#define MODBUS_ERROR -1 // generic error +#define MODBUS_ERROR_CRC -2 // checksum failed +#define MODBUS_ERROR_FRAME_INVALID -3 // invalid frame format / length +#define MODBUS_ERROR_OUT_OF_BOUNDS -4 // requested register is out of bounds +#define MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED -5 // function not implemented in callback +#define MODBUS_ERROR_REGISTER_NOT_IMPLEMENTED -6 // register not implemented in callback + +/* + * Data types + */ + +/* Public functions codes (Modbus Application protocol specification, section 5.1) */ +typedef enum { + /* single bit access functions */ + MODBUS_READ_COILS = 1, + MODBUS_READ_DO = 1, // alias + MODBUS_READ_DISCRETE_INPUTS = 2, + MODBUS_READ_DI = 2, // alias + MODBUS_WRITE_SINGLE_COIL = 5, + MODBUS_WRITE_SINGLE_DO = 5, // alias + MODBUS_WRITE_MULTIPLE_COILS = 15, + MODBUS_WRITE_MULTIPLE_DO = 15, // alias + /* 16-bit access functions */ + MODBUS_READ_HOLDING_REGISTERS = 3, + MODBUS_READ_AO = 3, // alias + MODBUS_READ_INPUT_REGISTERS = 4, + MODBUS_READ_AI = 4, // alias + MODBUS_WRITE_SINGLE_REGISTER = 6, + MODBUS_WRITE_SINGLE_AO = 6, // alias + MODBUS_WRITE_MULTIPLE_REGISTERS = 16, + MODBUS_WRITE_MULTIPLE_AO = 16, // alias + MODBUS_MASK_WRITE_REGISTER = 22, + MODBUS_READ_WRITE_MULTIPLE_REGISTERS = 23, + MODBUS_READ_FIFO_QUEUE = 24, + /* file record access */ + MODBUS_READ_FILE_RECORD = 20, + MODBUS_WRITE_FILE_RECORD = 21, + /* diagnostics */ + MODBUS_READ_EXCEPTION_STATUS = 7, + MODBUS_DIAGNOSTIC = 8, /* sub codes: 00-18,20 */ + MODBUS_GET_COM_EVENT_COUNTER = 11, + MODBUS_GET_COM_EVENT_LOG = 12, + MODBUS_REPORT_SLAVE_ID = 17, + MODBUS_READ_DEVICE_IDENTIFICATION = 43, /* sub codes: 14 */ +} modbus_function_code_t; + +typedef enum { + MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 1, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2, + MODBUS_EXCEPTION_ILLEGAL_REGISTER_QUANTITY = 2, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3, + MODBUS_EXCEPTION_SLAVE_DEVICE_FAILURE = 4, + MODBUS_EXCEPTION_ACKNOWLEDGE = 5, + MODBUS_EXCEPTION_SLAVE_DEVICE_BUSY = 6, + MODBUS_EXCEPTION_MEMORY_PARITY_ERROR = 8, + MODBUS_EXCEPTION_GATEWAY_PATH_UNAVAILABLE = 10, + MODBUS_EXCEPTION_GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 11, +} modbus_exception_code_t; + +typedef struct { + uint8_t exception_code; +} exception_t; + +typedef struct { + modbus_function_code_t function_code : 8; + uint16_t register_address; // e.g. first register of A0: 0 + uint16_t register_number; // e.g. first register of A0: 40001 + uint8_t register_count; // number of registers to be read/written + + exception_t exception; + + union { + uint8_t buffer8b[MODBUS_MAX_RTU_FRAME_SIZE]; + uint16_t buffer16b[MODBUS_MAX_RTU_FRAME_SIZE/2]; + uint16_t input_registers[MODBUS_MAX_REGISTERS]; + uint16_t holding_registers[MODBUS_MAX_REGISTERS]; + int16_t input_registers_signed[MODBUS_MAX_REGISTERS]; + int16_t holding_registers_signed[MODBUS_MAX_REGISTERS]; + }; +} modbus_transaction_t; + +typedef enum { + MODBUS_DO_START_NUMBER = 1, // Discrete output coils + MODBUS_DO_END_NUMBER = 9999, + MODBUS_DI_START_NUMBER = 10001, // Discrete input contacts + MODBUS_DI_END_NUMBER = 19999, + MODBUS_AI_START_NUMBER = 30001, // Analog input registers + MODBUS_AI_END_NUMBER = 39999, + MODBUS_AO_START_NUMBER = 40001, // Analog output (holding registers) + MODBUS_AO_END_NUMBER = 49999 +} modbus_register_number_t; + + +/* + * Global variables + */ + +/* device address: declared in modbus.c */ +extern uint8_t modbus_slave_address; + +/* shared modbus buffer; defined in modbus.c; may be used elsewhere in code */ +extern uint8_t modbus_buffer[]; + +/* + * Function prototypes + */ + +/* process message: should be called in when modbus message was received (e.g. in main.c) + * modbus_process_msg() may call following functions: + * - modbus_callback_function() if data readout is requested + * - modbus_uart_transmit_function() if response is required + * Both functions have to be implemented by user. + */ +int8_t modbus_slave_process_msg(const uint8_t *buffer, int len); +int8_t modbus_slave_set_address(uint8_t address); +/* modbus callback function type - should be implemented by user (e.g. in main.c) */ +int8_t modbus_slave_callback(modbus_transaction_t *transaction); +/* UART transmit function type - should be implemented by user (e.g. in main.c) */ +int8_t modbus_transmit_function(uint8_t *buffer, uint16_t data_len); + +#endif /* SRC_MODBUS_H_ */ diff --git a/fw_old/Core/Inc/scd4x.h b/fw_old/Core/Inc/scd4x.h new file mode 100644 index 0000000..921f9ee --- /dev/null +++ b/fw_old/Core/Inc/scd4x.h @@ -0,0 +1,57 @@ +/* + * sht4x.h + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#ifndef INC_SCD4X_H_ +#define INC_SCD4X_H_ + +#include "stdint.h" +#include "stm32l0xx_ll_i2c.h" +#include "stm32l0xx_ll_utils.h" +#include "i2c.h" +#include "crc8.h" + +/* + * Defines & macros + */ + +#define SCD4X_I2C_ADDRESS 0x62 + +/* + * Return values + */ + +#define SCD4X_OK 0 +#define SCD4X_ERROR -1 // generic error +#define SCD4X_CRC8_ERROR -2 // checksum failed + +/* + * Data types + */ + +typedef enum { + SCD4X_START_PERIODIC_MEASUREMENT = 0x21B1, + SCD4X_READ_MEASUREMENT = 0xEC05, + SCD4X_STOP_PERIODIC_MEASUREMENT = 0x3F86, + SCD4X_GET_DATA_READY_STATUS = 0xe4b8, + SCD4X_PERFORM_FACTORY_RESET = 0x3632 +} scd4x_cmd_t; + +/* + * Function prototypes + */ + +int8_t scd4x_send_cmd(scd4x_cmd_t cmd); +int8_t scd4x_read_data(uint8_t *buffer, int len); + +int8_t scd4x_start_periodic_measurement( void ); +int8_t scd4x_stop_periodic_measurement( void ); + +int8_t scd4x_perform_factory_reset( void ); + +int8_t scd4x_read_measurement(uint16_t * co2, int16_t *temperature, uint16_t *relative_humidity); + +#endif /* INC_SCD4X_H_ */ diff --git a/fw_old/Core/Inc/sht4x.h b/fw_old/Core/Inc/sht4x.h new file mode 100644 index 0000000..36c4351 --- /dev/null +++ b/fw_old/Core/Inc/sht4x.h @@ -0,0 +1,57 @@ +/* + * sht4x.h + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#ifndef INC_SHT4X_H_ +#define INC_SHT4X_H_ + +#include "stdint.h" +#include "stm32l0xx_ll_i2c.h" +#include "stm32l0xx_ll_utils.h" +#include "i2c.h" +#include "crc8.h" + +/* + * Defines & macros + */ + +#define SHT4X_I2C_ADDRESS 0x44 + +/* + * Return values + */ + +#define SHT4X_OK 0 +#define SHT4X_ERROR -1 // generic error +#define SHT4X_CRC8_ERROR -2 // checksum failed + +/* + * Data types + */ + +typedef enum { + SHT4X_START_MEAS_HIGH_PRECISION = 0xFD, + SHT4X_START_MEAS_MEDIUM_PRECISION = 0xF6, + SHT4X_START_MEAS_LOW_PRECISION = 0xE0, + SHT4X_READ_SERIAL = 0x89, + SHT4X_SOFT_RESET = 0x94, + SHT4X_HEATER_200_mW_1_s = 0x39, + SHT4X_HEATER_200_mW_01_s = 0x32, + SHT4X_HEATER_110_mW_1_s = 0x2F, + SHT4X_HEATER_110_mW_01_s = 0x24, + SHT4X_HEATER_20_mW_1_s = 0x1E, + SHT4X_HEATER_20_mW_01_s = 0x15 +} sht4x_cmd_t; + +/* + * Function prototypes + */ + +int8_t sht4x_send_cmd(sht4x_cmd_t cmd); +int8_t sht4x_read_data(uint8_t *buffer, int len); +int8_t sht4x_measure(int16_t *temperature, uint16_t *relative_humidity); + +#endif /* INC_SHT4X_H_ */ diff --git a/fw_old/Core/Inc/sps30.h b/fw_old/Core/Inc/sps30.h new file mode 100644 index 0000000..9ca3c45 --- /dev/null +++ b/fw_old/Core/Inc/sps30.h @@ -0,0 +1,78 @@ +/* + * sps30.h + * + * Created on: Jul 18, 2021 + * Author: mrs + */ + +#ifndef INC_SPS30_H_ +#define INC_SPS30_H_ + +#include "stdint.h" +#include "stm32l0xx_ll_i2c.h" +#include "stm32l0xx_ll_utils.h" +#include "i2c.h" +#include "crc8.h" + +/* + * Defines & macros + */ + +#define SPS30_I2C_ADDRESS 0x69 + +/* + * Return values + */ + +#define SPS30_OK 0 +#define SPS30_ERROR -1 // generic error +#define SPS30_CRC8_ERROR -2 // checksum failed + +/* + * Data types + */ + +typedef enum { + SPS30_START_MEASUREMENT = 0x0010, + SPS30_STOP_MEASUREMENT = 0x0104, + SPS30_READ_DATA_READY_FLAG = 0x0202, + SPS30_READ_MEASURED_VALUES = 0x0300, + SPS30_SLEEP = 0x1001, + SPS30_WAKE_UP = 0x1103, + SPS30_START_FAN_CLEANING = 0x5607, + SPS30_READ_AUTO_CLEANING_INTERVAL = 0x8004, + SPS30_WRITE_AUTO_CLEANING_INTERVAL = 0x8004, + SPS30_READ_PRODUCT_TYPE = 0xD002, + SPS30_READ_SERIAL_NUMBER = 0xD033, + SPS30_READ_VERSION = 0xD100, + SPS30_READ_DEVICE_STATUS_REGISTER = 0xD206, + SPS30_CLEAR_DEVICE_STATUS_REGISTER = 0xD210, + SPS30_RESET = 0xD304 + +} sps30_cmd_t; + +typedef enum { + SPS30_FLOAT_FORMAT = 0x03, + SPS30_UINT16_FORMAT = 0x05 +} sps30_data_format; + +int8_t sps30_send_cmd(sps30_cmd_t cmd); + +int8_t sps30_start_measurement( void ); +int8_t sps30_stop_measurement( void ); +int8_t sps30_read_measured_values(uint16_t *measured_values, uint8_t measured_values_len); + +int8_t sps30_sleep( void ); +int8_t sps30_wake_up( void ); + +int8_t sps30_start_fan_cleaning( void ); + +int8_t sps30_reset( void ); + +int8_t sps30_read_status_register ( void ); + +int8_t sps30_read_firmware_version ( uint8_t * fw_ver_hi, uint8_t * fw_ver_lo ); + +uint8_t calculate_crc(uint8_t data[2]); + +#endif /* INC_SPS30_H_ */ diff --git a/fw_old/Core/Inc/stm32_assert.h b/fw_old/Core/Inc/stm32_assert.h new file mode 100644 index 0000000..ca09699 --- /dev/null +++ b/fw_old/Core/Inc/stm32_assert.h @@ -0,0 +1,53 @@ +/** + ****************************************************************************** + * @file stm32_assert.h + * @brief STM32 assert file. + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_ASSERT_H +#define __STM32_ASSERT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32_ASSERT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw_old/Core/Inc/stm32l0xx_it.h b/fw_old/Core/Inc/stm32l0xx_it.h new file mode 100644 index 0000000..e4fecd6 --- /dev/null +++ b/fw_old/Core/Inc/stm32l0xx_it.h @@ -0,0 +1,65 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32l0xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L0xx_IT_H +#define __STM32L0xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void SVC_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void TIM21_IRQHandler(void); +void LPUART1_IRQHandler(void); +/* USER CODE BEGIN EFP */ +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L0xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw_old/Core/Src/config.c b/fw_old/Core/Src/config.c new file mode 100644 index 0000000..08f6112 --- /dev/null +++ b/fw_old/Core/Src/config.c @@ -0,0 +1,243 @@ +/* + * config.c + * + * Created on: Sep 5, 2021 + * Author: david + */ + +#include "config.h" + +/* + * Variables + */ +/* Baudrates - STM32L0xx can do baudrates from 1200 to 115200 + * - default value has index 0 */ +const uint32_t config_baudrates[] = { + 19200, // 0 + 4800, // 1 + 9600, // 2 + 14400, // 3 + 19200, // 4 + 28800, // 5 + 38400, // 6 + 57600, // 7 + 76800, // 8 + 115200 // 9 +}; +const uint8_t config_baudrates_length = 10; + +/* Function to lock the EEPROM */ +static int8_t eeprom_lock(void); +/* Function to unlock the EEPROM */ +static int8_t eeprom_unlock(void); +/* Function to write one byte to the EEPROM */ +/* IMPORTANT: EEPROM must be unlocked first */ +static int8_t eeprom_program_byte(uint32_t addr, uint8_t ee_data); +/* Function to write two bytes to the EEPROM */ +/* IMPORTANT: EEPROM must be unlocked first */ +static int8_t eeprom_program_halfword(uint32_t addr, uint16_t ee_data); +/* Function to write four bytes to the EEPROM */ +/* IMPORTANT: EEPROM must be unlocked first */ +static int8_t eeprom_program_word(uint32_t addr, uint32_t ee_data); + +int8_t config_read(config_t *config) +{ + config->modbus_addr = *(uint16_t *) (CONFIG_EEPROM_ADDR_MODBUS_ADDR); + config->baudrate_index = *(uint16_t *) (CONFIG_EEPROM_ADDR_BAUDRATE_INDEX); + config->led_on = *(uint16_t *) (CONFIG_EEPROM_ADDR_LED_ON); + config->led_brightness = *(uint16_t *) (CONFIG_EEPROM_ADDR_LED_BRIGHTNESS); + config->led_smooth = *(uint16_t *) (CONFIG_EEPROM_ADDR_LED_SMOOTH); + config->led_co2_alert_limit1 = *(uint16_t *) (CONFIG_EEPROM_ADDR_LED_ALERT1); + config->led_co2_alert_limit2 = *(uint16_t *) (CONFIG_EEPROM_ADDR_LED_ALERT2); + config->scd4x_t_offset = *(int16_t *) (CONFIG_EEPROM_ADDR_SCD4x_T_OFFSET); + + /* Check if the EEPROM is initialized - do not check: + * LED ON + * LED SMOOTH + * SCD4x T OFFSET + * BAUDRATE INDEX + * those can be 0 */ + if ((config->modbus_addr == EEPROM_EMPTY_BYTE) || + (config->led_co2_alert_limit1 == EEPROM_EMPTY_BYTE) || + (config->led_co2_alert_limit2 == EEPROM_EMPTY_BYTE) || + (config->led_brightness == EEPROM_EMPTY_BYTE)) + { + return CONFIG_ERROR; + } + return CONFIG_OK; +} + +int8_t config_write(config_t *config) +{ + /* Unlock the EEPROM */ + if (eeprom_unlock() != EEPROM_OK) + { + return EEPROM_UNLOCK_ERROR; + } + /* Reset the ERASE and DATA bits in the FLASH_PECR register to disable any residual erase */ + FLASH->PECR = FLASH->PECR & ~(FLASH_PECR_ERASE | FLASH_PECR_DATA); + + /* Write MODBUS ADDRESS */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_MODBUS_ADDR, config->modbus_addr) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + /* Write BAUDRATE */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_BAUDRATE_INDEX, config->baudrate_index) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED ON */ + if (eeprom_program_byte(CONFIG_EEPROM_ADDR_LED_ON, config->led_on) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED BRIGHTNESS */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_LED_BRIGHTNESS, config->led_brightness) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED SMOOTH */ + if (eeprom_program_byte(CONFIG_EEPROM_ADDR_LED_SMOOTH, config->led_smooth) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED CO2 ALERT LIMIT 1 */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_LED_ALERT1, config->led_co2_alert_limit1) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED CO2 ALERT LIMIT 2 */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_LED_ALERT2, config->led_co2_alert_limit2) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Write LED SCD4x TEMPERATURE OFFSET */ + if (eeprom_program_halfword(CONFIG_EEPROM_ADDR_SCD4x_T_OFFSET, config->scd4x_t_offset) != EEPROM_OK) + { + return EEPROM_WRITE_ERROR; + } + + /* Lock EEPROM*/ + if (eeprom_lock() != EEPROM_OK) + { + return EEPROM_LOCK_ERROR; + } + return CONFIG_OK; +} + +static int8_t eeprom_lock(void) +{ + uint32_t tick_start = SysTick->VAL; + while ((FLASH->SR & FLASH_SR_BSY) != 0) /* Wait for FLASH to be free */ + { + /* Timeout test */ + /* The maximum writing time is 3.94ms (half-word) */ + uint32_t tick_last = SysTick->VAL; + uint32_t tick_diff; + if (tick_start <= tick_last) + { + tick_diff = tick_last - tick_start; + } else + { + tick_diff = (0xFFFFFFFF - tick_last) + tick_start; + } + + /* If the time difference is more than 5ms */ + if (tick_diff >= (uint32_t)((uint32_t)SYSTICK_FREQ_HZ*(uint32_t)EEPROM_TIMEOUT_MAX_MS_INV)) + { + return EEPROM_LOCK_ERROR; + } + } + + FLASH->PECR = FLASH->PECR & ~(FLASH_PECR_ERRIE | FLASH_PECR_EOPIE); /* disable flash interrupts */ + FLASH->PECR = FLASH->PECR | FLASH_PECR_PELOCK; /* Lock memory with PELOCK */ + + return EEPROM_OK; +} + +static int8_t eeprom_unlock(void) +{ + uint32_t tick_start = SysTick->VAL; + while ((FLASH->SR & FLASH_SR_BSY) != 0) /* Wait for FLASH to be free */ + { + /* Timeout test */ + /* The maximum writing time is 3.94ms (half-word) */ + uint32_t tick_last = SysTick->VAL; + uint32_t tick_diff; + if (tick_start <= tick_last) + { + tick_diff = tick_last - tick_start; + } else + { + tick_diff = (0xFFFFFFFF - tick_last) + tick_start; + } + + /* If the time difference is more than 5ms */ + if (tick_diff >= (uint32_t)((uint32_t)SYSTICK_FREQ_HZ*(uint32_t)EEPROM_TIMEOUT_MAX_MS_INV)) + { + return EEPROM_UNLOCK_ERROR; + } + } + if ((FLASH->PECR & FLASH_PECR_PELOCK) != 0) /* If PELOCK is locked */ + { + /* Unlock PELOCK */ + FLASH->PEKEYR = FLASH_PEKEY1; /* PEKEY1 */ + FLASH->PEKEYR = FLASH_PEKEY2; /* PEKEY2 */ + } + FLASH->PECR = FLASH->PECR | (FLASH_PECR_ERRIE | FLASH_PECR_EOPIE); /* enable flash interrupts */ + return EEPROM_OK; +} + +static int8_t eeprom_program_byte(uint32_t addr, uint8_t ee_data) +{ + if ((EEPROM_ADDR_START <= addr) && (addr <= EEPROM_ADDR_END - 1)) + { + *(uint8_t *)(addr) = ee_data; /* write data to EEPROM */ + if (*(uint8_t *)(addr) != ee_data) + { + return EEPROM_WRITE_ERROR; + } + return EEPROM_OK; + } else + { + return EEPROM_ADDR_ERROR; + } +} +static int8_t eeprom_program_halfword(uint32_t addr, uint16_t ee_data) +{ + if ((EEPROM_ADDR_START <= addr) && (addr <= EEPROM_ADDR_END - 2)) + { + *(uint16_t *)(addr) = ee_data; /* write data to EEPROM */ + if (*(uint16_t *)(addr) != ee_data) + { + return EEPROM_WRITE_ERROR; + } + return EEPROM_OK; + } else + { + return EEPROM_ADDR_ERROR; + } +} + +static int8_t eeprom_program_word(uint32_t addr, uint32_t ee_data) +{ + if ((EEPROM_ADDR_START <= addr) && (addr <= EEPROM_ADDR_END - 4)) + { + *(uint32_t *)(addr) = ee_data; /* write data to EEPROM */ + if (*(uint32_t *)(addr) != ee_data) + { + return EEPROM_WRITE_ERROR; + } + return EEPROM_OK; + } else + { + return EEPROM_ADDR_ERROR; + } +} diff --git a/fw_old/Core/Src/crc8.c b/fw_old/Core/Src/crc8.c new file mode 100644 index 0000000..312cdf4 --- /dev/null +++ b/fw_old/Core/Src/crc8.c @@ -0,0 +1,28 @@ +/* + * crc.c + * + * Created on: Jun 9, 2021 + * Author: user + */ + +#include "crc8.h" + +/* Stolen from Sensirion SCD4x datasheet, section 3.11 */ +uint8_t crc8_calculate(const uint8_t *data, uint16_t count) +{ + uint16_t current_byte; + uint8_t crc = CRC8_INIT; + uint8_t crc_bit; + /* calculates 8-Bit checksum with given polynomial */ + for (current_byte = 0; current_byte < count; ++current_byte) { + crc ^= (data[current_byte]); + for(crc_bit = 8; crc_bit > 0; --crc_bit) { + if (crc & 0x80) { + crc =(crc << 1) ^ CRC8_POLYNOMIAL; + } else { + crc = (crc << 1); + } + } + } + return crc; +} diff --git a/fw_old/Core/Src/i2c.c b/fw_old/Core/Src/i2c.c new file mode 100644 index 0000000..07aeaaf --- /dev/null +++ b/fw_old/Core/Src/i2c.c @@ -0,0 +1,78 @@ +/* + * i2c.c + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#include "i2c.h" +#include "stm32l0xx_ll_lpuart.h" + +i2c_context_t *i2c_context; + +int i2c_init(i2c_context_t *context) +{ + if (context == NULL) { + return I2C_ERROR; + } + i2c_context = context; + return I2C_OK; +} + +int i2c_transmit(uint8_t address, uint8_t *buffer, int len) +{ + /* prevent interrupts during I2C communication (e.g. collision with MODBUS) */ +// LL_LPUART_Disable(LPUART1); +// LL_LPUART_DisableIT_RXNE(LPUART1); +// __disable_irq(); + LL_I2C_HandleTransfer(i2c_context->i2c, address, LL_I2C_ADDRSLAVE_7BIT, len, + LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); + int i = 0; + // Autoend mode will raise STOP flag if NACK is detected + // (or if desired number of bytes is transmitted) + while (!LL_I2C_IsActiveFlag_STOP(i2c_context->i2c)) { + if (LL_I2C_IsActiveFlag_TXE(i2c_context->i2c)) { + if (i < len) { + LL_I2C_TransmitData8(i2c_context->i2c, buffer[i++]); + } + } + } + LL_I2C_ClearFlag_STOP(i2c_context->i2c); + if (LL_I2C_IsActiveFlag_NACK(i2c_context->i2c)) { + return I2C_ERROR_NACK; + } + if (len != i) { + // this will probably never happen, as NACK flag + // is raised everytime len != number of TXed bytes + return I2C_ERROR_TX_INCOMPLETE; + } +// __enable_irq(); +// LL_LPUART_Enable(LPUART1); +// LL_LPUART_EnableIT_RXNE(LPUART1); + return I2C_OK; +} + +int i2c_receive(uint8_t address, uint8_t *buffer, int len) +{ +// __disable_irq(); +// LL_LPUART_Disable(LPUART1); +// LL_LPUART_DisableIT_RXNE(LPUART1); + LL_I2C_HandleTransfer(i2c_context->i2c, address, LL_I2C_ADDRSLAVE_7BIT, len, + LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ); + int i = 0; + while (!LL_I2C_IsActiveFlag_STOP(i2c_context->i2c)) { + if (LL_I2C_IsActiveFlag_RXNE(i2c_context->i2c)) { + if (i < len) { + buffer[i++] = LL_I2C_ReceiveData8(i2c_context->i2c); + } + } + } + LL_I2C_ClearFlag_STOP(i2c_context->i2c); + if (len != i) { + return I2C_ERROR_RX_INCOMPLETE; + } +// __enable_irq(); +// LL_LPUART_Enable(LPUART1); +// LL_LPUART_EnableIT_RXNE(LPUART1); + return I2C_OK; // TODO error detection +} diff --git a/fw_old/Core/Src/main.c b/fw_old/Core/Src/main.c new file mode 100644 index 0000000..23f6270 --- /dev/null +++ b/fw_old/Core/Src/main.c @@ -0,0 +1,827 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* + * BASE CLOCK 12MHz + * Desired interrupt period 60s + */ +const uint16_t tim21_prescaler = 60000-1; // 100Hz +//const uint16_t tim21_period = 12000-1; // 60s +const uint16_t tim21_period = 1200-1; // 6s +//const uint16_t tim21_period = 200-1; // 1s + +/* Input register memory map + * (All registers are 16-bit) + * ------------------------- + * + * 30010 : CO2 [ppm] Unsigned value in range [0,40000] + * 30011 : T [deg_C * 10] From SHT4x; unsigned value in range [0; 1250]; e.g. 21.5 C => 215 + * 30012 : RH [%] From SHT4x; unsigned value in range [0; 100] + * + * Backup T and RH sensor: + * 30013 : T [deg_C * 10] From SCD4x; unsigned value in range [0; 600]; e.g. 21.5 C => 215 + * 30014 : RH [%] From SCD4x; unsigned value in range [0; 100] + * + * Extended temperature range (signed values): + * 30015 : T [deg_C * 10] From SHT4x; signed value (two's complement) in range [-400;1250] + * 30016 : T [deg_C * 10] From SCD4x; signed value (two's complement) in range [-100;600]; e.g. -12.3 C => -123 + * + */ +/* Input registers memory map implementation */ +enum +{ + REGISTER_NUM_CO2 = 30010, + REGISTER_NUM_T_SHT4x = 30011, + REGISTER_NUM_RH_SHT4x = 30012, + REGISTER_NUM_T_SCD4x = 30013, + REGISTER_NUM_RH_SCD4x = 30014, + REGISTER_NUM_T_SHT4x_SIGNED = 30015, + REGISTER_NUM_T_SCD4x_SIGNED = 30016 +} data_registers_numbers; + +enum +{ + REGISTER_NUM_LED_ON = 40001, + REGISTER_NUM_LED_BRIGHTNESS = 40002, + REGISTER_NUM_LED_SMOOTH = 40003, + REGISTER_NUM_CO2_ALERT_LIMIT1 = 40004, + REGISTER_NUM_CO2_ALERT_LIMIT2 = 40005, + REGISTER_NUM_SCD4x_T_OFFSET = 40006, + REGISTER_NUM_MODBUS_ADDR = 40007, + REGISTER_NUM_BAUDRATE = 40008 +} config_registers_numbers; + +enum +{ + REGISTER_NUM_VENDOR_NAME = 30010, + REGISTER_NUM_PRODUCT_CODE = 30011, + REGISTER_NUM_REVISION = 30012, + REGISTER_NUM_PRODUCT_NAME = 30013, + REGISTER_NUM_SERIAL_NUMBER = 30014 +} identification_registers_numbers; + +/* Variables to store the measured data */ +int CO2, T_SCD4x, RH_SCD4x; +int T_SHT4x, RH_SHT4x; +uint16_t sps30_measured_data[10]; + +/* Struct to store the sensor config */ +config_t sensor_config; +uint8_t sensor_config_pending_write = 0; +uint8_t baudrate_changed = 0; +uint8_t modbus_address_changed = 0; +uint8_t co2_valid = 0; +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_I2C1_Init(void); +static void MX_LPUART1_UART_Init(void); +static void MX_TIM21_Init(void); +/* USER CODE BEGIN PFP */ +void LPUART1_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len); +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + + /* System interrupt init*/ + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + /* Read config from EEPROM - if unsuccessful, set the default values*/ + int8_t config_read_status = config_read(&sensor_config); + if (config_read_status != CONFIG_OK) + { + sensor_config.modbus_addr = MODBUS_DEFAULT_SLAVE_ADDRESS; + sensor_config.led_co2_alert_limit1 = CONFIG_DEFAULT_LED_ALERT1_LIMIT; + sensor_config.led_co2_alert_limit2 = CONFIG_DEFAULT_LED_ALERT2_LIMIT; + sensor_config.led_on = CONFIG_DEFAULT_LED_ON; + sensor_config.led_brightness = CONFIG_DEFAULT_LED_BRIGHTNESS; + sensor_config.led_smooth = CONFIG_DEFAULT_LED_SMOOTH; + sensor_config.scd4x_t_offset = CONFIG_DEFAULT_SCD4x_T_OFFSET; + sensor_config.baudrate_index = CONFIG_DEFAULT_BAUDRATE_INDEX; + } + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_I2C1_Init(); + MX_LPUART1_UART_Init(); + MX_TIM21_Init(); + /* USER CODE BEGIN 2 */ + + /* Turn on MAGENTA LED to signal startup state */ + LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + + /* Enable I2C for sensors */ + LL_I2C_Enable(I2C1); + + + /* Set the modbus address */ + modbus_slave_set_address(sensor_config.modbus_addr); + + /* Enable UART for RS485 */ + LL_LPUART_Enable(LPUART1); + + /* Start the timer for measurement triggering */ + LL_TIM_EnableCounter(TIM21); + LL_TIM_EnableIT_UPDATE(TIM21); + + /* I2C context init (for SHT4x and SCD4x) */ + i2c_context_t i2c_context; + i2c_context.i2c = I2C1; + i2c_init(&i2c_context); + + scd4x_start_periodic_measurement(); + uint8_t scd4x_is_connected = 1; + uint8_t sps30_is_connected = 0; + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + /*uint8_t scd4x_is_connected = 0; + if (scd4x_start_periodic_measurement() == SCD4X_OK) + { + scd4x_is_connected = 1; + }*/ + + /* Attempt to start SPS30 measurement and check if it's connected */ + /*sps30_reset(); + uint8_t sps30_is_connected = 0; + if (sps30_start_measurement() == SPS30_OK) + { + sps30_is_connected = 1; + }*/ + + /* Wait 1000ms for sensors initialization */ + /* SHT4x Init Time: max 1 ms (datasheet pg. 8) */ + /* SCD4x Init Time: max 1000 ms (datasheet pg. 6) */ + /* SPS30 Init Time: max 30000 ms (datasheet pg. 2) */ + LL_mDelay(1000); + + static uint32_t new_baud; + + /* Enter the main loop */ + while (1) + { + if (lpuart1_rx_done == 1) + { + /* Process the message */ + if (lpuart1_rx_message_too_long) + { + /* Do nothing, just delete the buffer and set the flag back to zero*/ + lpuart1_rx_message_too_long = 0; + } else + { + /* Process the message: + * message is stored in modbus_buffer[], no copying necessary; + * but we need to make sure that modbus_buffer[] will not be used while + * processing the message: this can be done by disabling RX interrupt */ + LL_LPUART_DisableIT_RXNE(LPUART1); + modbus_slave_process_msg(modbus_buffer, lpuart1_rx_message_len); + /* Reset the RX DONE flag */ + lpuart1_rx_done = 0; + LL_LPUART_EnableIT_RXNE(LPUART1); + } + /* Reset the RX DONE flag */ + lpuart1_rx_done = 0; + } + /* if config changed (MODBUS write), reflect changes to EEPROM */ + if (sensor_config_pending_write) { + config_write(&sensor_config); + sensor_config_pending_write = 0; + } + if (modbus_address_changed) + { + modbus_slave_set_address(sensor_config.modbus_addr); + modbus_address_changed = 0; + } + if (baudrate_changed) + { + while (!LL_LPUART_IsActiveFlag_TXE(LPUART1)); + uart_disable_interrupts(); +// LL_LPUART_Disable(LPUART1); +// LL_LPUART_DisableIT_IDLE(LPUART1); +// LL_LPUART_EnableIT_RXNE(LPUART1); + + LL_LPUART_SetBaudRate(LPUART1, SYSTICK_FREQ_HZ, config_baudrates[sensor_config.baudrate_index]); + +// LL_LPUART_Enable(LPUART1); +// LL_LPUART_EnableIT_IDLE(LPUART1); +// LL_LPUART_EnableIT_RXNE(LPUART1); + uart_enable_interrupts(); + LL_LPUART_EnableDirectionRx(LPUART1); + LL_LPUART_EnableDirectionTx(LPUART1); + baudrate_changed = 0; + + new_baud = LL_LPUART_GetBaudRate(LPUART1, SYSTICK_FREQ_HZ); + } + + /* It is time for measurement */ + if (tim21_elapsed_period == 1) + { + /* TODO: Check the data */ + /* Read SHT4x data (always connected) */ + sht4x_measure(&T_SHT4x, &RH_SHT4x); + + /* Read SCD4x data (if connected) */ + if (scd4x_is_connected == 1) + { + scd4x_read_measurement(&CO2, + &T_SCD4x, + &RH_SCD4x); + if (CO2 > 0) { + co2_valid = 1; + } else { + co2_valid = 0; + } + } + + /* Read SPS30 data (if connected) */ + if (sps30_is_connected == 1) + { + sps30_read_measured_values(sps30_measured_data, 10); + } + /* TODO: Process data and light a desired color of LED */ + /* TODO: Add hystheresis */ + + /* Reset the TIM21 Elapsed Period Flag */ + tim21_elapsed_period = 0; + } + /* TEST END */ + if (sensor_config.led_on) { + if (co2_valid == 1) { + if (CO2 <= sensor_config.led_co2_alert_limit1) { + /* CO2 is OK -> GREEN */ + LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + + } else if ((sensor_config.led_co2_alert_limit1 < CO2) && (CO2 <= sensor_config.led_co2_alert_limit2)) { + /* CO2 is NOT OK -> YELLOW */ + LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_ResetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + + } else if (sensor_config.led_co2_alert_limit2 < CO2) { + /* CO2 is CRITICAL -> RED */ + LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + } + } else { + + LL_GPIO_ResetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_ResetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + } + + } else { + LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + } + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_0) + { + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + LL_RCC_HSI_Enable(); + + /* Wait till HSI is ready */ + while(LL_RCC_HSI_IsReady() != 1) + { + + } + LL_RCC_HSI_SetCalibTrimming(16); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLL_MUL_3, LL_RCC_PLL_DIV_4); + LL_RCC_PLL_Enable(); + + /* Wait till PLL is ready */ + while(LL_RCC_PLL_IsReady() != 1) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + + } + + LL_Init1msTick(12000000); + + LL_SetSystemCoreClock(12000000); + LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1); + LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1); +} + +/** + * @brief I2C1 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + LL_I2C_InitTypeDef I2C_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + /**I2C1 GPIO Configuration + PA9 ------> I2C1_SCL + PA10 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_9; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_1; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_10; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_1; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); + + /* USER CODE BEGIN I2C1_Init 1 */ + + /* USER CODE END I2C1_Init 1 */ + /** I2C Initialization + */ + LL_I2C_EnableAutoEndMode(I2C1); + LL_I2C_DisableOwnAddress2(I2C1); + LL_I2C_DisableGeneralCall(I2C1); + LL_I2C_EnableClockStretching(I2C1); + I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; + I2C_InitStruct.Timing = 0x40000A0B; + I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct.DigitalFilter = 0; + I2C_InitStruct.OwnAddress1 = 0; + I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK; + I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; + LL_I2C_Init(I2C1, &I2C_InitStruct); + LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK); + /* USER CODE BEGIN I2C1_Init 2 */ + /* USER CODE END I2C1_Init 2 */ + +} + +/** + * @brief LPUART1 Initialization Function + * @param None + * @retval None + */ +static void MX_LPUART1_UART_Init(void) +{ + + /* USER CODE BEGIN LPUART1_Init 0 */ + + /* USER CODE END LPUART1_Init 0 */ + + LL_LPUART_InitTypeDef LPUART_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPUART1); + + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); + /**LPUART1 GPIO Configuration + PA0-CK_IN ------> LPUART1_RX + PA1 ------> LPUART1_TX + PB1 ------> LPUART1_DE + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_0; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_6; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_1; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_6; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_1; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* LPUART1 interrupt Init */ + NVIC_SetPriority(LPUART1_IRQn, 0); + NVIC_EnableIRQ(LPUART1_IRQn); + + /* USER CODE BEGIN LPUART1_Init 1 */ + + /* USER CODE END LPUART1_Init 1 */ + LPUART_InitStruct.BaudRate = config_baudrates[sensor_config.baudrate_index]; + LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_9B; + LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1; + LPUART_InitStruct.Parity = LL_LPUART_PARITY_EVEN; + LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX; + LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; + LL_LPUART_Init(LPUART1, &LPUART_InitStruct); + LL_LPUART_EnableDEMode(LPUART1); + LL_LPUART_SetDESignalPolarity(LPUART1, LL_LPUART_DE_POLARITY_HIGH); + LL_LPUART_SetDEAssertionTime(LPUART1, 0); + LL_LPUART_SetDEDeassertionTime(LPUART1, 0); + /* USER CODE BEGIN LPUART1_Init 2 */ + + /* Enable IDLE Interrupt */ + LL_LPUART_EnableIT_IDLE(LPUART1); + + /* Enable RX Not Empty Interrupt */ + LL_LPUART_EnableIT_RXNE(LPUART1); + + LL_LPUART_EnableDirectionRx(LPUART1); + LL_LPUART_EnableDirectionTx(LPUART1); + LL_LPUART_Enable(LPUART1); + /* USER CODE END LPUART1_Init 2 */ + +} + +/** + * @brief TIM21 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM21_Init(void) +{ + + /* USER CODE BEGIN TIM21_Init 0 */ + + /* USER CODE END TIM21_Init 0 */ + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM21); + + /* TIM21 interrupt Init */ + NVIC_SetPriority(TIM21_IRQn, 0); + NVIC_EnableIRQ(TIM21_IRQn); + + /* USER CODE BEGIN TIM21_Init 1 */ + + /* USER CODE END TIM21_Init 1 */ + TIM_InitStruct.Prescaler = tim21_prescaler; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = tim21_period; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + LL_TIM_Init(TIM21, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM21); + LL_TIM_SetClockSource(TIM21, LL_TIM_CLOCKSOURCE_INTERNAL); + LL_TIM_SetTriggerOutput(TIM21, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM21); + /* USER CODE BEGIN TIM21_Init 2 */ + + /* USER CODE END TIM21_Init 2 */ + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + + /**/ + LL_GPIO_SetOutputPin(LED_B_GPIO_Port, LED_B_Pin); + + /**/ + LL_GPIO_SetOutputPin(LED_G_GPIO_Port, LED_G_Pin); + + /**/ + LL_GPIO_SetOutputPin(LED_R_GPIO_Port, LED_R_Pin); + + /**/ + GPIO_InitStruct.Pin = LED_B_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LED_B_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LED_G_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LED_G_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LED_R_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LED_R_GPIO_Port, &GPIO_InitStruct); + +} + +/* USER CODE BEGIN 4 */ +void LPUART1_TX_Buffer(uint8_t* buffer_tx, uint16_t buffer_tx_len) +{ + __disable_irq(); + for (uint16_t i = 0; i < buffer_tx_len; i++) + { + LL_LPUART_TransmitData9(LPUART1, buffer_tx[i]); + while (!LL_LPUART_IsActiveFlag_TXE(LPUART1)); + } + __enable_irq(); +} + +int8_t uart_disable_interrupts(void) +{ + LL_LPUART_Disable(LPUART1); + LL_LPUART_DisableIT_IDLE(LPUART1); + LL_LPUART_EnableIT_RXNE(LPUART1); + + return 0; +} + +int8_t uart_enable_interrupts(void) +{ + LL_LPUART_Enable(LPUART1); + LL_LPUART_EnableIT_IDLE(LPUART1); + LL_LPUART_EnableIT_RXNE(LPUART1); + + return 0; +} + +int8_t modbus_slave_callback(modbus_transaction_t *transaction) +{ + uint16_t register_number = transaction->register_number; + switch (transaction->function_code) + { + case MODBUS_READ_INPUT_REGISTERS: + for (int i = 0; i < transaction->register_count; i++, register_number++) + { + switch (register_number) + { + case REGISTER_NUM_CO2: + transaction->input_registers[i] = (uint16_t)CO2; + break; + case REGISTER_NUM_T_SHT4x: + transaction->input_registers[i] = (uint16_t)T_SHT4x; + break; + case REGISTER_NUM_RH_SHT4x: + transaction->input_registers[i] = (uint16_t)RH_SHT4x; + break; + case REGISTER_NUM_T_SCD4x: + transaction->input_registers[i] = (uint16_t)T_SCD4x; + break; + case REGISTER_NUM_RH_SCD4x: + transaction->input_registers[i] = (uint16_t)RH_SCD4x; + break; + case REGISTER_NUM_T_SHT4x_SIGNED: + transaction->input_registers_signed[i] = (int16_t)T_SHT4x; + break; + case REGISTER_NUM_T_SCD4x_SIGNED: + transaction->input_registers_signed[i] = (int16_t)T_SCD4x; + break; + default: + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + return MODBUS_OK; + case MODBUS_READ_HOLDING_REGISTERS: + for (int i = 0; i < transaction->register_count; i++, register_number++) + { + switch (register_number) + { + case REGISTER_NUM_LED_ON: + transaction->holding_registers[i] = (uint16_t)(sensor_config.led_on); + break; + case REGISTER_NUM_LED_BRIGHTNESS: + transaction->holding_registers[i] = (uint16_t)(sensor_config.led_brightness); + break; + case REGISTER_NUM_LED_SMOOTH: + transaction->holding_registers[i] = (uint16_t)(sensor_config.led_smooth); + break; + case REGISTER_NUM_CO2_ALERT_LIMIT1: + transaction->holding_registers[i] = (uint16_t)(sensor_config.led_co2_alert_limit1); + break; + case REGISTER_NUM_CO2_ALERT_LIMIT2: + transaction->holding_registers[i] = (uint16_t)(sensor_config.led_co2_alert_limit2); + break; + case REGISTER_NUM_SCD4x_T_OFFSET: + transaction->holding_registers[i] = (uint16_t)(sensor_config.scd4x_t_offset); + break; + case REGISTER_NUM_MODBUS_ADDR: + transaction->holding_registers[i] = (uint16_t)(sensor_config.modbus_addr); + break; + case REGISTER_NUM_BAUDRATE: + transaction->holding_registers[i] = (uint16_t)(sensor_config.baudrate_index); + break; + default: + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + return MODBUS_OK; + case MODBUS_WRITE_SINGLE_REGISTER: + transaction->register_count = 1; + case MODBUS_WRITE_MULTIPLE_REGISTERS: + for (int i = 0; i < transaction->register_count; i++, register_number++) + { + switch (register_number) + { + case REGISTER_NUM_LED_ON: + sensor_config.led_on = (uint8_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_LED_BRIGHTNESS: + sensor_config.led_brightness = (uint16_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_LED_SMOOTH: + sensor_config.led_smooth = (uint16_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_CO2_ALERT_LIMIT1: + sensor_config.led_co2_alert_limit1 = (uint16_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_CO2_ALERT_LIMIT2: + sensor_config.led_co2_alert_limit2 = (uint16_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_SCD4x_T_OFFSET: + sensor_config.scd4x_t_offset = (int16_t) transaction->holding_registers[i]; + break; + case REGISTER_NUM_MODBUS_ADDR: + sensor_config.modbus_addr = (uint16_t) transaction->holding_registers[i]; + modbus_address_changed = 1; + break; + case REGISTER_NUM_BAUDRATE: + if (transaction->holding_registers[0] < config_baudrates_length) + { + sensor_config.baudrate_index = (uint16_t) (transaction->holding_registers[i]); + baudrate_changed = 1; + } + break; + default: + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + sensor_config_pending_write = 1; + return MODBUS_OK; + default: + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + /* Catch-all error */ + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; /* nothing implemented yet! TODO */ +} + +int8_t modbus_transmit_function(uint8_t *buffer, uint16_t data_len) +{ + /* TODO */ + LPUART1_TX_Buffer(buffer, data_len); + return MODBUS_OK; +} +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw_old/Core/Src/modbus.c b/fw_old/Core/Src/modbus.c new file mode 100644 index 0000000..4ec6e09 --- /dev/null +++ b/fw_old/Core/Src/modbus.c @@ -0,0 +1,265 @@ +/* + * modbus.c + * + * Created on: Jul 18, 2021 + * Author: user + */ + +#include "modbus.h" + +/* + * Global variables + */ + +/* Modbus TX buffer; can be also used for RX in memory constrained systems (e.g. in main.c); + * NOTE if shared buffer is used for TX/RX, care must be taken to prevent writing into buffer + * during execution of modbus_process_message() */ +uint8_t modbus_buffer[MODBUS_MAX_RTU_FRAME_SIZE]; + +/* device address: declared */ +uint8_t modbus_slave_address = MODBUS_DEFAULT_SLAVE_ADDRESS; + +/* + * CRC16 functions + * see https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf + * section 6.2.2 + */ + +/* CRC16 (without memory mapped values) + * taken from https://ctlsys.com/support/how_to_compute_the_modbus_rtu_message_crc/ */ +uint16_t modbus_CRC16(const uint8_t *buf, int len) +{ + uint16_t crc = 0xFFFF; + + for (int pos = 0; pos < len; pos++) { + crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc + + for (int i = 8; i != 0; i--) { // Loop over each bit + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes) + return crc; +} + +/* + * Private functions + */ + +/* here we assume buffer has minimal size of MODBUS_MAX_RTU_FRAME_SIZE; + * this function is private, so hopefully it's going to be ok */ +int8_t modbus_copy_reply_to_buffer(uint8_t *buffer, uint8_t *msg_len, modbus_transaction_t *transaction) +{ + uint16_t crc16; + uint8_t byte_count; + + // TODO use relative indices (increments) instead of absolute + buffer[0] = modbus_slave_address; + buffer[1] = transaction->function_code; + *msg_len = 5; + + if (transaction->function_code & MODBUS_ERROR_FLAG) { + /* sending error reply */ + buffer[2] = transaction->exception.exception_code; + } else { + switch (transaction->function_code) { + case MODBUS_READ_HOLDING_REGISTERS: + case MODBUS_READ_INPUT_REGISTERS: + byte_count = transaction->register_count * 2; + buffer[2] = byte_count; + *msg_len = byte_count + 5; + for (int i = 0; i < transaction->register_count; i++) { + // TODO endianness handling + /* buffer16b is alias for both holding and input register buffers */ + buffer[3 + 2*i] = transaction->buffer16b[i] >> 8; + buffer[4 + 2*i] = transaction->buffer16b[i] & 0xff; + } + break; + case MODBUS_WRITE_SINGLE_REGISTER: + buffer[2] = (uint8_t) (transaction->register_address >> 8); + buffer[3] = (uint8_t) transaction->register_address; + buffer[4] = (uint8_t) (transaction->holding_registers[0] >> 8); + buffer[5] = (uint8_t) transaction->holding_registers[0]; + *msg_len = 8; + break; + case MODBUS_WRITE_MULTIPLE_REGISTERS: + buffer[2] = (uint8_t) (transaction->register_address >> 8); + buffer[3] = (uint8_t) transaction->register_address; + buffer[4] = (uint8_t) (transaction->register_count >> 8); + buffer[5] = (uint8_t) transaction->register_count; + *msg_len = 8; + break; + } + } + crc16 = modbus_CRC16(buffer, *msg_len - 2); /* last two bytes is the checksum itself */ + buffer[*msg_len - 2] = crc16 & 0xff; + buffer[*msg_len - 1] = crc16 >> 8; +} + +/* + * Public function definitions + */ + +int8_t modbus_slave_set_address(uint8_t address) +{ + if (address == 0) { + /* address 0 is broadcast address */ + return MODBUS_ERROR; + } + modbus_slave_address = address; + return MODBUS_OK; +} + +int8_t modbus_slave_process_msg(const uint8_t *buffer, int len) +{ + /* + * TODO list: + * + * 1) check that errors and exceptions are handled according to Modbus_Application_Protocol_V1_1b.pdf + * 2) buffer overflow prevention: for each function code, check that buffer is long enough + */ + /* transaction holds message context and content: + * it wraps all necessary buffers and variables */ + modbus_transaction_t transaction; + int8_t callback_result; + uint8_t buffer_pos = 0; + uint8_t byte_count; + + if (len < MODBUS_MINIMAL_FRAME_LEN) { + /* frame too short; return error */ + return MODBUS_ERROR_FRAME_INVALID; + } + /* check CRC first */ + uint16_t crc_received = (buffer[len - 1] << 8) | buffer[len - 2]; + uint16_t crc_calculated = modbus_CRC16(buffer, len - 2); + if (crc_received != crc_calculated) { + /* CRC mismatch, return error */ + //printf("crc mismatch: received 0x%x, calculated 0x%x\n", crc_received, crc_calculated); + return MODBUS_ERROR_CRC; + } + /* check if address matches ours */ + uint8_t address = buffer[buffer_pos++]; + if (address != modbus_slave_address && address != MODBUS_BROADCAST_ADDR) { + /* Message is not for us */ + return MODBUS_OK; + } + /* get function code */ + transaction.function_code = buffer[buffer_pos++]; + transaction.exception.exception_code = 0; + + if (transaction.function_code == MODBUS_READ_DEVICE_IDENTIFICATION) { + // TODO + goto modbus_send; + } + + /* set starting register number */ + switch (transaction.function_code) { + /* coils */ + case MODBUS_READ_DO: + case MODBUS_WRITE_SINGLE_DO: + case MODBUS_WRITE_MULTIPLE_DO: + transaction.register_number = MODBUS_DO_START_NUMBER; + break; + /* discrete inputs */ + case MODBUS_READ_DI: + transaction.register_number = MODBUS_DI_START_NUMBER; + break; + /* input registers */ + case MODBUS_READ_AI: + transaction.register_number = MODBUS_AI_START_NUMBER; + break; + /* holding registers */ + case MODBUS_READ_AO: + case MODBUS_WRITE_SINGLE_AO: + case MODBUS_WRITE_MULTIPLE_AO: + case MODBUS_READ_WRITE_MULTIPLE_REGISTERS: + transaction.register_number = MODBUS_AO_START_NUMBER; + break; + } + + #define MODBUS_FLAG_WRITE 0x01 + #define MODBUS_FLAG_SINGLE 0x02 + uint8_t flags = 0x00; + + /* process message */ + switch (transaction.function_code) { + case MODBUS_WRITE_SINGLE_COIL: + case MODBUS_WRITE_SINGLE_REGISTER: /* holding register */ + flags |= MODBUS_FLAG_SINGLE; + case MODBUS_WRITE_MULTIPLE_COILS: + case MODBUS_WRITE_MULTIPLE_REGISTERS: + flags |= MODBUS_FLAG_WRITE; + case MODBUS_READ_DISCRETE_INPUTS: + case MODBUS_READ_COILS: + case MODBUS_READ_INPUT_REGISTERS: + case MODBUS_READ_HOLDING_REGISTERS: + if (len < (MODBUS_MINIMAL_FRAME_LEN + 4)) { + /* buffer too short to contain everything we need */ + return MODBUS_ERROR; + } + transaction.register_address = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++]; + // TODO check length! + if (flags & MODBUS_FLAG_WRITE) { + if (flags & MODBUS_FLAG_SINGLE) { + transaction.holding_registers[0] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++]; + } else { + /* Write multiple registers */ + transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++]; + byte_count = buffer[buffer_pos++]; + if (transaction.register_count > 123 || 2*transaction.register_count != byte_count) { + /* Max number of register is defined by Modbus_Application_Protocol_V1_1b, section 6.12 */ + transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_REGISTER_QUANTITY; + } else { + for (uint8_t i = 0; i < transaction.register_count; i++) { + transaction.holding_registers[i] = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++]; + } + } + } + } else { + transaction.register_count = (buffer[buffer_pos++] << 8) | buffer[buffer_pos++]; + if ( + transaction.register_count < 1 || + transaction.register_count > MODBUS_MAX_REGISTERS + ) { + transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE; + } + } + // add offset to register number + transaction.register_number += transaction.register_address; + break; + default: + /* function code not known / not implemented, reply with + * ExceptionCode 1 */ + transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_FUNCTION; + break; + } + /* data in modbus_buffer have been processed and buffer can be re-used for TX */ + /* handle reply */ + if (transaction.exception.exception_code != 0) { + /* indicate error */ + transaction.function_code |= MODBUS_ERROR_FLAG; + } else { + callback_result = modbus_slave_callback(&transaction); + /* error handling */ + if (callback_result != MODBUS_OK) { + transaction.function_code |= MODBUS_ERROR_FLAG; + if (callback_result == MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED) { + transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_FUNCTION; + } else if (callback_result == MODBUS_ERROR_REGISTER_NOT_IMPLEMENTED) { + transaction.exception.exception_code = MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS; + } + } + } + uint8_t msg_len = 0; +modbus_send: + if (address != MODBUS_BROADCAST_ADDR) { + /* send only if master request was not broadcast */ + modbus_copy_reply_to_buffer(modbus_buffer, &msg_len, &transaction); + modbus_transmit_function(modbus_buffer, msg_len); + } +} diff --git a/fw_old/Core/Src/scd4x.c b/fw_old/Core/Src/scd4x.c new file mode 100644 index 0000000..1fc96ec --- /dev/null +++ b/fw_old/Core/Src/scd4x.c @@ -0,0 +1,106 @@ +/* + * sht4x.c + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#include "scd4x.h" +#include "main.h" /* for uart_disable_interrupts() */ + +int8_t scd4x_send_cmd(scd4x_cmd_t cmd) +{ + uint8_t buffer[32]; + int result; + + // start measurement + buffer[0] = cmd >> 8; + buffer[1] = cmd & 0x00ff; + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + if (result != I2C_OK) { + return SCD4X_ERROR; + } + + return SCD4X_OK; +} + +int8_t scd4x_read_data(uint8_t *buffer, int len) +{ + return SCD4X_OK; +} + +int8_t scd4x_start_periodic_measurement( void ) +{ + return scd4x_send_cmd(SCD4X_START_PERIODIC_MEASUREMENT); +} + +int8_t scd4x_stop_periodic_measurement( void ) +{ + return scd4x_send_cmd(SCD4X_STOP_PERIODIC_MEASUREMENT); +} + +int8_t scd4x_perform_factory_reset( void ) +{ + return scd4x_send_cmd(SCD4X_PERFORM_FACTORY_RESET); +} + +int8_t scd4x_read_measurement(uint16_t * co2, int16_t *temperature, uint16_t *relative_humidity) +{ + uint8_t buffer[32]; + int result; + + // start measurement + // TODO: Check for data ready + /* + buffer[0] = GET_DATA_READY_STATUS >> 8; + buffer[1] = GET_DATA_READY_STATUS & 0x00ff; + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + if (result != I2C_OK) { + return SCD4X_ERROR; + } + LL_mDelay(100); // 10 ms should be enough + // read out + result = i2c_receive(SCD4X_I2C_ADDRESS<<1, buffer, 6); + if (result != I2C_OK) { + return SCD4X_ERROR; + }*/ + + + // start measurement + buffer[0] = SCD4X_READ_MEASUREMENT >> 8; + buffer[1] = SCD4X_READ_MEASUREMENT & 0x00ff; + result = i2c_transmit(SCD4X_I2C_ADDRESS<<1, buffer, 2); + + // TODO: Proc to vraci NACK? Vyresit. + /*if (result != I2C_OK) { + return SCD4X_ERROR; + }*/ + uart_disable_interrupts(); + LL_mDelay(1); // 10 ms should be enough + uart_enable_interrupts(); + // read out + result = i2c_receive(SCD4X_I2C_ADDRESS<<1, buffer, 9); + if (result != I2C_OK) + { + return SCD4X_ERROR; + } + + // TODO checksum + // Convert to T and RH; taken directly from pseudocode in SHT4x datasheet, page 3 + uint32_t co2_ticks = (buffer[0] << 8) + buffer[1]; + uint32_t t_ticks = (buffer[3] << 8) + buffer[4]; + uint32_t rh_ticks = (buffer[6] << 8) + buffer[7]; + int t_degC = -450 + 10 * 175 * t_ticks / 65535; + int rh_pRH = 100 * rh_ticks / 65535; + if (rh_pRH > 100) { + rh_pRH = 100; + } + if (rh_pRH < 0) { + rh_pRH = 0; + } + *co2 = co2_ticks; + *temperature = t_degC; + *relative_humidity = rh_pRH; + + return SCD4X_OK; +} diff --git a/fw_old/Core/Src/sht4x.c b/fw_old/Core/Src/sht4x.c new file mode 100644 index 0000000..af6c23b --- /dev/null +++ b/fw_old/Core/Src/sht4x.c @@ -0,0 +1,58 @@ +/* + * sht4x.c + * + * Created on: Jun 8, 2021 + * Author: user + */ + +#include "sht4x.h" +#include "main.h" /* for uart_disable_interrupts() */ + +int8_t sht4x_send_cmd(sht4x_cmd_t cmd) +{ + return SHT4X_OK; +} + +int8_t sht4x_read_data(uint8_t *buffer, int len) +{ + return SHT4X_OK; +} + +int8_t sht4x_measure(int16_t *temperature, uint16_t *relative_humidity) +{ + uint8_t buffer[32]; + int result; + + // start measurement + buffer[0] = SHT4X_START_MEAS_HIGH_PRECISION; + result = i2c_transmit(SHT4X_I2C_ADDRESS<<1, buffer, 1); + // TODO: Proc to vraci NACK? Vyresit. + /* + if (result != I2C_OK) { + return SHT4X_ERROR; + }*/ + uart_disable_interrupts(); + LL_mDelay(10); // 10 ms should be enough + uart_enable_interrupts(); + // read out + result = i2c_receive(SHT4X_I2C_ADDRESS<<1, buffer, 6); + if (result != I2C_OK) { + return SHT4X_ERROR; + } + // TODO checksum + // Convert to T and RH; taken directly from pseudocode in SHT4x datasheet, page 3 + uint32_t t_ticks = (buffer[0] << 8) + buffer[1]; + uint32_t rh_ticks = (buffer[3] << 8) + buffer[4]; + int t_degC = -450 + 10 * 175 * t_ticks / 65535; /* temperature * 10 */ + int rh_pRH = -6 + 125 * rh_ticks / 65535; + if (rh_pRH > 100) { + rh_pRH = 100; + } + if (rh_pRH < 0) { + rh_pRH = 0; + } + *temperature = t_degC; + *relative_humidity = rh_pRH; + + return SHT4X_OK; +} diff --git a/fw_old/Core/Src/sps30.c b/fw_old/Core/Src/sps30.c new file mode 100644 index 0000000..c05a273 --- /dev/null +++ b/fw_old/Core/Src/sps30.c @@ -0,0 +1,193 @@ +/* + * sps30.c + * + * Created on: Jul 18, 2021 + * Author: david + */ + +#include "sps30.h" + +int8_t sps30_send_cmd(sps30_cmd_t cmd) +{ + uint8_t buffer[32]; + uint8_t result; + + // start measurement + buffer[0] = cmd >> 8; + buffer[1] = cmd & 0x00ff; + result = i2c_transmit(SPS30_I2C_ADDRESS<<1, buffer, 2); + // TODO: Proc to vraci NACK? Vyresit. + if (result != I2C_OK) { + return SPS30_ERROR; + } + + return SPS30_OK; +} + +int8_t sps30_start_measurement( void ) +{ + uint8_t i2c_tx_buffer[5]; + uint8_t data_for_crc = {SPS30_UINT16_FORMAT, 0x00}; + + uint8_t result; + + i2c_tx_buffer[0] = SPS30_START_MEASUREMENT >> 8; + i2c_tx_buffer[1] = SPS30_START_MEASUREMENT & 0x00ff; + i2c_tx_buffer[2] = SPS30_UINT16_FORMAT; + i2c_tx_buffer[3] = 0x00; + i2c_tx_buffer[4] = calculate_crc(data_for_crc); + + result = i2c_transmit(SPS30_I2C_ADDRESS<<1, i2c_tx_buffer, 5); + + // TODO: Proc to vraci NACK? Vyresit. + if (result != I2C_OK) { + return SPS30_ERROR; + } + return SPS30_OK; +} + +int8_t sps30_stop_measurement( void ) +{ + return sps30_send_cmd(SPS30_STOP_MEASUREMENT); +} + +int8_t sps30_read_measured_values(uint16_t *measured_values, uint8_t measured_values_len) +{ + + if (measured_values_len != 10) + { + return -5; + } + + uint8_t i2c_tx_buffer[2]; + uint8_t i2c_rx_buffer[30]; + + uint8_t result; + + // start measurement + i2c_tx_buffer[0] = SPS30_READ_MEASURED_VALUES >> 8; + i2c_tx_buffer[1] = SPS30_READ_MEASURED_VALUES & 0x00ff; + result = i2c_transmit(SPS30_I2C_ADDRESS<<1, i2c_tx_buffer, 2); + + // TODO: Proc to vraci NACK? Vyresit. + /*if (result != I2C_OK) { + return SPS30_ERROR; + } + return SPS30_OK;*/ + + LL_mDelay(1); // 10 ms should be enough + // read out + result = i2c_receive(SPS30_I2C_ADDRESS<<1, i2c_rx_buffer, 30); + if (result != I2C_OK) + { + return SPS30_ERROR; + } + + uint8_t checksums[10]; + + uint8_t j = 0; + for (uint8_t i = 0; i < 10; i++) + { + + measured_values[i] = (i2c_rx_buffer[j++] << 8) + i2c_rx_buffer[j++]; + checksums[i] = i2c_rx_buffer[j++]; + } + + return SPS30_OK; +} + +int8_t sps30_sleep( void ) +{ + return sps30_send_cmd(SPS30_SLEEP); +} + +int8_t sps30_wake_up( void ) +{ + return sps30_send_cmd(SPS30_WAKE_UP); + return sps30_send_cmd(SPS30_WAKE_UP); +} + +int8_t sps30_start_fan_cleaning( void ) +{ + return sps30_send_cmd(SPS30_START_FAN_CLEANING); +} + +int8_t sps30_reset( void ) +{ + return sps30_send_cmd(SPS30_RESET); +} + + +int8_t sps30_read_status_register ( void ) +{ + uint8_t i2c_tx_buffer[2]; + uint8_t i2c_rx_buffer[6]; + + uint8_t result; + + // start measurement + i2c_tx_buffer[0] = SPS30_READ_DEVICE_STATUS_REGISTER >> 8; + i2c_tx_buffer[1] = SPS30_READ_DEVICE_STATUS_REGISTER & 0x00ff; + result = i2c_transmit(SPS30_I2C_ADDRESS<<1, i2c_tx_buffer, 2); + + // TODO: Proc to vraci NACK? Vyresit. + /*if (result != I2C_OK) { + return SPS30_ERROR; + } + return SPS30_OK;*/ + + LL_mDelay(1); // 10 ms should be enough + // read out + result = i2c_receive(SPS30_I2C_ADDRESS<<1, i2c_rx_buffer, 6); + + return 0; +} + +int8_t sps30_read_firmware_version ( uint8_t * fw_ver_hi, uint8_t * fw_ver_lo ) +{ + uint8_t i2c_tx_buffer[2]; + uint8_t i2c_rx_buffer[3]; + + uint8_t result; + + // start measurement + i2c_tx_buffer[0] = SPS30_READ_VERSION >> 8; + i2c_tx_buffer[1] = SPS30_READ_VERSION & 0x00ff; + result = i2c_transmit(SPS30_I2C_ADDRESS<<1, i2c_tx_buffer, 2); + + // TODO: Proc to vraci NACK? Vyresit. + /*if (result != I2C_OK) { + return SPS30_ERROR; + } + return SPS30_OK;*/ + + LL_mDelay(1); // 10 ms should be enough + // read out + result = i2c_receive(SPS30_I2C_ADDRESS<<1, i2c_rx_buffer, 3); + /*if (result != I2C_OK) + { + return SPS30_ERROR; + }*/ + + *fw_ver_hi = i2c_rx_buffer[0]; + *fw_ver_lo = i2c_rx_buffer[1]; + + return SPS30_OK; +} + + +uint8_t calculate_crc(uint8_t data[2]) +{ + uint8_t crc = 0xFF; + for(uint8_t i = 0; i < 2; i++) { + crc ^= data[i]; + for(uint8_t bit = 8; bit > 0; --bit) { + if(crc & 0x80) { + crc = (crc << 1) ^ 0x31u; + } else { + crc = (crc << 1); + } + } + } + return crc; +} diff --git a/fw_old/Core/Src/stm32l0xx_it.c b/fw_old/Core/Src/stm32l0xx_it.c new file mode 100644 index 0000000..504a5a5 --- /dev/null +++ b/fw_old/Core/Src/stm32l0xx_it.c @@ -0,0 +1,208 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32l0xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32l0xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "modbus.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ +uint16_t lpuart1_rx_message_index = 0; +uint16_t lpuart1_rx_message_len = 0; +uint8_t lpuart1_rx_done = 0; +uint8_t lpuart1_rx_message_too_long = 0; + +uint8_t tim21_elapsed_period = 0; +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ +void LPUART1_CharReception_Callback( void ); +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ + +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M0+ Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) + { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVC_IRQn 0 */ + + /* USER CODE END SVC_IRQn 0 */ + /* USER CODE BEGIN SVC_IRQn 1 */ + + /* USER CODE END SVC_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + + /* USER CODE BEGIN SysTick_IRQn 1 */ + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32L0xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32l0xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles TIM21 global interrupt. + */ +void TIM21_IRQHandler(void) +{ + /* USER CODE BEGIN TIM21_IRQn 0 */ + LL_TIM_ClearFlag_UPDATE(TIM21); + tim21_elapsed_period = 1; + + /* USER CODE END TIM21_IRQn 0 */ + /* USER CODE BEGIN TIM21_IRQn 1 */ + + /* USER CODE END TIM21_IRQn 1 */ +} + +/** + * @brief This function handles LPUART1 global interrupt / LPUART1 wake-up interrupt through EXTI line 28. + */ +void LPUART1_IRQHandler(void) +{ + /* USER CODE BEGIN LPUART1_IRQn 0 */ + /* Check RXNE flag value in SR register */ + if(LL_LPUART_IsActiveFlag_RXNE(LPUART1) && LL_LPUART_IsEnabledIT_RXNE(LPUART1)) + { + /* RXNE flag will be cleared by reading of DR register (done in call) */ + /* Call function in charge of handling Character reception */ + LPUART1_CharReception_Callback(); + } + /* USER CODE END LPUART1_IRQn 0 */ + /* USER CODE BEGIN LPUART1_IRQn 1 */ + /* If the IDLE flag is active */ + if (LL_LPUART_IsActiveFlag_IDLE(LPUART1) && LL_LPUART_IsEnabledIT_IDLE(LPUART1)) + { + /* Clear the IDLE flag */ + LL_LPUART_ClearFlag_IDLE(LPUART1); + + /* Reset the buffer index */ + lpuart1_rx_message_len = lpuart1_rx_message_index; + lpuart1_rx_message_index = 0; + lpuart1_rx_done = 1; + if (lpuart1_rx_message_len > MODBUS_MAX_RTU_FRAME_SIZE) + { + lpuart1_rx_message_too_long = 1; + } + } + /* USER CODE END LPUART1_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ +void LPUART1_CharReception_Callback( void ) +{ + uint16_t lpuart1_rx_bit = LL_LPUART_ReceiveData9(LPUART1); + if (lpuart1_rx_message_index < MODBUS_MAX_RTU_FRAME_SIZE) + { + modbus_buffer[lpuart1_rx_message_index] = (uint8_t)lpuart1_rx_bit; + } + lpuart1_rx_message_index++; +} +/* USER CODE END 1 */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw_old/Core/Src/syscalls.c b/fw_old/Core/Src/syscalls.c new file mode 100644 index 0000000..4ec9584 --- /dev/null +++ b/fw_old/Core/Src/syscalls.c @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +//#undef errno +extern int errno; +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + +register char * stack_ptr asm("sp"); + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + +return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + return 0; +} + +int _open(char *path, int flags, ...) +{ + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + return -1; +} + +int _stat(char *file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + errno = ENOMEM; + return -1; +} diff --git a/fw_old/Core/Src/sysmem.c b/fw_old/Core/Src/sysmem.c new file mode 100644 index 0000000..d7cc52c --- /dev/null +++ b/fw_old/Core/Src/sysmem.c @@ -0,0 +1,80 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeIDE + * @brief STM32CubeIDE System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the newlib libc manual + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/fw_old/Core/Src/system_stm32l0xx.c b/fw_old/Core/Src/system_stm32l0xx.c new file mode 100644 index 0000000..9189ed8 --- /dev/null +++ b/fw_old/Core/Src/system_stm32l0xx.c @@ -0,0 +1,275 @@ +/** + ****************************************************************************** + * @file system_stm32l0xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32l0xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

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

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l0xx_system + * @{ + */ + +/** @addtogroup STM32L0xx_System_Private_Includes + * @{ + */ + +#include "stm32l0xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (MSI_VALUE) + #define MSI_VALUE ((uint32_t)2097152U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + + +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_Defines + * @{ + */ +/************************* Miscellaneous Configuration ************************/ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ + +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_Variables + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 2097152U; /* 32.768 kHz * 2^6 */ + const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; + const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + const uint8_t PLLMulTable[9] = {3U, 4U, 6U, 8U, 12U, 16U, 24U, 32U, 48U}; + +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L0xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @param None + * @retval None + */ +void SystemInit (void) +{ + /* Configure the Vector Table location add offset address ------------------*/ +#if defined (USER_VECT_TAB_ADDRESS) + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI + * value as defined by the MSI range. + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32l0xx_hal.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32l0xx_hal.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * @param None + * @retval None + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0U, pllmul = 0U, plldiv = 0U, pllsource = 0U, msirange = 0U; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00U: /* MSI used as system clock */ + msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> RCC_ICSCR_MSIRANGE_Pos; + SystemCoreClock = (32768U * (1U << (msirange + 1U))); + break; + case 0x04U: /* HSI used as system clock */ + if ((RCC->CR & RCC_CR_HSIDIVF) != 0U) + { + SystemCoreClock = HSI_VALUE / 4U; + } + else + { + SystemCoreClock = HSI_VALUE; + } + break; + case 0x08U: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + default: /* PLL used as system clock */ + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmul = RCC->CFGR & RCC_CFGR_PLLMUL; + plldiv = RCC->CFGR & RCC_CFGR_PLLDIV; + pllmul = PLLMulTable[(pllmul >> RCC_CFGR_PLLMUL_Pos)]; + plldiv = (plldiv >> RCC_CFGR_PLLDIV_Pos) + 1U; + + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + + if (pllsource == 0x00U) + { + /* HSI oscillator clock selected as PLL clock entry */ + if ((RCC->CR & RCC_CR_HSIDIVF) != 0U) + { + SystemCoreClock = (((HSI_VALUE / 4U) * pllmul) / plldiv); + } + else + { + SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv); + } + } + else + { + /* HSE selected as PLL clock entry */ + SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv); + } + break; + } + /* Compute HCLK clock frequency --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/fw/Core/Startup/startup_stm32l011f4ux.s b/fw_old/Core/Startup/startup_stm32l011f4ux.s similarity index 100% rename from fw/Core/Startup/startup_stm32l011f4ux.s rename to fw_old/Core/Startup/startup_stm32l011f4ux.s diff --git a/fw_old/Debug/Core/Src/config.d b/fw_old/Debug/Core/Src/config.d new file mode 100644 index 0000000..b31ca43 --- /dev/null +++ b/fw_old/Debug/Core/Src/config.d @@ -0,0 +1,24 @@ +Core/Src/config.o: ../Core/Src/config.c ../Core/Inc/config.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h \ + ../Drivers/CMSIS/Include/core_cm0plus.h \ + ../Drivers/CMSIS/Include/cmsis_version.h \ + ../Drivers/CMSIS/Include/cmsis_compiler.h \ + ../Drivers/CMSIS/Include/cmsis_gcc.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h + +../Core/Inc/config.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h: + +../Drivers/CMSIS/Include/core_cm0plus.h: + +../Drivers/CMSIS/Include/cmsis_version.h: + +../Drivers/CMSIS/Include/cmsis_compiler.h: + +../Drivers/CMSIS/Include/cmsis_gcc.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h: diff --git a/fw_old/Debug/Core/Src/config.o b/fw_old/Debug/Core/Src/config.o new file mode 100644 index 0000000000000000000000000000000000000000..fbc3e9cc0b16b652b1f7dcdd36778d306434d78d GIT binary patch literal 292872 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

sv@;!0AFA62!=q+1vuy*QULpC# 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�yG{-!n6mO`HJAie}cp~}6^^f@%bS|skbII*09McynZ?2GVHhA%a7%&8yjVeVh5$DZ{384@ z5Pmp3U@_e^Ff(78YgXFti-@r#3@~iWj@AS7?FrV#8`yYg8Y?QzRn2Aj!b)a5W_`S% zWtA-6Zlp!j+_!=s@`)Zd<}k^~MdtNTrx;_?XwOH=~jxH!G#Cr9DdC zqt+D8;kc1BrCD53&ZKW`HJ`M(fh7VTL_sfUPs=NnaLOTix>pM_EM}M+>2o=}x(CMS zCC>XBF((;=aL5!%CTcRZWq7jEctuufyENf@s1uyeF0d@pcv;(LTF)5p!Qw?^lhOzn znzfMyaG-pxYkXrM8Z!v#B_g zeAlvgb2gUbyWu_H5-3@pnRZIW;$omhiUG-KM4A(dT9TvI+gOxRIG|#oA|FI$gDqwz zK3Y`+*V%Q*h;^3BuQ)xE1~_{G9GW6o*Q`lzXC@yflVI%92;5ZLR1btqdAvR6*Zl-L zb)H(JHD66JF*^;9q#5dq`G_6><;!w-v&}0q9JW_58936lWaTIZaR~Gg_PF}c4p%uu z^TC)Is~~KR4t8WLJ9c_mKvFSN7{%6fBTxol5N@pH3BJ}wzL}6sx?It3U74&R%OT5S zTU~g}3S@%Kt@DLbyV-+TG#u!gbhfRFL2JEi){q^&B zcH`)bg>r@tV*}3cn6EkAh&qyyX<1d{mF`$<7~6+zH#EOvazb<(^MlLnWLY+Nd=@(r zWF(50>b>N((TPKodKG!Sj9q~nRCvBcqeB*Bb150B_TRj-B#}4qhY)cOk-i~oE$CeUP-T7vRT}$ zTfw7N7wKv)9|^OvIlrlmI-;6ed1Pj2V0vgGZJ206qTv-*fu13<<*w)%qC-O240dc2 zq7^|PtM*MxHVcx5h5`@4@=+Nx+WcE#vbm_5@p2*X}u~&0b3()E@1dh<>N=)*lftl^tI<(2O z9=>xXCXD-I<0SW1@m<*kz9=YQhY>qI`^~)25{#mWj}$i2N+!$AxrRwIyA8TdTmhZc zVg(7rXg2;y)I;o*)AW$d_hd^59NW8k78obU~la! z);#zzf?(K+XX}4^YTl~wXtxS^&u6ZCUK(>4gWHJBQacCH{Lsug1G(*h3t%J-XzomF zoNZ$=J}GV)i|rFClY-s_?Wi?S%H;!jSGMKuGzJu|($*91p1`K#s4|$c9mtrv&bj2m zu^it>%FzqZ10kF}cA2v)s3#?vRA^3FGFr%B`+Hb?(y=^z9H@#ZP@%mTZa`$YcB^*P zhF!bE9WtvnKN2)>+-v3`JXix91?3#lj7NLp*u_9$m~#|@Z7ZSLr?L`ktTZHGQ7L>m znJ%VsIDD_9vNri`qKDknB1zrQtX0-QvV}oCZGqg-9r4JYttQWe^+LaGxd<~6q~j35 zlR_@bk&hIsOEyo7tXSy4Z$rg6H8MRqwaNMKbL_NF`%~yo=YlYpriY6?>`b!Jtgz9` zze-PH2EUsYSo9Uv=t|mOCp{jOyx6-3^zlod&af<+8MvweEc0ST=Yu~B+|6+jBi5Wl zHOO6;j3-m5DQ3ql8SUH*>~`2O?R%Mfm0gv073zf*mdBgmKGt&Y?%jL$


ZlX%wp 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 literal 0 HcmV?d00001 diff --git a/fw_old/Debug/Core/Src/config.su b/fw_old/Debug/Core/Src/config.su new file mode 100644 index 0000000..48bcb7f --- /dev/null +++ b/fw_old/Debug/Core/Src/config.su @@ -0,0 +1,7 @@ +config.c:43:8:config_read 16 static +config.c:70:8:config_write 16 static +config.c:135:15:eeprom_lock 24 static +config.c:165:15:eeprom_unlock 24 static +config.c:198:15:eeprom_program_byte 16 static +config.c:213:15:eeprom_program_halfword 16 static +config.c:229:15:eeprom_program_word 16 static diff --git a/fw_old/Debug/Core/Src/crc8.d b/fw_old/Debug/Core/Src/crc8.d new file mode 100644 index 0000000..8c3a7ee --- /dev/null +++ b/fw_old/Debug/Core/Src/crc8.d @@ -0,0 +1,3 @@ +Core/Src/crc8.o: ../Core/Src/crc8.c ../Core/Inc/crc8.h + +../Core/Inc/crc8.h: diff --git a/fw_old/Debug/Core/Src/crc8.o b/fw_old/Debug/Core/Src/crc8.o new file mode 100644 index 0000000000000000000000000000000000000000..e5faa1ea486d72a36ac056078fe335a1dff8a3a7 GIT binary patch literal 30196 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 literal 0 HcmV?d00001 diff --git a/fw_old/Debug/Core/Src/crc8.su b/fw_old/Debug/Core/Src/crc8.su new file mode 100644 index 0000000..d2e1e30 --- /dev/null +++ b/fw_old/Debug/Core/Src/crc8.su @@ -0,0 +1 @@ +crc8.c:11:9:crc8_calculate 24 static diff --git a/fw_old/Debug/Core/Src/i2c.d b/fw_old/Debug/Core/Src/i2c.d new file mode 100644 index 0000000..82b3267 --- /dev/null +++ b/fw_old/Debug/Core/Src/i2c.d @@ -0,0 +1,30 @@ +Core/Src/i2c.o: ../Core/Src/i2c.c ../Core/Inc/i2c.h \ + ../Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h \ + ../Drivers/CMSIS/Include/core_cm0plus.h \ + ../Drivers/CMSIS/Include/cmsis_version.h \ + ../Drivers/CMSIS/Include/cmsis_compiler.h \ + ../Drivers/CMSIS/Include/cmsis_gcc.h \ + ../Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h \ + ../Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h + +../Core/Inc/i2c.h: + +../Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_i2c.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l0xx.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/stm32l011xx.h: + +../Drivers/CMSIS/Include/core_cm0plus.h: + +../Drivers/CMSIS/Include/cmsis_version.h: + +../Drivers/CMSIS/Include/cmsis_compiler.h: + +../Drivers/CMSIS/Include/cmsis_gcc.h: + +../Drivers/CMSIS/Device/ST/STM32L0xx/Include/system_stm32l0xx.h: + +../Drivers/STM32L0xx_HAL_Driver/Inc/stm32l0xx_ll_lpuart.h: diff --git a/fw_old/Debug/Core/Src/i2c.o b/fw_old/Debug/Core/Src/i2c.o new file mode 100644 index 0000000000000000000000000000000000000000..1e1b60cca8a4f10797df7945b2dd280002d7fb56 GIT binary patch literal 300872 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%0A36