From a2043006cc64eb67f7a7a8869ea4e54b393a0704 Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Tue, 17 Dec 2024 18:24:41 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D0=B8=20adc,=20modbus=20(=D0=B5=D0=B3=D0=BE=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=D0=BE=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D1=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В библиотеке adc пока только сделана заготовка для считывания выброса, надо доделать: Пока в main крутиться тест: формирование импульса ножкой светодиодом и считыание АЦП. Считывается этот импульс и определяется его пик (максимальное значение) и в районе этого пика беруться значения для расчета его амплитуды Modbus добавлен но не проверен --- diode_tester/.mxproject | 22 +- diode_tester/Core/Inc/stm32f1xx_hal_conf.h | 2 +- diode_tester/Core/Inc/stm32f1xx_it.h | 2 + diode_tester/Core/Inc/tim.h | 3 + diode_tester/Core/Inc/usart.h | 52 + diode_tester/Core/Interfaces/crc_algs.c | 116 + diode_tester/Core/Interfaces/crc_algs.h | 9 + .../Core/Interfaces/interface_config.h | 125 + diode_tester/Core/Interfaces/modbus.c | 938 ++++ diode_tester/Core/Interfaces/modbus.h | 325 ++ diode_tester/Core/Interfaces/modbus_data.h | 163 + diode_tester/Core/Interfaces/rs_message.c | 580 +++ diode_tester/Core/Interfaces/rs_message.h | 265 ++ diode_tester/Core/MyLibs/bit_access.h | 249 ++ diode_tester/Core/MyLibs/mylibs_config.h | 36 + diode_tester/Core/MyLibs/mylibs_defs.h | 106 + diode_tester/Core/MyLibs/mylibs_include.h | 79 + diode_tester/Core/MyLibs/trace.h | 80 + diode_tester/Core/MyLibs/trackers.h | 141 + diode_tester/Core/Src/adc.c | 6 +- diode_tester/Core/Src/gpio.c | 13 + diode_tester/Core/Src/main.c | 24 +- diode_tester/Core/Src/stm32f1xx_it.c | 36 +- diode_tester/Core/Src/tim.c | 74 +- diode_tester/Core/Src/usart.c | 122 + .../Core/Tester_main/tester_adc_func.c | 457 ++ .../Core/Tester_main/tester_adc_func.h | 156 + diode_tester/Core/Tester_main/tester_config.h | 67 + .../Inc/stm32f1xx_hal_uart.h | 915 ++++ .../Inc/stm32f1xx_ll_usart.h | 2569 +++++++++++ .../Src/stm32f1xx_hal_uart.c | 3771 +++++++++++++++++ diode_tester/MDK-ARM/EventRecorderStub.scvd | 9 + diode_tester/MDK-ARM/diode_tester.uvoptx | 420 +- diode_tester/MDK-ARM/diode_tester.uvprojx | 221 +- diode_tester/diode_tester.ioc | 47 +- 35 files changed, 12115 insertions(+), 85 deletions(-) create mode 100644 diode_tester/Core/Inc/usart.h create mode 100644 diode_tester/Core/Interfaces/crc_algs.c create mode 100644 diode_tester/Core/Interfaces/crc_algs.h create mode 100644 diode_tester/Core/Interfaces/interface_config.h create mode 100644 diode_tester/Core/Interfaces/modbus.c create mode 100644 diode_tester/Core/Interfaces/modbus.h create mode 100644 diode_tester/Core/Interfaces/modbus_data.h create mode 100644 diode_tester/Core/Interfaces/rs_message.c create mode 100644 diode_tester/Core/Interfaces/rs_message.h create mode 100644 diode_tester/Core/MyLibs/bit_access.h create mode 100644 diode_tester/Core/MyLibs/mylibs_config.h create mode 100644 diode_tester/Core/MyLibs/mylibs_defs.h create mode 100644 diode_tester/Core/MyLibs/mylibs_include.h create mode 100644 diode_tester/Core/MyLibs/trace.h create mode 100644 diode_tester/Core/MyLibs/trackers.h create mode 100644 diode_tester/Core/Src/usart.c create mode 100644 diode_tester/Core/Tester_main/tester_adc_func.c create mode 100644 diode_tester/Core/Tester_main/tester_adc_func.h create mode 100644 diode_tester/Core/Tester_main/tester_config.h create mode 100644 diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h create mode 100644 diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h create mode 100644 diode_tester/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c create mode 100644 diode_tester/MDK-ARM/EventRecorderStub.scvd diff --git a/diode_tester/.mxproject b/diode_tester/.mxproject index b2f689a..a30f765 100644 --- a/diode_tester/.mxproject +++ b/diode_tester/.mxproject @@ -1,35 +1,37 @@ [PreviousLibFiles] -LibFiles=Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_tim.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_tim.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f103x6.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; +LibFiles=Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_adc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_adc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f103x6.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; [] SourceFiles=;; [PreviousUsedKeilFiles] -SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\dma.c;..\Core\Src\tim.c;..\Core\Src\stm32f1xx_it.c;..\Core\Src\stm32f1xx_hal_msp.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;;; +SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\dma.c;..\Core\Src\tim.c;..\Core\Src\usart.c;..\Core\Src\stm32f1xx_it.c;..\Core\Src\stm32f1xx_hal_msp.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;;; HeaderPath=..\Drivers\STM32F1xx_HAL_Driver\Inc;..\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F1xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; CDefines=USE_HAL_DRIVER;STM32F103x6;USE_HAL_DRIVER;USE_HAL_DRIVER; [PreviousGenFiles] AdvancedFolderStructure=true -HeaderFileListSize=7 +HeaderFileListSize=8 HeaderFiles#0=..\Core\Inc\gpio.h HeaderFiles#1=..\Core\Inc\adc.h HeaderFiles#2=..\Core\Inc\dma.h HeaderFiles#3=..\Core\Inc\tim.h -HeaderFiles#4=..\Core\Inc\stm32f1xx_it.h -HeaderFiles#5=..\Core\Inc\stm32f1xx_hal_conf.h -HeaderFiles#6=..\Core\Inc\main.h +HeaderFiles#4=..\Core\Inc\usart.h +HeaderFiles#5=..\Core\Inc\stm32f1xx_it.h +HeaderFiles#6=..\Core\Inc\stm32f1xx_hal_conf.h +HeaderFiles#7=..\Core\Inc\main.h HeaderFolderListSize=1 HeaderPath#0=..\Core\Inc HeaderFiles=; -SourceFileListSize=7 +SourceFileListSize=8 SourceFiles#0=..\Core\Src\gpio.c SourceFiles#1=..\Core\Src\adc.c SourceFiles#2=..\Core\Src\dma.c SourceFiles#3=..\Core\Src\tim.c -SourceFiles#4=..\Core\Src\stm32f1xx_it.c -SourceFiles#5=..\Core\Src\stm32f1xx_hal_msp.c -SourceFiles#6=..\Core\Src\main.c +SourceFiles#4=..\Core\Src\usart.c +SourceFiles#5=..\Core\Src\stm32f1xx_it.c +SourceFiles#6=..\Core\Src\stm32f1xx_hal_msp.c +SourceFiles#7=..\Core\Src\main.c SourceFolderListSize=1 SourcePath#0=..\Core\Src SourceFiles=; diff --git a/diode_tester/Core/Inc/stm32f1xx_hal_conf.h b/diode_tester/Core/Inc/stm32f1xx_hal_conf.h index 56f878c..3f78a90 100644 --- a/diode_tester/Core/Inc/stm32f1xx_hal_conf.h +++ b/diode_tester/Core/Inc/stm32f1xx_hal_conf.h @@ -65,7 +65,7 @@ /*#define HAL_SPI_MODULE_ENABLED */ /*#define HAL_SRAM_MODULE_ENABLED */ #define HAL_TIM_MODULE_ENABLED -/*#define HAL_UART_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED /*#define HAL_USART_MODULE_ENABLED */ /*#define HAL_WWDG_MODULE_ENABLED */ diff --git a/diode_tester/Core/Inc/stm32f1xx_it.h b/diode_tester/Core/Inc/stm32f1xx_it.h index ffe78c1..a62cee0 100644 --- a/diode_tester/Core/Inc/stm32f1xx_it.h +++ b/diode_tester/Core/Inc/stm32f1xx_it.h @@ -56,7 +56,9 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void DMA1_Channel1_IRQHandler(void); +void TIM2_IRQHandler(void); void TIM3_IRQHandler(void); +void USART1_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/diode_tester/Core/Inc/tim.h b/diode_tester/Core/Inc/tim.h index 581c08e..b341b87 100644 --- a/diode_tester/Core/Inc/tim.h +++ b/diode_tester/Core/Inc/tim.h @@ -32,12 +32,15 @@ extern "C" { /* USER CODE END Includes */ +extern TIM_HandleTypeDef htim2; + extern TIM_HandleTypeDef htim3; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ +void MX_TIM2_Init(void); void MX_TIM3_Init(void); /* USER CODE BEGIN Prototypes */ diff --git a/diode_tester/Core/Inc/usart.h b/diode_tester/Core/Inc/usart.h new file mode 100644 index 0000000..b8f18ef --- /dev/null +++ b/diode_tester/Core/Inc/usart.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.h + * @brief This file contains all the function prototypes for + * the usart.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USART_H__ +#define __USART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern UART_HandleTypeDef huart1; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_USART1_UART_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USART_H__ */ + diff --git a/diode_tester/Core/Interfaces/crc_algs.c b/diode_tester/Core/Interfaces/crc_algs.c new file mode 100644 index 0000000..fcfa779 --- /dev/null +++ b/diode_tester/Core/Interfaces/crc_algs.c @@ -0,0 +1,116 @@ +#include "crc_algs.h" + + +uint32_t CRC_calc; +uint32_t CRC_ref; + +//uint16_t CRC_calc; +//uint16_t CRC_ref; + + +// left this global for debug +uint8_t uchCRCHi = 0xFF; +uint8_t uchCRCLo = 0xFF; +unsigned uIndex; + + +uint32_t crc32(uint8_t *data, uint32_t data_size) +{ + static const unsigned int crc32_table[] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; +unsigned int crc = 0xFFFFFFFF; + while (data_size--) + { + crc = (crc >> 8) ^ crc32_table[(crc ^ *data) & 255]; + data++; + } + return crc^0xFFFFFFFF; +} + + +uint16_t crc16(uint8_t *data, uint32_t data_size) +{ + /*Table of CRC values for high order byte*/ + static unsigned char auchCRCHi[]= + { + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, + 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, + }; + /*Table of CRC values for low order byte*/ + static char auchCRCLo[] = + { + 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04, + 0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8, + 0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC, + 0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10, + 0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4, + 0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38, + 0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C, + 0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0, + 0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4, + 0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68, + 0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C, + 0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0, + 0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54, + 0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98, + 0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C, + 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40, + }; + uchCRCHi = 0xFF; + uchCRCLo = 0xFF; + /* CRC Generation Function */ + while( data_size--) /* pass through message buffer */ + { + uIndex = uchCRCHi ^ *data++; /* calculate the CRC */ + uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; + uchCRCLo = auchCRCLo[uIndex]; + } + return uchCRCHi | uchCRCLo<<8; +} diff --git a/diode_tester/Core/Interfaces/crc_algs.h b/diode_tester/Core/Interfaces/crc_algs.h new file mode 100644 index 0000000..5957880 --- /dev/null +++ b/diode_tester/Core/Interfaces/crc_algs.h @@ -0,0 +1,9 @@ +#include "mylibs_include.h" + +// extern here to use in bootloader.c +extern uint32_t CRC_calc; +extern uint32_t CRC_ref; + + +uint16_t crc16(uint8_t *data, uint32_t data_size); +uint32_t crc32(uint8_t *data, uint32_t data_size); diff --git a/diode_tester/Core/Interfaces/interface_config.h b/diode_tester/Core/Interfaces/interface_config.h new file mode 100644 index 0000000..1e86cd8 --- /dev/null +++ b/diode_tester/Core/Interfaces/interface_config.h @@ -0,0 +1,125 @@ +/** +************************************************************************** +* @file interface_config.h +* @brief Конфигурации для интерфейсов +************************************************************************** + * @defgroup INTERFACE_CONFIGS Configs for interfaces + * @brief Конфигурации для интерфейсов + * @details + @{ +*************************************************************************/ +#ifndef _INTERFACE_CONFIG_H_ +#define _INTERFACE_CONFIG_H_ + +/** + * @addtogroup MODBUS_CONFIG Конфигурации для модбас + * @ingroup INTERFACE_CONFIGS + * @ingroup MODBUS + @{ + */ + +#define MODBUS_UART_NUMB 3 ///< Номер используемого UART, по нему выставляется дефайн USED_MB_UART = USARTx +#define MODBUS_SPEED 115200 ///< Скорость UART для модбас +#define MODBUS_GPIOX GPIOB ///< Порт для UART RX/TX +#define MODBUS_GPIO_PIN_RX GPIO_PIN_11 ///< Пин для UART RX +#define MODBUS_GPIO_PIN_TX GPIO_PIN_10 ///< Пин для UART TX + +#define MODBUS_TIM_NUMB 7 ///< number of used tim, accord to this define sets define USED_MB_TIM = TIMx +#define MODBUS_TIM_AHB_FREQ 72 ///< TIM AHB Bus Freq + +// defines for modbus behaviour +#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства +#define MODBUS_MAX_TIMEOUT 5000 ///< максимальнйы тайтаут MB is ms + + +#define RS_UART_Init MX_USART1_UART_Init +#define RS_UART_DeInit HAL_UART_MspDeInit +#define RS_TIM_Init MX_TIM2_Init +#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit +#define rs_huart huart1 +#define rs_htim htim2 + + + +///////////////////////////////////////////////////////////////////// +/////////////////////////---CALC DEFINES---////////////////////////// + +/* set USART_TypeDef for choosen numb of usart */ +#if (MODBUS_UART_NUMB == 1) + #define USED_MODBUS_UART USART1 + #define USE_USART1 +#elif (MODBUS_UART_NUMB == 2) + #define USED_MODBUS_UART USART2 + #define USE_USART2 +#elif (MODBUS_UART_NUMB == 3) + #define USED_MODBUS_UART USART3 + #define USE_USART3 +#elif (MODBUS_UART_NUMB == 4) + #define USED_MODBUS_UART UART4 + #define USE_UART4 +#elif (MODBUS_UART_NUMB == 5) + #define USED_MODBUS_UART UART5 + #define USE_UART6 +#elif (MODBUS_UART_NUMB == 6) + #define USED_MODBUS_UART USART6 + #define USE_USART6 +#endif + +#if (MODBUS_TIM_NUMB == 1) + #define USED_MODBUS_TIM TIM1 + #define USE_TIM1 +#elif (MODBUS_TIM_NUMB == 2) + #define USED_MODBUS_TIM TIM2 + #define USE_TIM2 +#elif (MODBUS_TIM_NUMB == 3) + #define USED_MODBUS_TIM TIM3 + #define USE_TIM3 +#elif (MODBUS_TIM_NUMB == 4) + #define USED_MODBUS_TIM TIM4 + #define USE_TIM4 +#elif (MODBUS_TIM_NUMB == 5) + #define USED_MODBUS_TIM TIM5 + #define USE_TIM5 +#elif (MODBUS_TIM_NUMB == 6) + #define USED_MODBUS_TIM TIM6 + #define USE_TIM6 +#elif (MODBUS_TIM_NUMB == 7) + #define USED_MODBUS_TIM TIM7 + #define USE_TIM7 +#elif (MODBUS_TIM_NUMB == 8) + #define USED_MODBUS_TIM TIM8 + #define USE_TIM8 +#elif (MODBUS_TIM_NUMB == 9) + #define USED_MODBUS_TIM TIM9 + #define USE_TIM9 +#elif (MODBUS_TIM_NUMB == 10) + #define USED_MODBUS_TIM TIM10 + #define USE_TIM10 +#elif (MODBUS_TIM_NUMB == 11) + #define USED_MODBUS_TIM TIM11 + #define USE_TIM11 +#elif (MODBUS_TIM_NUMB == 12) + #define USED_MODBUS_TIM TIM12 + #define USE_TIM12 +#elif (MODBUS_TIM_NUMB == 13) + #define USED_MODBUS_TIM TIM13 + #define USE_TIM13 +#elif (MODBUS_TIM_NUMB == 14) + #define USED_MODBUS_TIM TIM14 + #define USE_TIM14 +#endif + + + +/** MODBUS_CONFIG + * @} + */ + + + + +/** INTERFACE_CONFIGS + * @} + */ + +#endif //_INTERFACE_CONFIG_H_ \ No newline at end of file diff --git a/diode_tester/Core/Interfaces/modbus.c b/diode_tester/Core/Interfaces/modbus.c new file mode 100644 index 0000000..83db20d --- /dev/null +++ b/diode_tester/Core/Interfaces/modbus.c @@ -0,0 +1,938 @@ +/** +************************************************************************** +* @file modbus.c +* @brief Модуль для реализации MODBUS. +************************************************************************** +* @par Функции и дефайны +* +* Defines: data access +* - MB_Set_Coil_Local() - Выставление коила по локальному адресу относительно начала массива +* - MB_Reset_Coil_Local() - Сброс коила по локальному адресу относительно начала массива +* - MB_Toogle_Coil_Local() - Переключение коила по локальному адресу относительно начала массива +* - MB_Read_Coil_Local() - Чтение коила по локальному адресу относительно начала массива +* +* Functions: data access +* - MB_Write_Coil_Global() - Запись 0/1 в один коил по глобальному адресу +* - MB_Read_Coil_Global() - Чтение одного коила по глобальному адресу +* +* Functions: process message +* - MB_DefineRegistersAddress() - Определение "начального" адреса регистров +* - MB_DefineCoilsAddress() - Определение "начального" адреса коилов +* - MB_Check_Address_For_Arr() - Определение принадлежит ли адресс Addr конкретному массиву +* - Обработка команд модбас +* - MB_Read_Coils(), +* - MB_Read_Hold_Regs(), +* - MB_Write_Single_Coil() +* - MB_Write_Miltuple_Coils() +* - MB_Write_Miltuple_Regs() +* +* Functions: RS functions +* - RS_Parse_Message() / RS_Collect_Message() - Заполнение структуры сообщения и буфера +* - RS_Response() - Ответ на комманду +* - RS_Define_Size_of_RX_Message() - Определение размера принимаемых данных +* - RS_Init() - Инициализация периферии и modbus handler +* +* Functions: initialization +* - MODBUS_FirstInit() - Инициализация modbus +* +************************************************************************** +* @par Данные для модбас +* +* Holding/Input Registers +* - Регистры представляют собой 16-битные числа (слова). В обработке комманд +* находится адресс "начального" регистра и записывается в указатель. Доступ к +* остальным регистрам осуществляется через указатель. Таким образом, сами +* регистры могут представлять собой как массив так и структуру. +* +* Coils +* - Коилы представляют собой биты, упакованные в 16-битные регистры. В обработке +* комманд находится адресс "начального" регистра запрашиваемого коила. Доступ к +* остальным коилам осуществляется через маску и указатель. Таким образом, сами +* коилы могут представлять собой как массив так и структуру. +* +@verbatim +EXAMPLE: INIT SLAVE RECEIVE + //--------------Настройка модбас--------------// + // set up UART for modbus + modbus1_suart.huart.Instance = USED_MODBUS_UART; + modbus1_suart.huart.Init.BaudRate = PROJSET.MB_SPEED; + modbus1_suart.GPIOx = GPIOB; + modbus1_suart.GPIO_PIN_RX = GPIO_PIN_11; + modbus1_suart.GPIO_PIN_TX = GPIO_PIN_10; + + // set up timeout TIM for modbus + modbus1_stim.htim.Instance = TIM7; + modbus1_stim.sTimAHBFreqMHz = 84; + modbus1_stim.sTimMode = TIM_IT_CONF; + + // set up modbus: MB_RX_Size_NotConst and Timeout enable + hmodbus1.ID = 1; + hmodbus1.sRS_Timeout = 5000; + hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; + hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; + + // INIT + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0); + + //----------------Прием модбас----------------// + RS_MsgTypeDef MODBUS_MSG; + RS_Receive_IT(&hmodbus1, &MODBUS_MSG); +@endverbatim +*************************************************************************/ + +#include "rs_message.h" +uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug +/* MODBUS HANDLES */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +UART_SettingsTypeDef modbus1_suart; +TIM_SettingsTypeDef modbus1_stim; +#else +extern UART_HandleTypeDef rs_huart; +extern TIM_HandleTypeDef rs_htim; +#endif +RS_HandleTypeDef hmodbus1; + +/* DEFINE REGISTERS/COILS */ +MB_DataStructureTypeDef MB_DATA; +RS_MsgTypeDef MODBUS_MSG; + +uint32_t delay_scide = 1; +uint32_t numb_scide = 10; +//------------------------------------------------------------------- +//-----------------------------FOR USER------------------------------ +/** + * @brief First set up of MODBUS. + * @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас. + * Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1) + * ШИМ генерируется на одном канале. + * @note This called from main + */ +void MODBUS_FirstInit(void) +{ + //-----------SETUP MODBUS------------- + // set up UART for modbus +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + modbus1_suart.huart.Instance = USED_MODBUS_UART; + modbus1_suart.huart.Init.BaudRate = MODBUS_SPEED; + modbus1_suart.GPIOx = MODBUS_GPIOX; + modbus1_suart.GPIO_PIN_RX = MODBUS_GPIO_PIN_RX; + modbus1_suart.GPIO_PIN_TX = MODBUS_GPIO_PIN_TX; + + // set up timeout TIM for modbus + modbus1_stim.htim.Instance = USED_MODBUS_TIM; + modbus1_stim.sTimAHBFreqMHz = MODBUS_TIM_AHB_FREQ; + modbus1_stim.sTimMode = TIM_IT_CONF; + +#endif + // set up modbus: MB_RX_Size_NotConst and Timeout enable + hmodbus1.ID = MODBUS_DEVICE_ID; + hmodbus1.sRS_Timeout = MODBUS_MAX_TIMEOUT; + hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; + hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; + + // INIT +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0); +#else + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, &rs_htim, 0); +#endif + + RS_EnableReceive(); +} +/** + * @brief Set or Reset Coil at its global address. + * @param Addr - адрес коила. + * @param WriteVal - Что записать в коил: 0 или 1. + * @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. + * + * @details Позволяет обратиться к любому коилу по его глобальному адрессу. + Вне зависимости от того как коилы размещены в памяти. + */ +MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) +{ + //---------CHECK FOR ERRORS---------- + MB_ExceptionTypeDef Exception = NO_ERRORS; + uint16_t *coils; + uint16_t start_shift = 0; // shift in coils register + + //------------WRITE COIL------------- + Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1); + if(Exception == NO_ERRORS) + { + switch(WriteVal) + { + case SET_COIL: + *coils |= (1<= R_ARR_ADDR) + { + // if quantity too big return error + if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) + { + return ILLEGAL_DATA_ADDRESS; // return exception code + } + // if all ok - return no errors + return NO_ERRORS; + } + // if address isnt from this array return error + else + return ILLEGAL_DATA_ADDRESS; // return exception code +} +/** + * @brief Define Address Origin for Input/Holding Registers + * @param pRegs - указатель на указатель регистров. + * @param Addr - адрес начального регистра. + * @param Qnt - количество запрашиваемых регистров. + * @param WriteFlag - флаг регистр нужны для чтения или записи. + * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. + * + * @details Определение адреса начального регистра. + * @note WriteFlag пока не используется. + */ +MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType) +{ + /* check quantity error */ + if (Qnt > 125) + { + return ILLEGAL_DATA_VALUE; // return exception code + } + + if(RegisterType == RegisterType_Holding) + { + // Устаки для напряжений ТЭ: предупреждения аварии + if(MB_Check_Address_For_Arr(Addr, Qnt, R_SETPOINTS_ADDR, R_SETPOINTS_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // начало регистров хранения/входных + } + // Устаки для настройки МЗКТЭ: запрет опроса и настройки общения (MODBUS/UART) + else if(MB_Check_Address_For_Arr(Addr, Qnt, R_SETTINGS_ADDR, R_SETTINGS_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // начало регистров хранения/входных + } + // if address doesnt match any array - return illegal data address response + else + { + return ILLEGAL_DATA_ADDRESS; + } + } + else if(RegisterType == RegisterType_Input) + { + // Напряжения на ТЭ + if(MB_Check_Address_For_Arr(Addr, Qnt, R_TE_VOLTAGE_ADDR, R_TE_VOLTAGE_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // начало регистров хранения/входных + } + // Статус регистр МЗКТЭ + else if(MB_Check_Address_For_Arr(Addr, Qnt, R_STATUS_REG_ADDR, R_STATUS_REG_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // начало регистров хранения/входных + } + // if address doesnt match any array - return illegal data address response + else + { + return ILLEGAL_DATA_ADDRESS; + } + } + else + { + return ILLEGAL_FUNCTION; + } + // if found requeried array return no err + return NO_ERRORS; // return no errors +} +/** + * @brief Define Address Origin for coils + * @param pCoils - указатель на указатель коилов. + * @param Addr - адресс начального коила. + * @param Qnt - количество запрашиваемых коилов. + * @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила. + * @param WriteFlag - флаг коилы нужны для чтения или записи. + * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. + * + * @details Определение адреса начального регистра запрашиваемых коилов. + * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. + */ +MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag) +{ + /* check quantity error */ + if (Qnt > 2000) + { + return ILLEGAL_DATA_VALUE; // return exception code + } + + // peripheral control coils + if(MB_Check_Address_For_Arr(Addr, Qnt, C_TE_EXCLUDE_ADDR, C_TE_EXCLUDE_QNT) == NO_ERRORS) + { + *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr-C_TE_EXCLUDE_ADDR); + } + // if address doesnt match any array - return illegal data address response + else + { + return ILLEGAL_DATA_ADDRESS; + } + + *start_shift = Addr % 16; // set shift to requested coil + // if found requeried array return no err + return NO_ERRORS; // return no errors +} + + +/** + * @brief Proccess command Read Coils (01 - 0x01). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Coils. + */ +uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + uint16_t *coils; + uint16_t start_shift = 0; // shift in coils register + + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------READING COIL------------ + // setup output message data size + modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8); + // create mask for coils + uint16_t mask_for_coils = 0; // mask for coils that've been chosen + uint16_t setted_coils = 0; // value of setted coils + uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen + uint16_t coil_cnt = 0; // counter for processed coils + + // cycle until all registers with requered coils would be processed + int shift = start_shift; // set shift to first coil in first register + int ind = 0; // index for coils registers and data + for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) + { + //----SET MASK FOR COILS REGISTER---- + mask_for_coils = 0; + for(; shift < 0x10; shift++) + { + mask_for_coils |= 1<<(shift); // choose certain coil + if(++coil_cnt >= modbus_msg->Qnt) + break; + } + shift = 0; // set shift to zero for the next step + + //-----------READ COILS-------------- + modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; + if(ind > 0) + modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; + + } + // т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты + for(; ind >= 0; --ind) + modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); + + return 1; +} + +/** + * @brief Proccess command Read Holding Registers (03 - 0x03). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Holding Registers. + */ +uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + // get origin address for data + uint16_t *pHoldRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + + //-----------READING REGS------------ + // setup output message data size + modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits + // read data + int i; + for (i = 0; iQnt; i++) + { + modbus_msg->DATA[i] = *(pHoldRegs++); + } + return 1; +} + +/** + * @brief Proccess command Read Input Registers (04 - 0x04). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Input Registers. + */ +uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + // get origin address for data + uint16_t *pInRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + + //-----------READING REGS------------ + // setup output message data size + modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits + // read data + int i; + for (i = 0; iQnt; i++) + { + if(*((int16_t *)pInRegs) > 0) + modbus_msg->DATA[i] = (*pInRegs++); + else + modbus_msg->DATA[i] = (*pInRegs++); + } + return 1; +} +/** + * @brief Proccess command Write Single Coils (05 - 0x05). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Single Coils. + */ +uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) + { + modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + return 0; + } + // define position of coil + uint16_t *coils; + uint16_t start_shift = 0; // shift in coils register + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + + //----------WRITTING COIL------------ + if(modbus_msg->Qnt == 0xFF00) + *(coils) |= 1<Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------WRITTING REG------------ + *(pHoldRegs) = modbus_msg->Qnt; + return 1; +} + +/** + * @brief Proccess command Write Multiple Coils (15 - 0x0F). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Multiple Coils. + */ +uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) + { // if quantity too large OR if quantity and bytes count arent match + modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + return 0; + } + // define position of coil + uint16_t *coils; // pointer to coils + uint16_t start_shift = 0; // shift in coils register + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //----------WRITTING COILS----------- + // create mask for coils + uint16_t mask_for_coils = 0; // mask for coils that've been chosen + uint32_t setted_coils = 0; // value of setted coils + uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen + uint16_t coil_cnt = 0; // counter for processed coils + + // cycle until all registers with requered coils would be processed + int shift = start_shift; // set shift to first coil in first register + for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) + { + //----SET MASK FOR COILS REGISTER---- + mask_for_coils = 0; + for(; shift < 0x10; shift++) + { + mask_for_coils |= 1<<(shift); // choose certain coil + if(++coil_cnt >= modbus_msg->Qnt) + break; + } + shift = 0; // set shift to zero for the next step + + + + //-----------WRITE COILS------------- + // get current coils + temp_reg = *(coils+ind); + // set coils + setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; + if(ind > 0) + { + setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); + } + // write coils + + *(coils+ind) = setted_coils & mask_for_coils; + // restore untouched coils + *(coils+ind) |= temp_reg&(~mask_for_coils); + + + if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle + break; // *kind of unnecessary + } + + return 1; +} + +/** + * @brief Proccess command Write Multiple Registers (16 - 0x10). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Multiple Registers. + */ +uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) +{ + //---------CHECK FOR ERRORS---------- + if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt) + { // if quantity and bytes count arent match + modbus_msg->Except_Code = 3; + return 0; + } + // get origin address for data + uint16_t *pHoldRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------WRITTING REGS----------- + for (int i = 0; iQnt; i++) + { + *(pHoldRegs++) = modbus_msg->DATA[i]; + } + return 1; +} + + +/** + * @brief Respond accord to received message. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о результате ответа на комманду. + * @details Обработка принятой комманды и ответ на неё. + */ +RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) +{ + RS_StatusTypeDef MB_RES = 0; + hmodbus->f.MessageHandled = 0; + hmodbus->f.EchoResponse = 0; + RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit + + if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing + { + switch (modbus_msg->Func_Code) + { + // Read Coils + case MB_R_COILS: + hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr); + break; + + // Read Hodling Registers + case MB_R_HOLD_REGS: + hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr); + break; + case MB_R_IN_REGS: + hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr); + break; + + + // Write Single Coils + case MB_W_COIL: + hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) + } + break; + + case MB_W_HOLD_REG: + hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) + } + break; + + // Write Multiple Coils + case MB_W_COILS: + hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) + } + break; + + // Write Multiple Registers + case MB_W_HOLD_REGS: + hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) + } + break; + + /* unknown func code */ + default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */ + } + + if(hmodbus->f.MessageHandled == 0) + { + TrackerCnt_Err(hmodbus->rs_err); + modbus_msg->Func_Code += ERR_VALUES_START; + } + else + { + TrackerCnt_Ok(hmodbus->rs_err); + } + + + } + + // if we need response - check that transmit isnt busy + if( RS_Is_TX_Busy(hmodbus) ) + RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free + + // Transmit right there, or sets (fDeferredResponse) to transmit response in main code + MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg); + + hmodbus->RS_STATUS = MB_RES; + return MB_RES; +} + +/** + * @brief Collect message in buffer to transmit it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения буфера. + * @details Заполнение буффера UART из структуры сообщения. + */ +RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) +{ + int ind = 0; // ind for modbus-uart buffer + + if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need + ind = hmodbus->RS_Message_Size; + else + { + //------INFO ABOUT DATA/MESSAGE------ + //-----------[first bytes]----------- + // set ID of message/user + modbus_uart_buff[ind++] = modbus_msg->MbAddr; + + // set dat or err response + modbus_uart_buff[ind++] = modbus_msg->Func_Code; + + if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur + { + // set size of received data + if (modbus_msg->ByteCnt <= DATA_SIZE*2) // if ByteCnt less than DATA_SIZE + modbus_uart_buff[ind++] = modbus_msg->ByteCnt; + else // otherwise return data_size err + { + TrackerCnt_Err(hmodbus->rs_err); + return RS_COLLECT_MSG_ERR; + } + + //---------------DATA---------------- + //-----------[data bytes]------------ + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data + { // set data + if (i%2 == 0) // HI byte + modbus_uart_buff[ind++] = (*tmp_data_addr)>>8; + else // LO byte + { + modbus_uart_buff[ind++] = *tmp_data_addr; + tmp_data_addr++; + } + } + } + else // if some error occur + { // send expection code + modbus_uart_buff[ind++] = modbus_msg->Except_Code; + } + } + //---------------CRC---------------- + //---------[last 16 bytes]---------- + // calc crc of received data + uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); + // write crc to message structure and modbus-uart buffer + modbus_msg->MB_CRC = CRC_VALUE; + modbus_uart_buff[ind++] = CRC_VALUE; + modbus_uart_buff[ind++] = CRC_VALUE >> 8; + + hmodbus->RS_Message_Size = ind; + + return RS_OK; // returns ok +} + +/** + * @brief Parse message from buffer to process it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения структуры. + * @details Заполнение структуры сообщения из буффера UART. + */ +RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) +{ + uint32_t check_empty_buff; + int ind = 0; // ind for modbus-uart buffer + //-----INFO ABOUT DATA/MESSAGE------- + //-----------[first bits]------------ + // get ID of message/user + modbus_msg->MbAddr = modbus_uart_buff[ind++]; + if(modbus_msg->MbAddr != hmodbus->ID) + return RS_SKIP; + + // get dat or err response + modbus_msg->Func_Code = modbus_uart_buff[ind++]; + + // get address from CMD + modbus_msg->Addr = modbus_uart_buff[ind++] << 8; + modbus_msg->Addr |= modbus_uart_buff[ind++]; + + // get address from CMD + modbus_msg->Qnt = modbus_uart_buff[ind++] << 8; + modbus_msg->Qnt |= modbus_uart_buff[ind++]; + + if(hmodbus->f.RX_Half == 0) // if all message received + { + //---------------DATA---------------- + // (optional) + if (modbus_msg->ByteCnt != 0) + { + ind++; // increment ind for data_size byte + //check that data size is correct + if (modbus_msg->ByteCnt > DATA_SIZE*2) + { + TrackerCnt_Err(hmodbus->rs_err); + modbus_msg->Func_Code += ERR_VALUES_START; + return RS_PARSE_MSG_ERR; + } + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits + { // set data + if (i%2 == 0) + *tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8); + else + { + *tmp_data_addr |= modbus_uart_buff[ind++]; + tmp_data_addr++; + } + } + } + + //---------------CRC---------------- + //----------[last 16 bits]---------- + // calc crc of received data + uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); + // get crc of received data + modbus_msg->MB_CRC = modbus_uart_buff[ind++]; + modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; + // compare crc + if (modbus_msg->MB_CRC != CRC_VALUE) + { + TrackerCnt_Err(hmodbus->rs_err); + modbus_msg->Func_Code += ERR_VALUES_START; + } + // hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc + + // check is buffer empty + check_empty_buff = 0; + for(int i=0; iMB_RESPONSE = MB_EMPTY_MSG; // + } + + return RS_OK; + +} + +/** + * @brief Define size of RX Message that need to be received. + * @param hRS - указатель на хендлер RS. + * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. + * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. + * @details Определение сколько байтов надо принять по протоколу. + */ +RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_t *rx_data_size) +{ + RS_StatusTypeDef MB_RES = 0; + + MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr); + if(MB_RES == RS_SKIP) // if message not for us + return MB_RES; // return + + if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F) + { + hmodbus->pMessagePtr->ByteCnt = 0; + *rx_data_size = 1; + } + else + { + hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command + // +1 because that defines is size, not ind. + *rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2; + } + hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message + return RS_OK; +} + +//-----------------------------FOR USER------------------------------ +//------------------------------------------------------------------- + + + +//------------------------------------------------------------------- +//-------------------------HANDLERS FUNCTION------------------------- +#if (MODBUS_UART_NUMB == 1) // choose handler for UART +void USART1_IRQHandler(void) +#elif (MODBUS_UART_NUMB == 2) +void USART2_IRQHandler(void) +#elif (MODBUS_UART_NUMB == 3) +void USART3_IRQHandler(void) +#elif (MODBUS_UART_NUMB == 4) +void USART4_IRQHandler(void) +#elif (MODBUS_UART_NUMB == 5) +void USART5_IRQHandler(void) +#elif (MODBUS_UART_NUMB == 6) +void USART6_IRQHandler(void) +#endif +{ + Trace_MB_UART_Enter(); + RS_UART_Handler(&hmodbus1); + Trace_MB_UART_Exit(); +} +#if (MODBUS_TIM_NUMB == 1) || (MODBUS_TIM_NUMB == 10) // choose handler for TIM +void TIM1_UP_TIM10_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 2) +void TIM2_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 3) +void TIM3_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 4) +void TIM4_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 5) +void TIM5_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 6) +void TIM6_DAC_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 7) +void TIM7_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 8) || (MODBUS_TIM_NUMB == 13) +void TIM8_UP_TIM13_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 1) || (MODBUS_TIM_NUMB == 9) +void TIM1_BRK_TIM9_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 1) || (MODBUS_TIM_NUMB == 11) +void TIM1_TRG_COM_TIM11_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 8) || (MODBUS_TIM_NUMB == 12) +void TIM8_BRK_TIM12_IRQHandler(void) +#elif (MODBUS_TIM_NUMB == 8) || (MODBUS_TIM_NUMB == 14) +void TIM8_TRG_COM_TIM14_IRQHandler(void) +#endif +{ + Trace_MB_TIM_Enter(); + RS_TIM_Handler(&hmodbus1); + Trace_MB_TIM_Exit(); +} + +//-------------------------HANDLERS FUNCTION------------------------- +//------------------------------------------------------------------- diff --git a/diode_tester/Core/Interfaces/modbus.h b/diode_tester/Core/Interfaces/modbus.h new file mode 100644 index 0000000..ca0af1d --- /dev/null +++ b/diode_tester/Core/Interfaces/modbus.h @@ -0,0 +1,325 @@ +/** + ************************************************************************** + * @file modbus.h + * @brief Заголовочный файл модуля MODBUS. + * @details Данный файл необходимо подключить в rs_message.h. После подключать + * rs_message.h к основному проекту. + * + * @defgroup MODBUS + * @brief Modbus stuff + * + *************************************************************************/ +#ifndef __MODBUS_H_ +#define __MODBUS_H_ + +#include "mylibs_include.h" +#include "modbus_data.h" +//#include "settings.h" // for modbus settings + +/** + * @addtogroup MODBUS_SETTINGS + * @ingroup MODBUS + * @brief Some defines for modbus + @{ + */ +///////////////////////////////////////////////////////////////////// +//////////////////////////---SETTINGS---///////////////////////////// +// USER SETTINGS FOR MODBUS IN interface_config.h +//////////////////////////---SETTINGS---///////////////////////////// + + +///////////////////////////////////////////////////////////////////// +/////////////////////---USER MESSAGE DEFINES---////////////////////// +//-------------DEFINES FOR STRUCTURE---------------- +/* defines for structure of modbus message */ +#define MbAddr_SIZE 1 ///< size of (MbAddr) +#define Func_Code_SIZE 1 ///< size of (Func_Code) +#define Addr_SIZE 2 ///< size of (Addr) +#define Qnt_SIZE 2 ///< size of (Qnt) +#define ByteCnt_SIZE 1 ///< size of (ByteCnt) +#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) +#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes + +/** @brief Size of whole message */ +#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) + +/** @brief Size of first part of message that will be received +first receive info part of message, than defines size of rest message*/ +#define RX_FIRST_PART_SIZE INFO_SIZE_MAX + +/** @brief Size of buffer: max size of whole message */ +#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message + +/** @brief Structure for modbus exception codes */ +typedef enum //MB_ExceptionTypeDef +{ + // reading + NO_ERRORS = 0x00, ///< no errors + ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан + ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен + ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной + SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие +// ACKNOWLEDGE = 0x05, ///< idk +// SLAVE_DEVICE_BUSY = 0x06, ///< idk +// MEMORY_PARITY_ERROR = 0x08, ///< idk +}MB_ExceptionTypeDef; + +#define ERR_VALUES_START 0x80U ///< from this value starts error func codes +/** @brief Structure for modbus func codes */ +typedef enum //MB_FunctonTypeDef +{ + /* COMMANDS */ + // reading + MB_R_COILS = 0x01, ///< Чтение битовых ячеек + MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов +#ifndef TESTER_MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS + MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров + MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения +#else + MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров + MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения +#endif + + // writting + MB_W_COIL = 0x05, ///< Запись битовой ячейки + MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра + MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек + MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров + + /* ERRORS */ + // error reading + MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек + MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов + MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения + MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров + + // error writting + MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки + MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра + MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек + MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров +}MB_FunctonTypeDef; + +/** @brief Structure for modbus messsage */ +typedef struct // RS_MsgTypeDef +{ + uint8_t MbAddr; ///< Modbus Slave Address + MB_FunctonTypeDef Func_Code; ///< Modbus Function Code + uint16_t Addr; ///< Modbus Address of data + uint16_t Qnt; ///< Quantity of modbus data + uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive + + uint16_t DATA[DATA_SIZE]; ///< Modbus Data + MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command + + uint16_t MB_CRC; ///< Modbus CRC +}RS_MsgTypeDef; +//-------------------------------------------------- +extern RS_MsgTypeDef MODBUS_MSG; +/////////////////////---MODBUS USER SETTINGS---////////////////////// + +/** MODBUS_SETTINGS + * @} + */ + + +///////////////////////////////////////////////////////////////////// +////////////////////---MODBUS MESSAGE DEFINES---///////////////////// +/** + * @addtogroup MODBUS_MESSAGE_DEFINES + * @ingroup MODBUS + * @brief Some defines for modbus + @{ + */ +/** @brief Structure for coils operation */ +typedef enum +{ + SET_COIL, + RESET_COIL, + TOOGLE_COIL, +}MB_CoilsOpTypeDef; + +//-------------------------------------------------- + +/** + * @brief Macros to set pointer to 16-bit array + * @param _arr_ - массив регистров (16-бит). + */ +#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_))) +/** + * @brief Macros to set pointer to register + * @param _parr_ - массив регистров. + * @param _addr_ - Номер регистра (его индекс) от начала массива _arr_. + */ +#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_)) + +/** + * @brief Macros to set pointer to a certain register that contains certain coil + * @param _parr_ - массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * @note Используется вместе с @ref MB_Set_Coil_Mask + @verbatim Пояснение выражений + (_coil_/16) - get index (address shift) of register that contain certain coil + Visual explanation: 30th coil in coils registers array + xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx + |register[0]----| |register[1]----| + |skip this------| |get this-------| + |shift to 14 bit| + @endverbatim + */ +#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) +/** + * @brief Macros to set mask to a certain bit in coils register + * @param _coil_ - Номер коила от начала массива _arr_. + * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr + @verbatim Пояснение выражений + (16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register + _coil_-(16*(_coil_/16)) - shift to certain coil in certain register + e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14) + + Visual explanation: 30th coil in coils registers array + xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx + |register[0]----| |register[1]----| + |skip this------| |get this-------| + |shift to 14 bit| + @endverbatim + */ +#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) + +/** + * @brief Read Coil at its local address. + * @param _parr_ - массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * @return uint16_t - Возвращает запрошенный коил на 0м бите. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) +/** + * @brief Set Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) +/** + * @brief Reset Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) +/** + * @brief Set Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) +//-------------------------------------------------- + + +//------------------OTHER DEFINES------------------- +#define RegisterType_Holding 0 +#define RegisterType_Input 1 +#define RegisterType_Discrete 2 +// create hadnles and settings for uart, tim, rs with _modbus_ name +#define CONCAT(a,b) a##b +#define Create_MODBUS_Handles(_modbus_) \ + UART_SettingsTypeDef CONCAT(_modbus_, _suart); \ + UART_HandleTypeDef CONCAT(_modbus_, _huart); \ + TIM_SettingsTypeDef CONCAT(_modbus_, _stim); \ + TIM_HandleTypeDef CONCAT(_modbus_, _htim); \ + RS_HandleTypeDef CONCAT(h, _modbus_) +//-------------------------------------------------- +/** GENERAL_MODBUS_STUFF + * @} + */ +////////////////////---MODBUS MESSAGE DEFINES---///////////////////// + + + +///////////////////////////////////////////////////////////////////// +/////////////////////////---FUNCTIONS---///////////////////////////// +/** + * @addtogroup MODBUS_FUNCTIONS + * @ingroup MODBUS + * @brief Function for controling modbus communication + */ + +//----------------FUNCTIONS FOR USER---------------- +/** + * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS + * @ingroup MODBUS_FUNCTIONS + * @brief Function for user use + @{ + */ +/* First set up of MODBUS */ +void MODBUS_FirstInit(void); +/* Set or Reset Coil at its global address */ +MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal); +/* Read Coil at its global address */ +uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); + +/** MODBUS_DATA_ACCESS_FUNCTIONS + * @} + */ + +//---------PROCESS MODBUS COMMAND FUNCTIONS--------- +/** + * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS + * @ingroup MODBUS_FUNCTIONS + * @brief Function process commands + @{ + */ +/* Check is address valid for certain array */ +MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB); +/* Define Address Origin for Input/Holding Registers */ +MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType); +/* Define Address Origin for coils */ +MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag); +/* Proccess command Read Coils (01 - 0x01) */ +uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg); +/* Proccess command Read Holding Registers (03 - 0x03) */ +uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); +/* Proccess command Read Input Registers (04 - 0x04) */ +uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); +/* Proccess command Write Single Coils (05 - 0x05) */ +uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg); +/* Proccess command Write Multiple Coils (15 - 0x0F) */ +uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); +/* Proccess command Write Multiple Register (16 - 0x10) */ +uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); + +/** MODBUS_DATA_ACCESS_FUNCTIONS + * @} + */ +/////////////////////////---FUNCTIONS---///////////////////////////// + + + +///////////////////////////////////////////////////////////////////// +/////////////////////////---CALC DEFINES---////////////////////////// + + +// TRACES DEFINES +#ifndef Trace_MB_UART_Enter +#define Trace_MB_UART_Enter() +#endif //Trace_MB_UART_Enter + +#ifndef Trace_MB_UART_Exit +#define Trace_MB_UART_Exit() +#endif //Trace_MB_UART_Exit + +#ifndef Trace_MB_TIM_Enter +#define Trace_MB_TIM_Enter() +#endif //Trace_MB_TIM_Enter + +#ifndef Trace_MB_TIM_Exit +#define Trace_MB_TIM_Exit() +#endif //Trace_MB_TIM_Exit + +#endif //__MODBUS_H_ diff --git a/diode_tester/Core/Interfaces/modbus_data.h b/diode_tester/Core/Interfaces/modbus_data.h new file mode 100644 index 0000000..5744cd7 --- /dev/null +++ b/diode_tester/Core/Interfaces/modbus_data.h @@ -0,0 +1,163 @@ +/** +************************************************************************** +* @file modbus_data.h +* @brief Заголовочный файл с описанием даты MODBUS. +* @details Данный файл необходимо подключается в rs_message.h. После rs_message.h +* подключается к основному проекту. +* +* @defgroup MODBUS_DATA +* @ingroup MODBUS +* @brief Modbus data description +* +*************************************************************************/ + +#ifndef _MODBUS_DATA_H_ +#define _MODBUS_DATA_H_ + +#include "stdint.h" +//--------------DEFINES FOR REGISTERS--------------- +// DEFINES FOR ARRAYS +/** + * @addtogroup MODBUS_DATA_RERISTERS_DEFINES + * @ingroup MODBUS_DATA + * @brief Defines for registers + Структура дефайна адресов + @verbatim + Для массивов регистров: + R__ADDR - модбас адресс первого регистра в массиве + R__QNT - количество регистров в массиве + + @endverbatim + * @{ + */ + + +/** + * @brief Регистры хранения + */ +typedef struct //MB_DataInRegsTypeDef +{ + unsigned DUMMY; +}MB_DataInRegsTypeDef; + + +/** + * @brief Входные регистры + */ +typedef struct //MB_DataInRegsTypeDef +{ + unsigned DUMMY; +}MB_DataHoldRegsTypeDef; + + +// DEFINES FOR INPUT REGISTERS ARRAYS +#define R_TE_VOLTAGE_ADDR 0 +#define R_TE_VOLTAGE_QNT 85 + +#define R_STATUS_REG_ADDR 85 +#define R_STATUS_REG_QNT 1 + +// DEFINES FOR HOLDING REGISTERS ARRAYS +#define R_SETPOINTS_ADDR 0 +#define R_SETPOINTS_QNT 170 + +#define R_SETTINGS_ADDR 170 +#define R_SETTINGS_QNT 5 + + +// DEFINES FOR REGISTERS LOCAL ADDRESSES +//#define R_SET_ERROR(_te_num_) 0 + + +/** MODBUS_DATA_RERISTERS_DEFINES + * @} + */ + +//----------------DEFINES FOR COILS----------------- +/** + * @addtogroup MODBUS_DATA_COILS_DEFINES + * @ingroup MODBUS_DATA + * @brief Defines for coils + @verbatim + Структура дефайна + Для массивов коилов: + C__ADDR - модбас адресс первого коила в массиве + C__QNT - количество коилов в массиве (минимум 16) + + @endverbatim + * @{ + */ + + + +/** + * @brief Коилы + */ +typedef struct //MB_DataCoilsTypeDef +{ + unsigned DUMMY; +}MB_DataCoilsTypeDef; + +// DEFINES FOR COIL ARRAYS +#define C_TE_EXCLUDE_ADDR 0 +#define C_TE_EXCLUDE_QNT 85 + +/** MODBUS_DATA_COILS_DEFINES + * @} + */ + + +//-----------MODBUS DEVICE DATA SETTING------------- +// MODBUS DATA STRUCTTURE +/** + * @brief Структура со всеми регистрами и коилами модбас + * @ingroup MODBUS_DATA + */ +typedef struct // tester modbus data +{ + MB_DataInRegsTypeDef InRegs; ///< Modbus input registers @ref MB_DataInRegsTypeDef + + MB_DataCoilsTypeDef Coils; ///< Modbus coils @ref MB_DataCoilsTypeDef + + MB_DataHoldRegsTypeDef HoldRegs; ///< Modbus holding registers @ref MB_DataHoldRegsTypeDef +}MB_DataStructureTypeDef; +extern MB_DataStructureTypeDef MB_DATA; + + + +#endif //_MODBUS_DATA_H_ + +///////////////////////////////////////////////////////////// +///////////////////////TEMP/OUTDATE/OTHER//////////////////// + +//typedef enum //MB_TESTERCommandsTypeDef +//{ +// StandartMode = 0x00, ///< Стандартная работа +// Opros_TE_Disable = 0x01, ///< Запрет опроса ТЭ (активен только обмен с ЛСУ ЭС, ТЭ не контролируются) +//}MB_TESTERCommandsTypeDef; + +///** +// * @brief Состояние МЗКТЭ +// */ +//typedef enum //MB_TESTERErrStatusTypeDef +//{ +// TESTER_OK = 0x0, ///< МЗКТЭ функционирует нормально. Идет опрос ТЭ. +// NonCritical_Err = 0x1, ///< Неисправность МЗКТЭ, при которой МЗКТЭ может выполнять свои основные функции (некоторые программные ошибки из @ref MB_TESTERTrackerTypeDef). +// Critical_Err = 0x2, ///< Неисправность МЗКТЭ, при которой выполнение основных функций не представляется возможным (ошибки 1-3 и некоторые программные ошибки из @ref MB_TESTERTrackerTypeDef) +// +//}MB_TESTERErrStatusTypeDef; +//typedef enum +//{ +// TE_No_Err = 0x0, ///< Напряжения на всех ТЭ выше аварийных порогов, задаваемых уставками «Авария» +// TE_Err = 0x1, ///< Напряжение на одном или нескольких ТЭ достигло или ниже аварийного порога, задаваемого уставкой «Авария» +//}MB_TEErrActiveTypeDef; +//typedef enum +//{ +// TE_No_Warn = 0x0, ///< Напряжения на всех ТЭ выше предупредительных порогов, задаваемых уставкой «Предупреждение» +// TE_Warn = 0x1, ///< Напряжение на одном или нескольких ТЭ достигло или ниже предупредительного порога, задаваемого уставкой «Предупреждение» +//}MB_TEWarnActiveTypeDef; +//typedef enum +//{ +// OprosTE_Enable = 0x0, ///< Опрос ТЭ разрешен +// OprosTE_Disable = 0x1, ///< Опрос ТЭ запрещен (см. регистр хранения 170) +//}MB_OprosTETypeDef; diff --git a/diode_tester/Core/Interfaces/rs_message.c b/diode_tester/Core/Interfaces/rs_message.c new file mode 100644 index 0000000..0b4f3fb --- /dev/null +++ b/diode_tester/Core/Interfaces/rs_message.c @@ -0,0 +1,580 @@ +/** +************************************************************************** +* @file rs_message.c +* @brief Модуль для реализации протоколов по RS/UART. +************************************************************************** + @verbatim + //-------------------Функции-------------------// + Functions: users + - RS_Parse_Message/RS_Collect_Message Заполнение структуры сообщения и буфера + - RS_Response Ответ на сообщение + - RS_Define_Size_of_RX_Message Определение размера принимаемых данных + + Functions: general + - RS_Receive_IT Ожидание комманды и ответ на неё + - RS_Transmit_IT Отправление комманды и ожидание ответа + - RS_Init Инициализация переферии и структуры для RS + - RS_ReInit_UART Реинициализация UART для RS + - RS_Abort Отмена приема/передачи по ЮАРТ + - RS_Init Инициализация периферии и modbus handler + + Functions: callback/handler + - RS_Handle_Receive_Start Функция для запуска приема или остановки RS + - RS_Handle_Transmit_Start Функция для запуска передачи или остановки RS + + - RS_UART_RxCpltCallback Коллбек при окончании приема или передачи + RS_UART_TxCpltCallback + + - RS_UART_Handler Обработчик прерывания для UART + - RS_TIM_Handler Обработчик прерывания для TIM + + Functions: uart initialize (это было в отдельных файлах, мб надо обратно разнести) + - UART_Base_Init Инициализация UART для RS + - RS_UART_GPIO_Init Инициализация GPIO для RS + - UART_DMA_Init Инициализация DMA для RS + - UART_MspInit Аналог HAL_MspInit для RS + - UART_MspDeInit Аналог HAL_MspDeInit для RS + + @endverbatim +*************************************************************************/ +#include "rs_message.h" + +uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer + +#ifndef INCLUDE_GENERAL_PERIPH_LIBS +extern void RS_UART_Init(void); +extern void RS_UART_DeInit(UART_HandleTypeDef *huart); +extern void RS_TIM_Init(void); +extern void RS_TIM_DeInit(TIM_HandleTypeDef *htim); +#endif + +//------------------------------------------------------------------- +//-------------------------GENERAL FUNCTIONS------------------------- +/** + * @brief Start receive IT. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о состоянии RS после инициализации приема. + */ +RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) +{ + RS_StatusTypeDef RS_RES = 0; + HAL_StatusTypeDef uart_res = 0; + + //-------------CHECK RS LINE---------------- + // check that receive isnt busy + if( RS_Is_RX_Busy(hRS) ) // if tx busy - return busy status + return RS_BUSY; + + //-----------INITIALIZE RECEIVE------------- + // if all OK: start receiving + RS_EnableReceive(); + RS_Set_Busy(hRS); // set RS busy + RS_Set_RX_Flags(hRS); // initialize flags for receive + hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions + + // start receiving + uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, RX_FIRST_PART_SIZE); // receive until ByteCnt+1 byte, + // then in Callback restart receive for rest bytes + + // if receive isnt started - abort RS + if(uart_res != HAL_OK) + { + RS_RES = RS_Abort(hRS, ABORT_RS); + printf_rs_err("\n%d: Error RS: Failed to start RS receiving...", uwTick); + TrackerCnt_Err(hRS->rs_err); + } + else + { + RS_RES = RS_OK; + printf_rs("\n%d: RS: Start Receiving...", uwTick); + TrackerCnt_Ok(hRS->rs_err); + } + + hRS->RS_STATUS = RS_RES; + return RS_RES; // returns result of receive init +} + +/** + * @brief Start transmit IT. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о состоянии RS после инициализации передачи. + */ +RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) +{ + RS_StatusTypeDef RS_RES = 0; + HAL_StatusTypeDef uart_res = 0; + + //-------------CHECK RS LINE---------------- + // check that transmit isnt busy + if( RS_Is_TX_Busy(hRS) ) // if tx busy - return busy status + return RS_BUSY; + // check receive line + + + //------------COLLECT MESSAGE--------------- + RS_RES = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr); + if (RS_RES != RS_OK) // if message isnt collect - stop RS and return error in RS_RES + {// need collect message status, so doesnt write abort to RS_RES + RS_Abort(hRS, ABORT_RS); + RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); // restart receive + } + else // if collect successful + { + + //----------INITIALIZE TRANSMIT------------- + RS_EnableTransmit(); +// for(int i = 0; i < hRS->sRS_Timeout; i++); + + RS_Set_Busy(hRS); // set RS busy + RS_Set_TX_Flags(hRS); // initialize flags for transmit IT + hRS->pMessagePtr = RS_msg; // set pointer for filling given structure from UARTHandler fucntion + + // if all OK: start transmitting + uart_res = HAL_UART_Transmit_IT(hRS->huart, hRS->pBufferPtr, hRS->RS_Message_Size); + // if transmit isnt started - abort RS + if(uart_res != HAL_OK) + { + RS_RES = RS_Abort(hRS, ABORT_RS); + printf_rs_err("\n%d: Error RS: Failed to start RS transmitting...", uwTick); + TrackerCnt_Err(hRS->rs_err); + } + else + { + RS_RES = RS_OK; + printf_rs("\n%d: RS: Start Transmitting...", uwTick); + TrackerCnt_Ok(hRS->rs_err); + } + } + + + hRS->RS_STATUS = RS_RES; + return RS_RES; // returns result of transmit init +} + +/** + * @brief Initialize UART and handle RS stucture. + * @param hRS - указатель на хендлер RS. + * @param suart - указатель на структуру с настройками UART. + * @param stim - указатель на структуру с настройками таймера. + * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. + * @return RS_RES - статус о состоянии RS после инициализации. + * @note Инициализация перефирии и структуры для приема-передачи по RS. + */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr) +#else +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr) +#endif +{ + // check that hRS is defined + if (hRS == NULL) + return RS_ERR; +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check that huart is defined + if ((suart->huart.Instance == NULL) || (suart->huart.Init.BaudRate == NULL)) + return RS_ERR; +#else + // check that huart is defined + if (huart == NULL) + return RS_ERR; +#endif + // init uart + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + UART_Base_Init(suart); + hRS->huart = &suart->huart; +#else + RS_UART_Init(); + hRS->huart = huart; +#endif + + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check that timeout in interrupt needed + if (hRS->sRS_Timeout) + { + if (stim->htim.Instance == NULL) // check is timer defined + return RS_ERR; + + // calc frequency corresponding to timeout and tims 1ms tickbase + stim->sTickBaseUS = TIM_TickBase_1MS; + stim->htim.Init.Period = hRS->sRS_Timeout; + + TIM_Base_Init(stim); + hRS->htim = &stim->htim; + } +#else + RS_TIM_Init(); + hRS->htim = htim; +#endif + + if (hRS->sRS_RX_Size_Mode == NULL) + return RS_ERR; + + // check that buffer is defined + if (hRS->pBufferPtr == NULL) + { + hRS->pBufferPtr = RS_Buffer; // if no - set default + } + else + hRS->pBufferPtr = pRS_BufferPtr; // if yes - set by user + + return RS_OK; +} + +/** + * @brief ReInitialize UART and RS receive. + * @param hRS - указатель на хендлер RS. + * @param suart - указатель на структуру с настройками UART. + * @return RS_RES - статус о состоянии RS после инициализации. + * @note Реинициализация UART и приема по RS. + */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart) +#else +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart) +#endif +{ + HAL_StatusTypeDef RS_RES; + hRS->f.ReInit_UART = 0; + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + // check is settings are valid + if(Check_UART_Init_Struct(suart) != HAL_OK) + return HAL_ERROR; + + RS_Abort(hRS, ABORT_RS); + + UART_MspDeInit(&suart->huart); + + RS_RES = UART_Base_Init(suart); + + RS_RES = RS_UART_Init() + +#else +// // check is settings are valid +// if(Check_UART_Init_Struct(suart) != HAL_OK) +// return HAL_ERROR; + + RS_Abort(hRS, ABORT_RS); + + RS_UART_DeInit(huart); + + RS_UART_Init(); + +#endif + + RS_Receive_IT(hRS, hRS->pMessagePtr); + return RS_RES; +} + + +/** + * @brief Abort RS/UART. + * @param hRS - указатель на хендлер RS. + * @param AbortMode - выбор, что надо отменить. + - ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX, + - ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX, + - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, + - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. + * @return RS_RES - статус о состоянии RS после аборта. + * @note Отмена работы UART в целом или отмена приема/передачи RS. + Также очищается хендл hRS. + */ +RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) +{ + HAL_StatusTypeDef uart_res = 0; + hRS->htim->Instance->CNT = 0; + __HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE); + + if(hRS->sRS_Timeout) // if timeout setted + HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout + + if((AbortMode&ABORT_RS) == 0x00) + { + if((AbortMode&ABORT_RX) == ABORT_RX) + { + uart_res = HAL_UART_AbortReceive(hRS->huart); // abort receive + RS_Reset_RX_Flags(hRS); + } + + if((AbortMode&ABORT_TX) == ABORT_TX) + { + uart_res = HAL_UART_AbortTransmit(hRS->huart); // abort transmit + RS_Reset_TX_Flags(hRS); + } + } + else + { + uart_res = HAL_UART_Abort(hRS->huart); + RS_Clear_All(hRS); + } + hRS->RS_STATUS = RS_ABORTED; + return RS_ABORTED; +} + + +//-------------------------GENERAL FUNCTIONS------------------------- +//------------------------------------------------------------------- + + + +//------------------------------------------------------------------- +//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- +/** + * @brief Handle for starting receive. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о состоянии RS после инициализации приема или окончания общения. + * @note Определяет начинать прием команды/ответа или нет. + */ +RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) +{ + RS_StatusTypeDef RS_RES = 0; + + switch(hRS->sRS_Mode) + { + case SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting + RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again + case SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request) + RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy) + } + + if(RS_RES != RS_OK) + { + TrackerCnt_Err(hRS->rs_err); + } + + return RS_RES; +} +/** + * @brief Handle for starting transmit. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о состоянии RS после инициализации передачи. + * @note Определяет отвечать ли на команду или нет. + */ +RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) +{ + RS_StatusTypeDef RS_RES = 0; + + switch(hRS->sRS_Mode) + { + case SLAVE_ALWAYS_WAIT: // in slave mode always response + case SLAVE_TIMEOUT_WAIT: // transmit response + RS_RES = RS_Transmit_IT(hRS, RS_msg); break; + } + if(RS_RES != RS_OK) + { + TrackerCnt_Err(hRS->rs_err); + } + + return RS_RES; +} + +/** + * @brief UART RX Callback: define behaviour after receiving parts of message. + * @param hRS - указатель на хендлер RS. + * @return RS_RES - статус о состоянии RS после обработки приема. + * @note Контролирует прием сообщения: определяет размер принимаемой посылки и обрабатывает его. + */ +RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS) +{ + RS_StatusTypeDef RS_RES = 0; + HAL_StatusTypeDef uart_res = 0; + + // if we had received bytes before ByteCnt + if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and + { // First receive part of message, then define size of rest of message, and start receive it + hRS->f.RX_Half = 1; + //---------------FIND DATA SIZE----------------- + uint32_t NuRS_of_Rest_Bytes = 0; + RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes); + + + // if there is no bytes to receive OR we need to skip this message - restart receive + if ((NuRS_of_Rest_Bytes == 0) || (RS_RES == RS_SKIP)) + { + TrackerCnt_Err(hRS->rs_err); + RS_Abort(hRS, ABORT_RX); + RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); + return RS_RES; + } + + //-------------START UART RECEIVE--------------- + uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes); + + if(uart_res != HAL_OK) + {// need uart status, so doesnt write abort to RS_RES + TrackerCnt_Err(hRS->rs_err); + RS_RES = RS_Abort(hRS, ABORT_RS); + } + else + RS_RES = RS_OK; + } + else // if we had received whole message + { + hRS->f.RX_Half = 0; + + //---------PROCESS DATA & ENDING RECEIVING-------- + RS_Set_RX_End(hRS); + + if(hRS->sRS_Timeout) // if timeout setted + HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout + + // parse received data + RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message + + // RESPONSE + RS_RES = RS_Response(hRS, hRS->pMessagePtr); + } + + return RS_RES; +} + + +/** + * @brief UART TX Callback: define behaviour after transmiting message. + * @param hRS - указатель на хендлер RS. + * @return RS_RES - статус о состоянии RS после обработки приема. + * @note Определяет поведение RS после передачи сообщения. + */ +RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS) +{ + RS_StatusTypeDef RS_RES = RS_OK; + HAL_StatusTypeDef uart_res = 0; + + //--------------ENDING TRANSMITTING------------- + RS_Set_TX_End(hRS); + RS_EnableReceive(); +// for(int i = 0; i < hRS->sRS_Timeout; i++); + + //-----------START RECEIVING or END RS---------- + RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); + + return RS_RES; +} + +/** + * @brief Handler for UART. + * @param hRS - указатель на хендлер RS. + * @note Обрабатывает ошибки если есть и вызывает RS Коллбеки. + * Добавить вызов этой функции в UARTx_IRQHandler(). + */ +void RS_UART_Handler(RS_HandleTypeDef *hRS) +{ + HAL_UART_IRQHandler(hRS->huart); + //-------------CALL RS CALLBACKS------------ + /* IF NO ERROR OCCURS */ + if(hRS->huart->ErrorCode == 0) + { + hRS->htim->Instance->CNT = 0; // reset cnt; + /* Start timeout */ + if(hRS->sRS_Timeout) // if timeout setted + if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active + { + HAL_TIM_Base_Start_IT(hRS->htim); + RS_Set_RX_Active_Flags(hRS); + } + + /* RX Callback */ + if (( hRS->huart->RxXferCount == 0U) && RS_Is_RX_Busy(hRS) && // if all bytes are received and receive is active + hRS->huart->RxState != HAL_UART_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy + RS_UART_RxCpltCallback(hRS); + + /* TX Callback */ + if (( hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active + hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy + RS_UART_TxCpltCallback(hRS); + } + //----------------ERRORS HANDLER---------------- + else + { + TrackerCnt_Err(hRS->rs_err); + /* de-init uart transfer */ + RS_Abort(hRS, ABORT_RS); + RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); + + // later, maybe, will be added specific handlers for err + } +} + + +/** + * @brief Handler for TIM. + * @param hRS - указатель на хендлер RS. + * @note Попадание сюда = таймаут и перезапуск RS приема + * Добавить вызов этой функции в TIMx_IRQHandler(). + */ +void RS_TIM_Handler(RS_HandleTypeDef *hRS) +{ + HAL_TIM_IRQHandler(hRS->htim); + HAL_TIM_Base_Stop_IT(hRS->htim); + RS_Abort(hRS, ABORT_RS); + + RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); +} +//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- +//------------------------------------------------------------------- + + + +//------------------------------------------------------------------- +//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- +/** + * @brief Respond accord to received message. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о результате ответа на комманду. + * @note Обработка принятой комманды и ответ на неё. + */ +__weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) +{ + /* Redefine function for user purposes */ + return RS_ERR; +} + +/** + * @brief Collect message in buffer to transmit it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения буфера. + * @note Заполнение буффера UART из структуры сообщения. + */ +__weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) +{ + /* Redefine function for user purposes */ + return RS_ERR; +} + +/** + * @brief Parse message from buffer to process it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения структуры. + * @note Заполнение структуры сообщения из буффера UART. + */ +__weak RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) +{ + /* Redefine function for user purposes */ + return RS_ERR; +} + +/** + * @brief Define size of RX Message that need to be received. + * @param hRS - указатель на хендлер RS. + * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. + * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. + * @note Определение сколько байтов надо принять по протоколу. + */ +__weak RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) +{ + /* Redefine function for user purposes */ + return RS_ERR; +} +//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- +//------------------------------------------------------------------- diff --git a/diode_tester/Core/Interfaces/rs_message.h b/diode_tester/Core/Interfaces/rs_message.h new file mode 100644 index 0000000..a3d525d --- /dev/null +++ b/diode_tester/Core/Interfaces/rs_message.h @@ -0,0 +1,265 @@ +/** +************************************************************************** +* @file rs_message.h +* @brief Заголовочный файл для модуля реализации протоколов по RS/UART. +************************************************************************** +* @defgroup RS_TOOLS +* @brief Всякое для работы по UART/RS +************************************************************************** +@details +************************************************************************** +Для настройки RS/UART под нужный протокол, необходимо: + - Определить структуру сообщения RS_MsgTypeDef и + дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX. + - Подключить этот файл в раздел rs_message.h. + - Определить функции для обработки сообщения: RS_Parse_Message(), + RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message() + - Добавить UART/TIM Handler в Хендлер используемых UART/TIM. + +Так же данный модуль использует счетчики +************************************************************************** +@verbatim +Визуальное описание. Форматирование сохраняется как в коде. +@endverbatim +*************************************************************************/ +#ifndef __RS_LIB_H_ +#define __RS_LIB_H_ + +#include "modbus.h" + +#include "mylibs_include.h" +#include "crc_algs.h" + + +///////////////////////////////////////////////////////////////////// +////////////////////////////---DEFINES---//////////////////////////// +/* Check that all defines required by RS are defined */ +#ifndef MSG_SIZE_MAX +#error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART. +#endif + +#ifndef RX_FIRST_PART_SIZE +#error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message. +#endif + + +/* Clear message-uart buffer */ +#define RS_Clear_Buff(_buff_) for(int i=0; if.RS_Busy = 0 +#define RS_Set_Busy(_hRS_) _hRS_->f.RS_Busy = 1 + +#define RS_Set_RX_Flags(_hRS_) _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 +#define RS_Set_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 1 + + +#define RS_Set_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0 + +#define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0 +#define RS_Reset_RX_Flags(_hRS_) RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 +#define RS_Reset_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0 + +#define RS_Set_RX_End_Flag(_hRS_) _hRS_->f.RX_Done = 1; +#define RS_Set_TX_End_Flag(_hRS_) _hRS_->f.TX_Done = 1 + +#define RS_Set_RX_End(_hRS_) RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_) +#define RS_Set_TX_End(_hRS_) RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_) + +/* Clear all RS stuff */ +#define RS_Clear_All(_hRS_) RS_Clear_Buff(_hRS_->pBufferPtr); RS_Reset_RX_Flags(_hRS_); RS_Reset_TX_Flags(_hRS_); + +//#define MB_Is_RX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX) +//#define MB_Is_TX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX) +#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1) +#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1) + + +#ifndef RS_EnableReceive +#define RS_EnableReceive() +#endif +#ifndef RS_EnableTransmit +#define RS_EnableTransmit() +#endif +////////////////////////////---DEFINES---//////////////////////////// + + + +///////////////////////////////////////////////////////////////////// +///////////////////////---STRUCTURES & ENUMS---////////////////////// +//------------------ENUMERATIONS-------------------- +/** @brief Enums for respond CMD about RS status */ +typedef enum // RS_StatusTypeDef +{ + /* IN-CODE STATUS (start from 0x01, and goes up)*/ + /*0x01*/ RS_OK = 0x01, + /*0x02*/ RS_ERR, + /*0x03*/ RS_ABORTED, + /*0x04*/ RS_BUSY, + /*0x05*/ RS_SKIP, + + /*0x06*/ RS_COLLECT_MSG_ERR, + /*0x07*/ RS_PARSE_MSG_ERR, + + // reserved values +// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) +}RS_StatusTypeDef; + + +/** @brief Enums for RS Modes */ +typedef enum // RS_ModeTypeDef +{ + SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting + SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout +// MASTER = 0x03, ///< Master mode +}RS_ModeTypeDef; + +/** @brief Enums for RS UART Modes */ +typedef enum // RS_ITModeTypeDef +{ + BLCK_MODE = 0x00, ///< Blocking mode + IT_MODE = 0x01, ///< Interrupt mode +}RS_ITModeTypeDef; + +/** @brief Enums for Abort modes */ +typedef enum // RS_AbortTypeDef +{ + ABORT_TX = 0x01, ///< Abort transmit + ABORT_RX = 0x02, ///< Abort receive + ABORT_RX_TX = 0x03, ///< Abort receive and transmit + ABORT_RS = 0x04, ///< Abort uart and reset RS structure +}RS_AbortTypeDef; + +/** @brief Enums for RX Size modes */ +typedef enum // RS_RXSizeTypeDef +{ + RS_RX_Size_Const = 0x01, ///< size of receiving message is constant + RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant +}RS_RXSizeTypeDef; + + +//-----------STRUCTURE FOR HANDLE RS------------ +/** @brief Struct for flags RS */ +typedef struct +{ + unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt + + unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy + unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data + + unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active + unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active + + unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done + unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done + + // setted by user + unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet + unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg + unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt + unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing +}RS_FlagsTypeDef; + + + +/** + * @brief Handle for RS communication. + * @note Prefixes: h - handle, s - settings, f - flag + */ +typedef struct // RS_HandleTypeDef +{ + /* MESSAGE */ + uint8_t ID; ///< ID of RS "channel" + RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct + uint8_t *pBufferPtr; ///< pointer to message buffer + uint32_t RS_Message_Size; ///< size of whole message, not only data + + /* HANDLERS and SETTINGS */ + UART_HandleTypeDef *huart; ///< handler for used uart + TIM_HandleTypeDef *htim; ///< handler for used tim + RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef + RS_ITModeTypeDef sRS_IT_Mode; ///< setting: 1 - IT mode, 0 - Blocking mode + uint16_t sRS_Timeout; ///< setting: timeout in ms + RS_RXSizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const + + /* FLAGS */ + RS_FlagsTypeDef f; ///< These flags for controling receive/transmit + + /* RS STATUS */ + RS_StatusTypeDef RS_STATUS; ///< RS status + RS_TrackerTypeDef rs_err; +}RS_HandleTypeDef; +extern RS_HandleTypeDef hmodbus1; + + +///////////////////////---STRUCTURES & ENUMS---////////////////////// + + +///////////////////////////////////////////////////////////////////// +///////////////////////////---FUNCTIONS---/////////////////////////// +//----------------FUNCTIONS FOR PROCESSING MESSAGE------------------- +/*--------------------Defined by users purposes--------------------*/ +/* Respond accord to received message */ +RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); + +/* Collect message in buffer to transmit it */ +RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); + +/* Parse message from buffer to process it */ +RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); + +/* Define size of RX Message that need to be received */ +RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size); + + +//-------------------------GENERAL FUNCTIONS------------------------- +/*-----------------Should be called from main code-----------------*/ +/* Start receive IT */ +RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); + +/* Start transmit IT */ +RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); + +/* Initialize UART and handle RS stucture */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr); +#else +RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr); +#endif +/* ReInitialize UART and RS receive */ +#ifdef INCLUDE_GENERAL_PERIPH_LIBS +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart); +#else +HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart); +#endif +/* Abort RS/UART */ +RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode); +//-------------------------GENERAL FUNCTIONS------------------------- + + +//------------------------------------------------------------------- +//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- +/* Handle for starting receive */ +RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); +/* Handle for starting transmit */ +RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); +/* UART RX Callback: define behaviour after receiving parts of message */ +RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS); +/* UART TX Callback: define behaviour after transmiting message */ +RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS); +/* Handler for UART */ +void RS_UART_Handler(RS_HandleTypeDef *hRS); +/* Handler for TIM */ +void RS_TIM_Handler(RS_HandleTypeDef *hRS); +//--------------------CALLBACK/HANDLER FUNCTIONS--------------------- +///////////////////////////---FUNCTIONS---/////////////////////////// + + +#ifndef printf_rs_err +#define printf_rs_err(...) +#endif + +#ifndef printf_rs +#define printf_rs(...) +#endif +#endif // __RS_LIB_H_ diff --git a/diode_tester/Core/MyLibs/bit_access.h b/diode_tester/Core/MyLibs/bit_access.h new file mode 100644 index 0000000..081983c --- /dev/null +++ b/diode_tester/Core/MyLibs/bit_access.h @@ -0,0 +1,249 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup BIT_ACCESS_DEFINES Bit access defines +* @ingroup MYLIBS_DEFINES +* @brief Всякое для доступа к битам в unsigned +*************************************************************************/ +#ifndef __BIT_ACCESS_H_ +#define __BIT_ACCESS_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup BIT_ACCESS_TYPEDEF Byte access typedefs + * @ingroup BIT_ACCESS_DEFINES + * @brief Дефайны юнионов для обращения к битам. + @{ + */ +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned reserved:4; + }bit; +}uint4_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned reserved:3; + }bit; +}uint5_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned reserved:2; + }bit; +}uint6_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned reserved:1; + }bit; +}uint7_BitTypeDef; + +typedef union +{ + uint8_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + }bit; +}uint8_BitTypeDef; + +typedef union +{ + uint16_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + }bit; +}uint16_BitTypeDef; + + +typedef union +{ + uint32_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + unsigned bit16:1; + unsigned bit17:1; + unsigned bit18:1; + unsigned bit19:1; + unsigned bit20:1; + unsigned bit21:1; + unsigned bit22:1; + unsigned bit23:1; + unsigned bit24:1; + unsigned bit25:1; + unsigned bit26:1; + unsigned bit27:1; + unsigned bit28:1; + unsigned bit29:1; + unsigned bit30:1; + unsigned bit31:1; + }bit; +}uint32_BitTypeDef; + + +typedef union +{ + uint64_t all; + struct + { + unsigned bit0:1; + unsigned bit1:1; + unsigned bit2:1; + unsigned bit3:1; + unsigned bit4:1; + unsigned bit5:1; + unsigned bit6:1; + unsigned bit7:1; + unsigned bit8:1; + unsigned bit9:1; + unsigned bit10:1; + unsigned bit11:1; + unsigned bit12:1; + unsigned bit13:1; + unsigned bit14:1; + unsigned bit15:1; + unsigned bit16:1; + unsigned bit17:1; + unsigned bit18:1; + unsigned bit19:1; + unsigned bit20:1; + unsigned bit21:1; + unsigned bit22:1; + unsigned bit23:1; + unsigned bit24:1; + unsigned bit25:1; + unsigned bit26:1; + unsigned bit27:1; + unsigned bit28:1; + unsigned bit29:1; + unsigned bit30:1; + unsigned bit31:1; + unsigned bit32:1; + unsigned bit33:1; + unsigned bit34:1; + unsigned bit35:1; + unsigned bit36:1; + unsigned bit37:1; + unsigned bit38:1; + unsigned bit39:1; + unsigned bit40:1; + unsigned bit41:1; + unsigned bit42:1; + unsigned bit43:1; + unsigned bit44:1; + unsigned bit45:1; + unsigned bit46:1; + unsigned bit47:1; + unsigned bit48:1; + unsigned bit49:1; + unsigned bit50:1; + unsigned bit51:1; + unsigned bit52:1; + unsigned bit53:1; + unsigned bit54:1; + unsigned bit55:1; + unsigned bit56:1; + unsigned bit57:1; + unsigned bit58:1; + unsigned bit59:1; + unsigned bit60:1; + unsigned bit61:1; + unsigned bit62:1; + unsigned bit63:1; + }bit; +}uint64_BitTypeDef; +/** BIT_ACCESS_TYPEDEF + * @} + */ + +/** + * @addtogroup BIT_ACCESS_FUNCTIONS Byte access functions + * @ingroup BIT_ACCESS_DEFINES + * @brief Дефайны для обращения к битам в unsigned. + @{ + */ +#define uint8_bit(_uint8_, _bit_) (*(uint8_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint16_bit(_uint8_, _bit_) (*(uint16_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint32_bit(_uint8_, _bit_) (*(uint32_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ +#define uint64_bit(_uint8_, _bit_) (*(uint64_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_ + +/** BIT_ACCESS_FUNCTIONS + * @} + */ +#endif //__BIT_ACCESS_H_ \ No newline at end of file diff --git a/diode_tester/Core/MyLibs/mylibs_config.h b/diode_tester/Core/MyLibs/mylibs_config.h new file mode 100644 index 0000000..d62fb78 --- /dev/null +++ b/diode_tester/Core/MyLibs/mylibs_config.h @@ -0,0 +1,36 @@ +/** +************************************************************************** +* @file mylibs_config.h +* @brief Конфигурации для библиотек MyLibs +************************************************************************** +* @defgroup MYLIBS_CONFIG Configs My Libs +* @ingroup MYLIBS_ALL +* @brief Конфигурации для библиотек MyLibs +@{ +*************************************************************************/ +#ifndef __MYLIBS_CONFIG_H_ +#define __MYLIBS_CONFIG_H_ + +#include "stm32f1xx_hal.h" + +// user includes +#include "interface_config.h" +#include "tester_config.h" + + +#define RS_USER_VARS_NUMB 0 +#define ADC_USER_VARS_NUMB 0 +#define ADC_CH_USER_VARS_NUMB 0 + + +#define INCLUDE_BIT_ACCESS_LIB +#define INCLUDE_TRACKERS_LIB +#define INCLUDE_TRACE_LIB +//#define INCLUDE_GENERAL_PERIPH_LIBS +//#define FREERTOS_DELAY + + +/** MYLIBS_CONFIG + * @} + */ +#endif //__MYLIBS_CONFIG_H_ \ No newline at end of file diff --git a/diode_tester/Core/MyLibs/mylibs_defs.h b/diode_tester/Core/MyLibs/mylibs_defs.h new file mode 100644 index 0000000..1e54b68 --- /dev/null +++ b/diode_tester/Core/MyLibs/mylibs_defs.h @@ -0,0 +1,106 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup MYLIBS_DEFINES My Libs defines +* @brief Базовые дефайны для всего проекта +* +*************************************************************************/ +#ifndef __MYLIBS_DEFINES_H_ +#define __MYLIBS_DEFINES_H_ + +#include "stm32f1xx_hal.h" +#include "mylibs_config.h" + +/*************************************************************************** +******************************ERROR_HANDLER********************************/ +/** + * @addtogroup ERROR_HANDLER_DEFINES Error Handler defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для определения функции обработки ошибок + @{ + */ + +/* extern Error_Handler from main.h */ +extern void Error_Handler(void); + +/* Define error handler for MyLibs */ +#define MyLibs_Error_Handler(_params_) Error_Handler(_params_) +/* If error handler not defined - set void */ +#ifndef MyLibs_Error_Handler +#define ((void)0U) +#endif // MyLibs_Error_Handler + +/** ERROR_HANDLER_DEFINES + * @} + */ + + +/*************************************************************************** +********************************ACCESS_DEFINES*****************************/ + +#define ClearStruct(_struct_) memset(&(_struct_), 0, sizeof(_struct_)) + + + +/*************************************************************************** +******************************DELAYS_DEFINES*******************************/ +/** + * @addtogroup DELAYS_DEFINES Delays defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для реализации задержек + @{ + */ + +#ifdef FREERTOS_DELAY + #define msDelay(_ms_) osDelay(_ms_) +#else + #define msDelay(_ms_) HAL_Delay(_ms_) +#endif + +/** DELAYS_DEFINES + * @} + */ + + +/*************************************************************************** +*******************************MATH_DEFINES********************************/ +/** + * @addtogroup MATH_DEFINES Math defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для различных математических функций + @{ + */ + +/** + * @brief Calc dividing including remainder + * @param _val_ - делимое. + * @param _div_ - делитель. + * @details Если результат деления без остатка: он возвращается как есть + Если с остатком - округляется вверх + */ +//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */ +#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */ + +/** + * @brief Swap between Little Endian and Big Endian + * @param v - Переменная для свапа. + * @return v (new) - Свапнутая переменная. + * @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты. + */ +#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8))) + +/** + * @brief Absolute + * @param x - Переменная для модудя. + * @return x (new) - Число по модулю. + * @details Берет число по модулю. Хз как работает библиотечный abs в stdlib.h, мб это быстрее, но вряд ли конечно. + */ +#define ABS(x) ( ((x) > 0)? (x) : -(x))? + +/** MATH_DEFINES + * @} + */ + +#endif //__MYLIBS_DEFINES_H_ \ No newline at end of file diff --git a/diode_tester/Core/MyLibs/mylibs_include.h b/diode_tester/Core/MyLibs/mylibs_include.h new file mode 100644 index 0000000..4404540 --- /dev/null +++ b/diode_tester/Core/MyLibs/mylibs_include.h @@ -0,0 +1,79 @@ +/** +************************************************************************** +* @file mylibs_include.h +* @brief Заголочный файл для всех библиотек +************************************************************************** +@details +Здесь нужно собрать библиотеки и дефайны, которые должны быть видны во всем проекте, +чтобы не подключать 100 инклюдов в каждом ".c" файле +************************************************************************** +* @defgroup MYLIBS_ALL My Libs +* @brief Все используемые MyLibs библиотеки +* +*************************************************************************/ +#ifndef __MYLIBS_INCLUDE_H_ +#define __MYLIBS_INCLUDE_H_ + +#include "mylibs_defs.h" + + +#ifdef ARM_MATH_CM4 + #include "arm_math.h" +#endif + + +#ifdef INCLUDE_BIT_ACCESS_LIB +#include "bit_access.h" +#endif + +#ifdef INCLUDE_TRACKERS_LIB +#include "trackers.h" +#endif + +#ifdef INCLUDE_TRACE_LIB +#include "trace.h" +#endif + + + +#ifdef INCLUDE_GENERAL_PERIPH_LIBS + +#include "general_flash.h" +#include "general_gpio.h" +#ifdef HAL_SPI_MODULE_ENABLED +#include "general_spi.h" +#endif +#ifdef HAL_UART_MODULE_ENABLED +#include "general_uart.h" +#endif +#ifdef HAL_TIM_MODULE_ENABLED +#include "general_tim.h" +#endif + +#endif //INCLUDE_GENERAL_PERIPH_LIBS + + + + +/////////////////////////---USER SETTINGS---///////////////////////// +// user includes +#include "stdlib.h" +#include "string.h" +#include "stdio.h" +#include "math.h" + +#include "main.h" +#include "modbus_data.h" + +/** @brief Struct for trackers for Measure */ +/** @brief Struct for trackers for RS */ +typedef TrackerTypeDef(RS_USER_VARS_NUMB) RS_TrackerTypeDef; +/** @brief Struct for trackers for ADC */ +typedef TrackerTypeDef(ADC_USER_VARS_NUMB) ADC_TrackerTypeDef; +/** @brief Struct for trackers for ADC Channel */ +typedef TrackerTypeDef(ADC_CH_USER_VARS_NUMB) ADCChannel_TrackerTypeDef; +/////////////////////////---USER SETTINGS---///////////////////////// + + +#endif // __MYLIBS_INCLUDE_H_ + diff --git a/diode_tester/Core/MyLibs/trace.h b/diode_tester/Core/MyLibs/trace.h new file mode 100644 index 0000000..0b4a87e --- /dev/null +++ b/diode_tester/Core/MyLibs/trace.h @@ -0,0 +1,80 @@ +/** +************************************************************************** +* @file trace.h +* @brief Заголочный файл для работы с трассировкой. +************************************************************************** +* @addtogroup TRACE Trace defines +* @ingroup MYLIBS_DEFINES +* @brief Дефайны для работы с трассировкой +*************************************************************************/ +#ifndef __TRACE_H_ +#define __TRACE_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup TRACE_SERIAL Serial trace defines + * @ingroup TRACE + * @brief Дефайны для работы с serial трассировкой + * @details Определяется дефайн my_printf() для работы с serial трассировкой: + - для RTT это будет вызов функции SEGGER_RTT_printf(), с подключением библиотеки SEGGER_RTT.h + - для SWO это будет просто printf(), но библиотеку STDOUT надо подключить самостоятельно: + + @verbatim + Manage Run-Time Environment -> Compiler -> I/O -> STDOUT + @endverbatim + + - Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют + @{ + */ +/* Выбор какой serial trace использовать */ +#ifdef SERIAL_TRACE_ENABLE + + #if defined(RTT_TRACE_ENABLE) + #undef SWO_TRACE_ENABLE + #include "SEGGER_RTT.h" + #define my_printf(...) SEGGER_RTT_printf(0, __VA_ARGS__) + #elif defined(SWO_TRACE_ENABLE) + #undef RTT_TRACE_ENABLE + #define my_printf(...) printf(__VA_ARGS__) + #else // NO_TRACE + #define my_printf(...) + #warning No trace is selected. Serial debug wont work. + #endif // RTT_TRACE_ENABLE/SWO_TRACE_ENABLE/NO_TRACE +#else //SERIAL_TRACE_ENABLE + #define my_printf(...) + #undef RTT_TRACE_ENABLE + #undef SWO_TRACE_ENABLE + +#endif //SERIAL_TRACE_ENABLE + +/** TRACE_SERIAL + * @} + */ + + +/** + * @addtogroup TRACE_GPIO GPIO trace defines + * @ingroup TRACE + * @brief Дефайны для работы с GPIO трассировкой + * @details Определяется дефайны для работы с GPIO трассировкой: + - TRACE_GPIO_RESET() - для сброса ножки GPIO (через BSRR) + - TRACE_GPIO_SET() - для выставления ножки GPIO (через BSRR) + + - Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют + @{ + */ +#ifndef GPIO_TRACE_ENABLE + #define TRACE_GPIO_RESET(_gpio_,_pin_) + #define TRACE_GPIO_SET(_gpio_,_pin_) +#else + #define TRACE_GPIO_RESET(_gpio_,_pin_) (_gpio_)->BSRR = ((_pin_)<<16) + #define TRACE_GPIO_SET(_gpio_,_pin_) (_gpio_)->BSRR = (((_pin_))) +#endif //GPIO_TRACE_ENABLE + + +/** TRACE_GPIO + * @} + */ + + +#endif //__TRACE_H_ \ No newline at end of file diff --git a/diode_tester/Core/MyLibs/trackers.h b/diode_tester/Core/MyLibs/trackers.h new file mode 100644 index 0000000..641d606 --- /dev/null +++ b/diode_tester/Core/MyLibs/trackers.h @@ -0,0 +1,141 @@ +/** +************************************************************************** +* @file mylibs_defs.h +* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral. +************************************************************************** +* @defgroup MYLIBS_DEFINES My Libs defines +* @brief Базовые дефайны для всего проекта +* +*************************************************************************/ +#ifndef __TRACKERS_H_ +#define __TRACKERS_H_ +#include "mylibs_defs.h" + +/** + * @addtogroup TRACKERS Trackers defines + * @ingroup MYLIBS_DEFINES + * @brief Дефайны для работы с трекерами + * @details Есть дефайн для объявления структуры трекера: TrackerTypeDef(num_user_vars). + Структура состоит из следующих элементов: + - cnt_ok + - cnt_err + - cnt_warn + - user[num_user_vars] + Также есть ряд функций (дефайнов) для обращения к элементам этой структуры. + + + Если трассировка отключена, то все дефайны определяются как ничего и на производительность кода не влияют + + @par Пример: + Определяем typedef трекера измерений @ref Measure_TrackerTypeDef + + @verbatim + typedef TrackerTypeDef(MEASURE_USER_VARS_NUMB) Measure_TrackerTypeDef; + @endverbatim + + И через @ref Measure_TrackerTypeDef структура подключается в @ref TESTER_MeasureHandleTypeDef, а также + если необхожимо в другие структуру, например в структуру всех ошибок через указатель @ref TESTER_TrackerTypeDef + + @{ + */ + +#ifdef TRACKERS_ENABLE + /** + * @brief Структура для счетчиков отладки + * @param num_user_vars - количество пользовательских счетчиков + * @details Содержит счетчик для успешных событый (cnt_ok), + * счетчик для ошибок (cnt_err), счетчик для предупреждений (cnt_warn). + * + * Также есть возможность объявить пользовательские счетчики в + * количестве штук. + * + * Для работы с структурой можно использовать функции: + * - TrackerCnt_Ok() + * - TrackerCnt_Err() + * - TrackerCnt_Warn() + * - TrackerCnt_User() + * - TrackerWrite_User() + * - TrackerClear_All() + * - TrackerClear_Ok() + * - TrackerClear_Err() + * - TrackerClear_Warn() + * - TrackerClear_User() + * - TrackerClear_UserAll() + */ + #define TrackerTypeDef(num_user_vars) \ + struct \ + { \ + uint32_t cnt_ok; \ + uint32_t cnt_err; \ + uint32_t cnt_warn; \ + uint32_t user[num_user_vars]; \ + } + + /** @brief Получить количетство пользовательских переменных */ + #define num_of_usercnts(_user_) (sizeof(_user_) / sizeof(_user_[0])) + /** @brief Проверка существует ли указанная пользовательская переменная */ + #define assert_usertracker(_cntstruct_, _uservarnumb_) ((_uservarnumb_) < num_of_usercnts((_cntstruct_).user)) + /** @brief Условие для проверки существует ли указанная пользовательская переменная */ + #define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(assert_usertracker(_cntstruct_, _uservarnumb_)) + /** @brief Тернарный оператор для проверки существует ли указанная пользовательская переменная */ + #define tern_assert_usertracker(_cntstruct_, _uservarnumb_) (assert_usertracker(_cntstruct_, _uservarnumb_)) ? _uservarnumb_ : 0 + + + + /** + * @brief Запись числа в пользовательскую переменную + * @note Здесь нет проверки - существует ли пользовательская переменная! + * Есть возможность выйти за границы структуры!!! + * Чтобы этого избежать используете дефайн #ref assert_usertracker() + */ + #define TrackerGet_User(_cntstruct_, _uservarnumb_) (_cntstruct_).user[tern_assert_usertracker(_cntstruct_, _uservarnumb_)] + + + + /** @brief Инкрементирование счетчика успешных событий */ + #define TrackerCnt_Ok(_cntstruct_) (_cntstruct_).cnt_ok++ + /** @brief Инкрементирование счетчика ошибок */ + #define TrackerCnt_Err(_cntstruct_) (_cntstruct_).cnt_err++ + /** @brief Инкрементирование счетчика предупреждений */ + #define TrackerCnt_Warn(_cntstruct_) (_cntstruct_).cnt_warn++ + /** @brief Инкрементирование пользовательской переменной */ + #define TrackerCnt_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_]++; + /** @brief Запись числа в пользовательскую переменную */ + #define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = (_val_) + + /** @brief Очистка всей структуры */ + #define TrackerClear_All(_cntstruct_) memset(&(_cntstruct_), 0, sizeof(_cntstruct_)) + /** @brief Очистка счетчика успешных событий */ + #define TrackerClear_Ok(_cntstruct_) (_cntstruct_).cnt_ok = 0 + /** @brief Очистка счетчика ошибок */ + #define TrackerClear_Err(_cntstruct_) (_cntstruct_).cnt_err = 0 + /** @brief Очистка счетчика предупреждений */ + #define TrackerClear_Warn(_cntstruct_) (_cntstruct_).cnt_warn = 0 + /** @brief Очистка пользовательской переменной */ + #define TrackerClear_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = 0; + /** @brief Очистка всех пользовательских переменных */ + #define TrackerClear_UserAll(_cntstruct_) memset(&(_cntstruct_).user, 0, sizeof((_cntstruct_).user)) + +#else //TRACKERS_ENABLE + #define TrackerTypeDef(num_user_vars) void * + + #define num_of_usercnts(_user_) + #define assert_tracecnt(_cntstruct_, _uservarnumb_) + + #define TrackerCnt_Ok(_cntstruct_) + #define TrackerCnt_Err(_cntstruct_) + #define TrackerCnt_Warn(_cntstruct_) + #define TrackerCnt_User(_cntstruct_, _uservarnumb_) + #define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) + + /** @brief Очистка всей структуры */ + #define TrackerClear_All(_cntstruct_) + #define TrackerClear_Ok(_cntstruct_) + #define TrackerClear_Err(_cntstruct_) + #define TrackerClear_Warn(_cntstruct_) + #define TrackerClear_User(_cntstruct_) + #define TrackerClear_UserAll(_cntstruct_) + +#endif //TRACKERS_ENABLE + +#endif //__TRACKERS_H_ \ No newline at end of file diff --git a/diode_tester/Core/Src/adc.c b/diode_tester/Core/Src/adc.c index b36ff28..2da8cda 100644 --- a/diode_tester/Core/Src/adc.c +++ b/diode_tester/Core/Src/adc.c @@ -45,9 +45,9 @@ void MX_ADC1_Init(void) */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; - hadc1.Init.ContinuousConvMode = DISABLE; + hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; - hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO; + hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) @@ -98,7 +98,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc1.Init.Mode = DMA_NORMAL; + hdma_adc1.Init.Mode = DMA_CIRCULAR; hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) { diff --git a/diode_tester/Core/Src/gpio.c b/diode_tester/Core/Src/gpio.c index 9520ebc..22e2660 100644 --- a/diode_tester/Core/Src/gpio.c +++ b/diode_tester/Core/Src/gpio.c @@ -42,10 +42,23 @@ void MX_GPIO_Init(void) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); + + /*Configure GPIO pin : PC13 */ + GPIO_InitStruct.Pin = GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + } /* USER CODE BEGIN 2 */ diff --git a/diode_tester/Core/Src/main.c b/diode_tester/Core/Src/main.c index 612fdbd..6fdddef 100644 --- a/diode_tester/Core/Src/main.c +++ b/diode_tester/Core/Src/main.c @@ -21,11 +21,13 @@ #include "adc.h" #include "dma.h" #include "tim.h" +#include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "rs_message.h" +#include "tester_adc_func.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -58,6 +60,10 @@ void SystemClock_Config(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ +int delay = 250; +int delay_en = 1; +int before_pulse_delay = 50; +int pulse_delay = 10; /* USER CODE END 0 */ /** @@ -92,14 +98,28 @@ int main(void) MX_DMA_Init(); MX_ADC1_Init(); MX_TIM3_Init(); + MX_USART1_UART_Init(); + MX_TIM2_Init(); /* USER CODE BEGIN 2 */ - +// HAL_ADC_Start_DMA(&hadc1, (uint32_t *)buff, ADC_BUFF_SIZE); +// HAL_TIM_Base_Start_IT(&htim3); + TESTER_ADC_StructInit(&tester_adc); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { + if(delay_en) + msDelay(delay); +// HAL_UART_Transmit(&huart1, (uint8_t *)"axaxa", 5, 100); + + ADC_DMA_StartRead(&tester_adc); + for(int i = 0; i < before_pulse_delay; i++); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1); + for(int i = 0; i < pulse_delay; i++); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0); + ADC_DMA_ReadWhileDMA(&tester_adc, 1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/diode_tester/Core/Src/stm32f1xx_it.c b/diode_tester/Core/Src/stm32f1xx_it.c index e9535f4..2d8fd52 100644 --- a/diode_tester/Core/Src/stm32f1xx_it.c +++ b/diode_tester/Core/Src/stm32f1xx_it.c @@ -22,6 +22,7 @@ #include "stm32f1xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "tester_adc_func.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -56,9 +57,12 @@ /* External variables --------------------------------------------------------*/ extern DMA_HandleTypeDef hdma_adc1; +extern TIM_HandleTypeDef htim2; extern TIM_HandleTypeDef htim3; +extern UART_HandleTypeDef huart1; /* USER CODE BEGIN EV */ + /* USER CODE END EV */ /******************************************************************************/ @@ -205,7 +209,7 @@ void SysTick_Handler(void) void DMA1_Channel1_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */ - + ADC_DMA_Handler(&tester_adc); /* USER CODE END DMA1_Channel1_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_adc1); /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */ @@ -213,13 +217,27 @@ void DMA1_Channel1_IRQHandler(void) /* USER CODE END DMA1_Channel1_IRQn 1 */ } +/** + * @brief This function handles TIM2 global interrupt. + */ +void TIM2_IRQHandler(void) +{ + /* USER CODE BEGIN TIM2_IRQn 0 */ + + /* USER CODE END TIM2_IRQn 0 */ + HAL_TIM_IRQHandler(&htim2); + /* USER CODE BEGIN TIM2_IRQn 1 */ + + /* USER CODE END TIM2_IRQn 1 */ +} + /** * @brief This function handles TIM3 global interrupt. */ void TIM3_IRQHandler(void) { /* USER CODE BEGIN TIM3_IRQn 0 */ - + HAL_NVIC_ClearPendingIRQ(TIM3_IRQn); /* USER CODE END TIM3_IRQn 0 */ HAL_TIM_IRQHandler(&htim3); /* USER CODE BEGIN TIM3_IRQn 1 */ @@ -227,6 +245,20 @@ void TIM3_IRQHandler(void) /* USER CODE END TIM3_IRQn 1 */ } +/** + * @brief This function handles USART1 global interrupt. + */ +void USART1_IRQHandler(void) +{ + /* USER CODE BEGIN USART1_IRQn 0 */ + + /* USER CODE END USART1_IRQn 0 */ + HAL_UART_IRQHandler(&huart1); + /* USER CODE BEGIN USART1_IRQn 1 */ + + /* USER CODE END USART1_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/diode_tester/Core/Src/tim.c b/diode_tester/Core/Src/tim.c index a48863d..4e9eae5 100644 --- a/diode_tester/Core/Src/tim.c +++ b/diode_tester/Core/Src/tim.c @@ -24,8 +24,49 @@ /* USER CODE END 0 */ +TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim3; +/* TIM2 init function */ +void MX_TIM2_Init(void) +{ + + /* USER CODE BEGIN TIM2_Init 0 */ + + /* USER CODE END TIM2_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + + /* USER CODE BEGIN TIM2_Init 1 */ + + /* USER CODE END TIM2_Init 1 */ + htim2.Instance = TIM2; + htim2.Init.Prescaler = 0; + htim2.Init.CounterMode = TIM_COUNTERMODE_UP; + htim2.Init.Period = 65535; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM2_Init 2 */ + + /* USER CODE END TIM2_Init 2 */ + +} /* TIM3 init function */ void MX_TIM3_Init(void) { @@ -70,7 +111,22 @@ void MX_TIM3_Init(void) void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { - if(tim_baseHandle->Instance==TIM3) + if(tim_baseHandle->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspInit 0 */ + + /* USER CODE END TIM2_MspInit 0 */ + /* TIM2 clock enable */ + __HAL_RCC_TIM2_CLK_ENABLE(); + + /* TIM2 interrupt Init */ + HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM2_IRQn); + /* USER CODE BEGIN TIM2_MspInit 1 */ + + /* USER CODE END TIM2_MspInit 1 */ + } + else if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspInit 0 */ @@ -90,7 +146,21 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) { - if(tim_baseHandle->Instance==TIM3) + if(tim_baseHandle->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspDeInit 0 */ + + /* USER CODE END TIM2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM2_CLK_DISABLE(); + + /* TIM2 interrupt Deinit */ + HAL_NVIC_DisableIRQ(TIM2_IRQn); + /* USER CODE BEGIN TIM2_MspDeInit 1 */ + + /* USER CODE END TIM2_MspDeInit 1 */ + } + else if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspDeInit 0 */ diff --git a/diode_tester/Core/Src/usart.c b/diode_tester/Core/Src/usart.c new file mode 100644 index 0000000..0c65d61 --- /dev/null +++ b/diode_tester/Core/Src/usart.c @@ -0,0 +1,122 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.c + * @brief This file provides code for the configuration + * of the USART instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "usart.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +UART_HandleTypeDef huart1; + +/* USART1 init function */ + +void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 115200; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ + +} + +void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(uartHandle->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspInit 0 */ + + /* USER CODE END USART1_MspInit 0 */ + /* USART1 clock enable */ + __HAL_RCC_USART1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspInit 1 */ + + /* USER CODE END USART1_MspInit 1 */ + } +} + +void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) +{ + + if(uartHandle->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspDeInit 0 */ + + /* USER CODE END USART1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART1_CLK_DISABLE(); + + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + + /* USART1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspDeInit 1 */ + + /* USER CODE END USART1_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/diode_tester/Core/Tester_main/tester_adc_func.c b/diode_tester/Core/Tester_main/tester_adc_func.c new file mode 100644 index 0000000..0324f4d --- /dev/null +++ b/diode_tester/Core/Tester_main/tester_adc_func.c @@ -0,0 +1,457 @@ +#include "tester_adc_func.h" +#include "adc.h" + +TESTER_ADCTypeDef tester_adc = {0}; + +uint16_t ADC_DMA_Buff[ADC_DMA_BUFF_SIZE]; +uint16_t ADC_DMA_HalfBuff[ADC_DMA_BUFF_SIZE/2]; + +void ADC_DMA_Handler(TESTER_ADCTypeDef *adc) +{ + int flag_parse_dma = 0; + int buff_start_ind = 0; + int buff_end_ind = 0; + + if(adc->f.dmaHandlerbusy) + return; + + + + adc->f.dmaHandlerbusy = 1; + __disable_irq(); + + if(DMA1->ISR & DMA_FLAG_HT1) + { + memcpy(ADC_DMA_HalfBuff, ADC_DMA_Buff, sizeof(ADC_DMA_HalfBuff)); + + adc->f.dmaBufferHalfDone = 1; + + buff_start_ind = 0; + buff_end_ind = ADC_BUFF_SIZE/2; + flag_parse_dma = 1; + } + else if (DMA1->ISR & DMA_FLAG_TC1) + { + memcpy(ADC_DMA_HalfBuff, (ADC_DMA_Buff+ADC_DMA_BUFF_SIZE/2), sizeof(ADC_DMA_HalfBuff)); + + + adc->f.dmaBufferHalfDone = 2; + + buff_start_ind = ADC_BUFF_SIZE/2; + buff_end_ind = ADC_BUFF_SIZE; + flag_parse_dma = 1; + } + else + { + flag_parse_dma = 0; + TrackerCnt_Warn(adc->adc_err); + } + + __enable_irq(); + if(adc->f.enable_dmaBuffTransfer && flag_parse_dma) + { + int dma_ind = 0; + for(int buff_ind = buff_start_ind; + buff_ind < buff_end_ind; + buff_ind++) + { + + + adc->chAdc.ADC_Buff[buff_ind] = ADC_DMA_HalfBuff[dma_ind]; + + dma_ind += 1; + } + + printf_adc_it("\n%d: ADC DMA IT Done %d-half", uwTick, adc->f.dmaBufferHalfDone); + adc->f.dmaHandlerbusy = 0; + TrackerCnt_Ok(adc->adc_err); + } + else + { + TrackerCnt_Warn(adc->adc_err); + } +} + + +void TESTER_ADC_StructInit(TESTER_ADCTypeDef *adc) +{ + ClearStruct(*adc); + adc->hadc = &hadc1; + adc->chAdc.pulse_width = 4; + adc->filter.array_size = FOSTER_STUDENT_N; + adc->chAdc.ChMask = ADC_MEASURE_CHANNEL_0; + +#ifdef FOSTER_STUDENT_USER_T_CRITICAL + adc->filter.t_critical = FOSTER_STUDENT_USER_T_CRITICAL; +#else + adc->filter.precise_table_ind = 2; +#endif +// adc->DMA_HalfBuff = ADC_DMA_HalfBuff; +// adc->DMA_Buff = ADC_DMA_Buff; +} + + +HAL_StatusTypeDef ADC_DMA_StartRead(TESTER_ADCTypeDef *adc) +{ + HAL_StatusTypeDef res; + + /* Очистка буферов каналов */ + ClearStruct(adc->chAdc.ADC_Buff); + + /* Очистка флага какая половина DMA уже готова */ + adc->f.dmaBufferHalfDone = 0; // никакая, данные DMA пока не готовы в принципе + + /* Разрешение заполнения буферов каналов */ + adc->f.enable_dmaBuffTransfer = 1; + /* Выставления флага, что АЦП работает */ + adc->f.adc_running = 1; + + printf_adc("\n%d: ADC DMA Start", uwTick); + + /* Старт АЦП с DMA */ + res = HAL_ADC_Start_DMA(adc->hadc, (uint32_t *)ADC_DMA_Buff, ADC_DMA_BUFF_SIZE); + + /* Если старт неудачен - запрет заполнения буферов каналов */ + if(res != HAL_OK) + { + adc->f.enable_dmaBuffTransfer = 0; + adc->f.adc_running = 0; + } + + return res; +} + +HAL_StatusTypeDef ADC_DMA_StopRead(TESTER_ADCTypeDef *adc) +{ + HAL_StatusTypeDef res; + if(adc->f.adc_running) + { + /* Остановка АЦП */ + res = HAL_ADC_Stop_DMA(adc->hadc); + + /* Очищение флагов АЦП */ + adc->f.adc_running = 0; + adc->f.enable_dmaBuffTransfer = 0; + adc->f.dmaHandlerbusy = 0; + + + printf_adc("\n%d: ADC DMA Stop", uwTick); + } + + return res; +} + +void ADC_DMA_Fuel_Cell_Reset(TESTER_ADCChannelTypeDef *adc_fc) +{ + adc_fc->ADC_Filtered = 0; + adc_fc->ADC_Max = 0; + adc_fc->ADC_Min = 0; + adc_fc->max_value_ind = 0; + adc_fc->state = 0; +} + +void ADC_DMA_Channels_Prepare(TESTER_ADCChannelTypeDef *adc_fuel_cells, uint8_t MaskForChannels, uint8_t state) +{ + for(int i = 0; i < 4; i++) + { + if(MaskForChannels&(1<ADC_Buff[ind]; +// uint16_t min = adc_fc->ADC_Buff[ind]; +// +// int16_t d_sum = 0; +// uint32_t t; +// +// uint16_t arr_size; +// if(ind < Filter->array_size) +// return 0xFF; +// +// for(int i = ind; i > ind - Filter->array_size; i--) +// { +// +// if(adc_fc->ADC_Buff[i] > max) +// { +// max = adc_fc->ADC_Buff[i]; +// m = 1; +// } +// else +// m = 0; +// if(adc_fc->ADC_Buff[i] < min) +// { +// min = adc_fc->ADC_Buff[i]; +// l = 1; +// } +// else +// l = 0; +// d_sum += (m-l); +// } +// +//#define fixed_base 1000 +// if(d_sum < 0) +// d_sum = -d_sum; +// t = d_sum*fixed_base*fixed_base/FOSTER_STUDENT_MSE; +// +// Filter->t_current = t; +//#ifndef FOSTER_STUDENT_USER_T_CRITICAL +// Filter->t_critical = t_critical[Filter->precise_table_ind]; +//#endif //FOSTER_STUDENT_USER_T_CRITICAL +// +// +// if(Filter->t_current > Filter->t_critical) +// { +// res = 1; +// } +// else +// { +// res = 0; +// } +// +// +// +// return res; +//} + + +void ADC_DMA_WaitForStableVoltage(TESTER_ADCChannelTypeDef *adc_fc, TESTER_ADCFilterTypeDef *Filter, uint32_t ind) +{ +// if(FosterStudent(adc_fc, Filter, ind) == 0) +// { +// /* Сохраняем индекс еще стабильного напряжения */ +// adc_fc->stable_start_ind = ind - Filter->array_size/2; +// /* Переключение на стабильное напряжение найдено */ +// adc_fc->state = WAIT_FOR_DROP; +// } +} + + +void ADC_DMA_WaitForDropVoltage(TESTER_ADCChannelTypeDef *adc_fc, TESTER_ADCFilterTypeDef *Filter, uint32_t ind) +{ +// if(FosterStudent(adc_fc, Filter, ind) == 1) +// { +// /* Сохраняем индекс еще стабильного напряжения */ +// adc_fc->stable_end_ind = ind-Filter->array_size/2; +// /* Переключение на стабильное напряжение найдено */ +// adc_fc->state = STABLE_FOUND; +// } +} + +void ADC_DMA_CalcStabilized(TESTER_ADCChannelTypeDef *adc_fc) +{ + uint16_t tmp_val = 0; + uint32_t val_sum = 0; + + adc_fc->ADC_Max = 0; + adc_fc->ADC_Min = 0xFFFF; + + /* Просмотр стабильных значений в буфере */ + for(int i = 0; i < ADC_BUFF_SIZE; i++) + { + tmp_val = adc_fc->ADC_Buff[i]; + /* Обновление максимального значения */ + if(tmp_val > adc_fc->ADC_Max) + { + adc_fc->ADC_Max = tmp_val; + adc_fc->max_value_ind = i; + } + + /* Обновление минимального значения */ + if(tmp_val < adc_fc->ADC_Min) + { + adc_fc->ADC_Min = tmp_val; + } + + } + + + /* Расчет среднего значения в пике */ + for(int i = (adc_fc->max_value_ind - adc_fc->pulse_width)/2; i < (adc_fc->max_value_ind + adc_fc->pulse_width/2); i++) + { + tmp_val = adc_fc->ADC_Buff[i]; + /* Накопление значений для расчета среднего */ + val_sum += tmp_val; + } + adc_fc->ADC_Filtered = val_sum/(adc_fc->pulse_width); + +} + +void ADC_DMA_ProcessSingleBuffer(TESTER_ADCChannelTypeDef *adc_fc) +{ + +} + + +void ADC_DMA_ProcessBuffer(TESTER_ADCTypeDef *adc) +{ + ADC_DMA_ProcessSingleBuffer(&adc->chAdc); +} + +void ADC_DMA_BufferHandler(TESTER_ADCChannelTypeDef *adc_fc, TESTER_ADCFilterTypeDef *Filter, uint32_t ind) +{ +// switch(adc_fc->state) +// { +// /* Канал не проверяется */ +// case NOT_CHECKING: +// break; +// +// /* Пока на каналах не зарядится кондер */ +// case WAIT_FOR_STABLE: +//// ADC_DMA_WaitForStableVoltage(adc_fc, Filter, ind); +// break; +// +// /* Проверка пока на первом канале не начнет разряжаться кондер */ +// case WAIT_FOR_DROP: +//// ADC_DMA_WaitForDropVoltage(adc_fc, Filter, ind); +// break; +// +// /* Стабильное напряжение найдено */ +// case STABLE_FOUND: +// /* Стабильное напряжение НЕ найдено */ +// case STABLE_NOT_FOUND: +// /* Конец стабильного напряжения НЕ найден */ +// case DROP_NOT_FOUND: +// break; +// +// +// /* Если состояние неопределенное */ +// default: +// adc_fc->state = NOT_CHECKING; +// break; +// +// } +} + + +/** + * @brief Считывать АЦП до тех пор, пока буфер DMA не заполнится и не будет обработан + */ +HAL_StatusTypeDef ADC_DMA_ReadWhileDMA(TESTER_ADCTypeDef *adc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Проверка принятых параметров функции */ + if(adc == 0) + { + ADC_DMA_StopRead(adc); + + printf_adc_err("\n%d: Error ADC: Handle is NULL)", uwTick); + return HAL_ERROR; + } + if(Timeout == 0) + { + ADC_DMA_StopRead(adc); + + printf_adc_err("\n%d: Error ADC: Read timeout is NULL)", uwTick); + return HAL_ERROR; + } + + + int adc_buff_ind = 1; + uint16_t filter_halfend = ADC_BUFF_SIZE/2; + uint16_t filter_end = ADC_BUFF_SIZE; + uint8_t run_adc_check = 0; + uint8_t expected_dmaBufferHalf = 1; + + /* Обработка АЦП */ + while(1) + { + /* Проверка на таймаут */ + if(HAL_GetTick() - tickstart > Timeout) + { + ADC_DMA_StopRead(adc); + + printf_adc_err("\n%d: Error ADC: Stable Not Found (Timeout)", uwTick); + return HAL_TIMEOUT; + } + + + /* Запуск обработки данных из DMA буфера, когда они готовы */ + if( (expected_dmaBufferHalf == adc->f.dmaBufferHalfDone) && // Ожидаемая половина DMA буфера готова + (run_adc_check == 0)) // Обработка предыдущей половины не активна + { + run_adc_check = 1; + + if(adc->f.dmaBufferHalfDone == 1) + printf_adc_processing("\n%d: ADC Processing DMA start...", uwTick); + else if(adc->f.dmaBufferHalfDone == 2) + printf_adc_processing("\n%d: ADC Processing DMA 2-half start...", uwTick); + + } + + + /* Обработка буфера DMA */ + if(run_adc_check) + { + /* Вызов обработчиков буфера DMA для каждого канала, если он выбран */ + ADC_DMA_BufferHandler(&adc->chAdc, &adc->filter, adc_buff_ind); + + + + /* Переход на следующие во времени значения каналов АЦП */ + adc_buff_ind++; + /* если это первая половина DMA буфера */ + if(expected_dmaBufferHalf == 1) + { + if(adc_buff_ind > filter_halfend) // Проверка первой половины закончена + { + adc_buff_ind = filter_halfend; // Выставляем индекс на вторую половину + run_adc_check = 0; // Сбрасываем флаг проверки каналов + expected_dmaBufferHalf = 2; // Устанавливаем ожидание готовности второй половины данных DMA буфера + + printf_adc_processing("\n%d: ADC Processing 1-half DMA complete, wait for 2-half...", uwTick); + + } + } + /* если это вторая половина DMA буфера */ + else if(expected_dmaBufferHalf == 2) + { + /* Если АЦП работает - останавливаем его */ + // note: пока без кольцевого режима, если за один цикл буфера ничего не удалось словить, вряд ли далее что-то появиться?? + if(adc->f.adc_running) + { + ADC_DMA_StopRead(adc); + printf_adc_processing(": wait for processing complete..."); + } + + if(adc_buff_ind > filter_end) // Проверка первой половины закончена + { + adc_buff_ind = 0; // Выставляем индекс на первую половину + run_adc_check = 0; // Сбрасываем флаг проверки каналов + expected_dmaBufferHalf = 1; // Устанавливаем ожидание готовности первой половины данных DMA буфера + + printf_adc_processing("\n%d: ADC Processing DMA complete", uwTick); + break; + } + } + /* если это "никакая" половина DMA буфера */ + else + { /* Сброс всего */ + + printf_adc_err("\n%d: ADC Processing DMA unexcpected half", uwTick); + + adc_buff_ind = 0; + run_adc_check = 0; + expected_dmaBufferHalf = 1; + } + } + } + + ADC_DMA_CalcStabilized(&adc->chAdc); + + return HAL_OK; +} \ No newline at end of file diff --git a/diode_tester/Core/Tester_main/tester_adc_func.h b/diode_tester/Core/Tester_main/tester_adc_func.h new file mode 100644 index 0000000..9517168 --- /dev/null +++ b/diode_tester/Core/Tester_main/tester_adc_func.h @@ -0,0 +1,156 @@ +/** +************************************************************************** +* @file tester_func.h +* @brief Заголовочный файл для функций МЗКТ. +************************************************************************** +@details + +*************************************************************************/ + + +#ifndef _TESTER_ADC_FUNC_H_ +#define _TESTER_ADC_FUNC_H_ + +#include "mylibs_include.h" + +#define ADC_MEASURE_CHANNEL_0_Pos 0x00 +#define ADC_MEASURE_CHANNEL_1_Pos 0x01 +#define ADC_MEASURE_CHANNEL_2_Pos 0x02 +#define ADC_MEASURE_CHANNEL_3_Pos 0x03 + +#define ADC_MEASURE_CHANNEL_0 (0x01 << ADC_MEASURE_CHANNEL_0_Pos) +#define ADC_MEASURE_CHANNEL_1 (0x01 << ADC_MEASURE_CHANNEL_1_Pos) +#define ADC_MEASURE_CHANNEL_2 (0x01 << ADC_MEASURE_CHANNEL_2_Pos) +#define ADC_MEASURE_CHANNEL_3 (0x01 << ADC_MEASURE_CHANNEL_3_Pos) +#define ADC_CH_IGNORE NULL // должно быть NULL!!! + +#define Measure_Get_Channel(_chPtr_) (_chPtr_)->Tadc->chAdc +#define Measure_Get_Voltage(_chPtr_) ((_chPtr_)->Tadc->chAdc->U_Current) +#define Measure_Get_Zero(_chPtr_) ((_chPtr_)->Tadc->chAdc->refADC_zero) +#define Measure_Get_Calibr(_chPtr_) ((_chPtr_)->Tadc->chAdc->refADC_calibr) +#define Measure_Get_VoltStep(_chPtr_) ((_chPtr_)->Tadc->chAdc->refU_step) +#define Measure_Get_Filtered(_chPtr_) ((_chPtr_)->Tadc->chAdc->ADC_Filtered) + +#define Measure_Calc_CalibrDiff(_chPtr_) abs((int)Measure_Get_Calibr(_chPtr_) - Measure_Get_Zero(_chPtr_)) +#define Measure_Calc_FilterDiff(_chPtr_) abs((int)Measure_Get_Filtered(_chPtr_) - Measure_Get_Zero(_chPtr_)) +#define Measure_Calc_Voltage(_chPtr_) ((float)Measure_Calc_FilterDiff(_chPtr_)*Measure_Get_VoltStep(_chPtr_)) + +//#define ADC_GetChannel(_AdcChPtr_) (_AdcChPtr_)->Tadc->chAdc +////#define Measure_Get_Voltage(_AdcChPtr_) ((_AdcChPtr_)->Tadc->chAdc->U_Current) +////#define Measure_Get_Zero(_AdcChPtr_) ((_AdcChPtr_)->Tadc->chAdc->refADC_zero) +////#define Measure_Get_Calibr(_AdcChPtr_) ((_AdcChPtr_)->Tadc->chAdc->refADC_calibr) +////#define Measure_Get_VoltStep(_AdcChPtr_) ((_AdcChPtr_)->Tadc->chAdc->refU_step) +////#define Measure_Get_Filtered(_AdcChPtr_) ((_AdcChPtr_)->Tadc->chAdc->ADC_Filtered) + +//#define Channel_Calc_Diff(_AdcChPtr_, _value_) ((int)(_value_) - (_AdcChPtr_)->refADC_zero) +//#define Channel_Calc_CalibrValue(_AdcChPtr_) (abs(Channel_Calc_Diff((_AdcChPtr_), (_AdcChPtr_)->refADC_calibr)) ) +//#define Channel_Calc_AdcValue(_AdcChPtr_) (abs(Channel_Calc_Diff((_AdcChPtr_), (_AdcChPtr_)->ADC_Filtered)) ) +//#define Channel_Calc_Voltage(_AdcChPtr_) ((float)Channel_Calc_AdcValue(_AdcChPtr_)*(_AdcChPtr_)->refU_step) + +typedef uint16_t ADC_BuffTypeDef[ADC_BUFF_SIZE]; + +typedef enum +{ + ADC_DISABLED = 0, + WAIT_FOR_FIRST_HALF = 1, + PROCESSING_FIRST_HALF = 2, + WAIT_FOR_SECOND_HALF = 3, + PROCESSING_SECOND_HALF = 4, + ADC_DONE = 5, +}ADC_ChannelState; + + +typedef struct +{ + ADC_BuffTypeDef ADC_Buff; + uint16_t ADC_Filtered; + float U_Current; + + + + + /* Parameter for calc voltage */ + uint16_t refADC_zero; + uint16_t refADC_calibr; + float refU_step; + + uint16_t ADC_Max; + uint16_t ADC_Min; + + unsigned pulse_width; + unsigned max_value_ind; + + uint8_t ChMask; + ADC_ChannelState state; + + ADCChannel_TrackerTypeDef adc_ch_err; +}TESTER_ADCChannelTypeDef; + +typedef struct +{ + int32_t t_current; + int32_t t_critical; + +#ifdef FOSTER_STUDENT_USER_T_CRITICAL +#else + uint8_t precise_table_ind; +#endif + uint16_t array_size; + +}TESTER_ADCFilterTypeDef; + + +typedef struct +{ + TESTER_ADCChannelTypeDef chAdc; + + ADC_HandleTypeDef *hadc; + + TESTER_ADCFilterTypeDef filter; + + struct + { + + unsigned adc_running:1; + unsigned enable_dmaBuffTransfer:1; + unsigned dmaBufferHalfDone:2; + unsigned dmaHandlerbusy:1; + }f; + ADC_TrackerTypeDef adc_err; +}TESTER_ADCTypeDef; + + +extern TESTER_ADCTypeDef tester_adc; +extern uint16_t ADC_DMA_Buff[ADC_DMA_BUFF_SIZE]; +extern uint16_t ADC_DMA_HalfBuff[ADC_DMA_BUFF_SIZE/2]; + +void TESTER_ADC_StructInit(TESTER_ADCTypeDef *adc); + +void ADC_DMA_Handler(TESTER_ADCTypeDef *adc); + +void ADC_DMA_ProcessBuffer(TESTER_ADCTypeDef *adc); +void ADC_DMA_Channels_Prepare(TESTER_ADCChannelTypeDef *adc_fuel_cells, uint8_t MaskForChannels, uint8_t state); +HAL_StatusTypeDef ADC_DMA_StartRead(TESTER_ADCTypeDef *adc); +HAL_StatusTypeDef ADC_DMA_ReadWhileDMA(TESTER_ADCTypeDef *adc, uint32_t Timeout); + + +#ifndef printf_adc_result +#define printf_adc_result(...) +#endif +#ifndef printf_adc_processing +#define printf_adc_processing(...) +#endif + +#ifndef printf_adc_err +#define printf_adc_err(...) +#endif + +#ifndef printf_adc_it +#define printf_adc_it(...) +#endif + +#ifndef printf_adc +#define printf_adc(...) +#endif +#endif //_TESTER_ADC_FUNC_H_ + diff --git a/diode_tester/Core/Tester_main/tester_config.h b/diode_tester/Core/Tester_main/tester_config.h new file mode 100644 index 0000000..481a9e4 --- /dev/null +++ b/diode_tester/Core/Tester_main/tester_config.h @@ -0,0 +1,67 @@ +/** +************************************************************************** +* @file tester_config.h +* @brief Конфигурации для тестера диодов +************************************************************************** +* @defgroup TESTER_CONFIGS Configs for project +* @brief Конфигурации для тестера диодов +* @details +@{ +*************************************************************************/ +#ifndef _TESTER_CONFIG_H_ +#define _TESTER_CONFIG_H_ + + +/** + * @addtogroup TESTER_ADC_CONFIG Configs for ADC + * @ingroup TESTER_CONFIGS + * @brief Конфигурации для АЦП + @{ + */ + +#define ADC_BUFF_SIZE (500) ///< Размер буфера АЦП +#define ADC_DMA_BUFF_SIZE (ADC_BUFF_SIZE*4) ///< Размер буфера ДМА (4 канала) + +#define ADC_U_CALIBR ((float)1.1) ///< Напряжение, которое подается при калибровке + +#define ADC_READ_TIMEOUT_MS 20 ///< Таймаут на ожидание разрядки конденсатора +#define ADC_ZERO_WAIT_TIMEOUS_MS 100 ///< Таймаут на ожидание нуля (при калибровке) + +#define FOSTER_STUDENT_N 40 ///< Выборка для определения начала разрядки конденсатора +#define FOSTER_STUDENT_MSE 2561 /*!< @brief Среднеквадратическая ошибка для выборки размером FOSTER_STUDENT_N, умноженная на 1000 + @details Выражение для СКО: sqrt(2*ln(N) - 0,8456) + URL: https://old.stgau.ru/company/personal/user/7750/files/lib/%D0%A1%D1%82%D0%B0%D1%82%D0%B8%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5%20%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D1%8B%20%D0%BF%D1%80%D0%BE%D0%B3%D0%BD%D0%BE%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/%D0%9F%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%BA%D1%83%D0%BC_%D1%82%D0%B5%D0%BC%D0%B0%201.pdf + */ + +/** + * @brief Критическое значение Стьюдента + * @details Используется для определения разрядки конденсатора. + * Записывается в единицах*1000 + * @note Если закомментировать, то будет использоваться таблица указанная в @ref FOSTER_STUDENT_T_CRITICALS + с индексом, указанным в @ref precise_table_ind + */ +#define FOSTER_STUDENT_USER_T_CRITICAL 1600//2650//2500 +/** + * @brief Критическое значение Стьюдента для калибровки + * @details Используется для определения разрядки конденсатора при калибровке. + * Записывается в единицах*1000 + * @note Если закомментировать, то будет использоваться значение указанное в @ref FOSTER_STUDENT_USER_T_CRITICAL + */ +//#define FOSTER_STUDENT_USER_T_CRITICAL_CALIBR 2600//2650//2500 +/** + * @brief Таблица критических значений Стьюдента с разной погрешностью + * @details Используется для определения разрядки конденсатора при закомментированном + * @ref FOSTER_STUDENT_USER_T_CRITICAL + */ +#define FOSTER_STUDENT_T_CRITICALS {257, 688, 1328, 1729, 2093, 2539} +/** TESTER_ADC_CONFIG + * @} + */ + + +/** TESTER_CONFIGS + * @} + */ + +#endif //_TESTER_CONFIG_H_ + diff --git a/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h new file mode 100644 index 0000000..7fe76e3 --- /dev/null +++ b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h @@ -0,0 +1,915 @@ +/** + ****************************************************************************** + * @file stm32f1xx_hal_uart.h + * @author MCD Application Team + * @brief Header file of UART HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_UART_H +#define __STM32F1xx_HAL_UART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal_def.h" + +/** @addtogroup STM32F1xx_HAL_Driver + * @{ + */ + +/** @addtogroup UART + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Types UART Exported Types + * @{ + */ + +/** + * @brief UART Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the UART communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (16 * (huart->Init.BaudRate))) + - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 16) + 0.5 */ + + uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref UART_Word_Length */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref UART_Stop_Bits */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref UART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref UART_Mode */ + + uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled or disabled. + This parameter can be a value of @ref UART_Hardware_Flow_Control */ + + uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8). + This parameter can be a value of @ref UART_Over_Sampling. This feature is only available + on STM32F100xx family, so OverSampling parameter should always be set to 16. */ +} UART_InitTypeDef; + +/** + * @brief HAL UART State structures definition + * @note HAL UART State value is a combination of 2 different substates: gState and RxState. + * - gState contains UART state information related to global Handle management + * and also information related to Tx operations. + * gState value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : (Not Used) + * 10 : Timeout + * 11 : Error + * b5 Peripheral initialization status + * 0 : Reset (Peripheral not initialized) + * 1 : Init done (Peripheral initialized. HAL UART Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (Peripheral busy with some configuration or internal operations) + * b1 (not used) + * x : Should be set to 0 + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + * - RxState contains information related to Rx operations. + * RxState value coding follow below described bitmap : + * b7-b6 (not used) + * xx : Should be set to 00 + * b5 Peripheral initialization status + * 0 : Reset (Peripheral not initialized) + * 1 : Init done (Peripheral initialized) + * b4-b2 (not used) + * xxx : Should be set to 000 + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 (not used) + * x : Should be set to 0. + */ +typedef enum +{ + HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized + Value is allowed for gState and RxState */ + HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing + Not to be used for neither gState nor RxState. + Value is result of combination (Or) between gState and RxState values */ + HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_UART_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +} HAL_UART_StateTypeDef; + +/** + * @brief HAL UART Reception type definition + * @note HAL UART Reception type value aims to identify which type of Reception is ongoing. + * This parameter can be a value of @ref UART_Reception_Type_Values : + * HAL_UART_RECEPTION_STANDARD = 0x00U, + * HAL_UART_RECEPTION_TOIDLE = 0x01U, + */ +typedef uint32_t HAL_UART_RxTypeTypeDef; + +/** + * @brief HAL UART Rx Event type definition + * @note HAL UART Rx Event type value aims to identify which type of Event has occurred + * leading to call of the RxEvent callback. + * This parameter can be a value of @ref UART_RxEvent_Type_Values : + * HAL_UART_RXEVENT_TC = 0x00U, + * HAL_UART_RXEVENT_HT = 0x01U, + * HAL_UART_RXEVENT_IDLE = 0x02U, + */ +typedef uint32_t HAL_UART_RxEventTypeTypeDef; + +/** + * @brief UART handle Structure definition + */ +typedef struct __UART_HandleTypeDef +{ + USART_TypeDef *Instance; /*!< UART registers base address */ + + UART_InitTypeDef Init; /*!< UART communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< UART Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< UART Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ + + __IO HAL_UART_RxTypeTypeDef ReceptionType; /*!< Type of ongoing reception */ + + __IO HAL_UART_RxEventTypeTypeDef RxEventType; /*!< Type of Rx Event */ + + DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< UART Error code */ + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Half Complete Callback */ + void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Complete Callback */ + void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Half Complete Callback */ + void (* RxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Complete Callback */ + void (* ErrorCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Error Callback */ + void (* AbortCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Complete Callback */ + void (* AbortTransmitCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Transmit Complete Callback */ + void (* AbortReceiveCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Receive Complete Callback */ + void (* WakeupCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Wakeup Callback */ + void (* RxEventCallback)(struct __UART_HandleTypeDef *huart, uint16_t Pos); /*!< UART Reception Event Callback */ + + void (* MspInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp Init callback */ + void (* MspDeInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp DeInit callback */ +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +} UART_HandleTypeDef; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +/** + * @brief HAL UART Callback ID enumeration definition + */ +typedef enum +{ + HAL_UART_TX_HALFCOMPLETE_CB_ID = 0x00U, /*!< UART Tx Half Complete Callback ID */ + HAL_UART_TX_COMPLETE_CB_ID = 0x01U, /*!< UART Tx Complete Callback ID */ + HAL_UART_RX_HALFCOMPLETE_CB_ID = 0x02U, /*!< UART Rx Half Complete Callback ID */ + HAL_UART_RX_COMPLETE_CB_ID = 0x03U, /*!< UART Rx Complete Callback ID */ + HAL_UART_ERROR_CB_ID = 0x04U, /*!< UART Error Callback ID */ + HAL_UART_ABORT_COMPLETE_CB_ID = 0x05U, /*!< UART Abort Complete Callback ID */ + HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID = 0x06U, /*!< UART Abort Transmit Complete Callback ID */ + HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID = 0x07U, /*!< UART Abort Receive Complete Callback ID */ + HAL_UART_WAKEUP_CB_ID = 0x08U, /*!< UART Wakeup Callback ID */ + + HAL_UART_MSPINIT_CB_ID = 0x0BU, /*!< UART MspInit callback ID */ + HAL_UART_MSPDEINIT_CB_ID = 0x0CU /*!< UART MspDeInit callback ID */ + +} HAL_UART_CallbackIDTypeDef; + +/** + * @brief HAL UART Callback pointer definition + */ +typedef void (*pUART_CallbackTypeDef)(UART_HandleTypeDef *huart); /*!< pointer to an UART callback function */ +typedef void (*pUART_RxEventCallbackTypeDef)(struct __UART_HandleTypeDef *huart, uint16_t Pos); /*!< pointer to a UART Rx Event specific callback function */ + +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UART_Exported_Constants UART Exported Constants + * @{ + */ + +/** @defgroup UART_Error_Code UART Error Code + * @{ + */ +#define HAL_UART_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_UART_ERROR_PE 0x00000001U /*!< Parity error */ +#define HAL_UART_ERROR_NE 0x00000002U /*!< Noise error */ +#define HAL_UART_ERROR_FE 0x00000004U /*!< Frame error */ +#define HAL_UART_ERROR_ORE 0x00000008U /*!< Overrun error */ +#define HAL_UART_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +#define HAL_UART_ERROR_INVALID_CALLBACK 0x00000020U /*!< Invalid Callback error */ +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup UART_Word_Length UART Word Length + * @{ + */ +#define UART_WORDLENGTH_8B 0x00000000U +#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M) +/** + * @} + */ + +/** @defgroup UART_Stop_Bits UART Number of Stop Bits + * @{ + */ +#define UART_STOPBITS_1 0x00000000U +#define UART_STOPBITS_2 ((uint32_t)USART_CR2_STOP_1) +/** + * @} + */ + +/** @defgroup UART_Parity UART Parity + * @{ + */ +#define UART_PARITY_NONE 0x00000000U +#define UART_PARITY_EVEN ((uint32_t)USART_CR1_PCE) +#define UART_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) +/** + * @} + */ + +/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control + * @{ + */ +#define UART_HWCONTROL_NONE 0x00000000U +#define UART_HWCONTROL_RTS ((uint32_t)USART_CR3_RTSE) +#define UART_HWCONTROL_CTS ((uint32_t)USART_CR3_CTSE) +#define UART_HWCONTROL_RTS_CTS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE)) +/** + * @} + */ + +/** @defgroup UART_Mode UART Transfer Mode + * @{ + */ +#define UART_MODE_RX ((uint32_t)USART_CR1_RE) +#define UART_MODE_TX ((uint32_t)USART_CR1_TE) +#define UART_MODE_TX_RX ((uint32_t)(USART_CR1_TE | USART_CR1_RE)) +/** + * @} + */ + +/** @defgroup UART_State UART State + * @{ + */ +#define UART_STATE_DISABLE 0x00000000U +#define UART_STATE_ENABLE ((uint32_t)USART_CR1_UE) +/** + * @} + */ + +/** @defgroup UART_Over_Sampling UART Over Sampling + * @{ + */ +#define UART_OVERSAMPLING_16 0x00000000U +#if defined(USART_CR1_OVER8) +#define UART_OVERSAMPLING_8 ((uint32_t)USART_CR1_OVER8) +#endif /* USART_CR1_OVER8 */ +/** + * @} + */ + +/** @defgroup UART_LIN_Break_Detection_Length UART LIN Break Detection Length + * @{ + */ +#define UART_LINBREAKDETECTLENGTH_10B 0x00000000U +#define UART_LINBREAKDETECTLENGTH_11B ((uint32_t)USART_CR2_LBDL) +/** + * @} + */ + +/** @defgroup UART_WakeUp_functions UART Wakeup Functions + * @{ + */ +#define UART_WAKEUPMETHOD_IDLELINE 0x00000000U +#define UART_WAKEUPMETHOD_ADDRESSMARK ((uint32_t)USART_CR1_WAKE) +/** + * @} + */ + +/** @defgroup UART_Flags UART FLags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the SR register + * @{ + */ +#define UART_FLAG_CTS ((uint32_t)USART_SR_CTS) +#define UART_FLAG_LBD ((uint32_t)USART_SR_LBD) +#define UART_FLAG_TXE ((uint32_t)USART_SR_TXE) +#define UART_FLAG_TC ((uint32_t)USART_SR_TC) +#define UART_FLAG_RXNE ((uint32_t)USART_SR_RXNE) +#define UART_FLAG_IDLE ((uint32_t)USART_SR_IDLE) +#define UART_FLAG_ORE ((uint32_t)USART_SR_ORE) +#define UART_FLAG_NE ((uint32_t)USART_SR_NE) +#define UART_FLAG_FE ((uint32_t)USART_SR_FE) +#define UART_FLAG_PE ((uint32_t)USART_SR_PE) +/** + * @} + */ + +/** @defgroup UART_Interrupt_definition UART Interrupt Definitions + * Elements values convention: 0xY000XXXX + * - XXXX : Interrupt mask (16 bits) in the Y register + * - Y : Interrupt source register (2bits) + * - 0001: CR1 register + * - 0010: CR2 register + * - 0011: CR3 register + * @{ + */ + +#define UART_IT_PE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) +#define UART_IT_TXE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) +#define UART_IT_TC ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) +#define UART_IT_RXNE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) +#define UART_IT_IDLE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE)) + +#define UART_IT_LBD ((uint32_t)(UART_CR2_REG_INDEX << 28U | USART_CR2_LBDIE)) + +#define UART_IT_CTS ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_CTSIE)) +#define UART_IT_ERR ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_EIE)) +/** + * @} + */ + +/** @defgroup UART_Reception_Type_Values UART Reception type values + * @{ + */ +#define HAL_UART_RECEPTION_STANDARD (0x00000000U) /*!< Standard reception */ +#define HAL_UART_RECEPTION_TOIDLE (0x00000001U) /*!< Reception till completion or IDLE event */ +/** + * @} + */ + +/** @defgroup UART_RxEvent_Type_Values UART RxEvent type values + * @{ + */ +#define HAL_UART_RXEVENT_TC (0x00000000U) /*!< RxEvent linked to Transfer Complete event */ +#define HAL_UART_RXEVENT_HT (0x00000001U) /*!< RxEvent linked to Half Transfer event */ +#define HAL_UART_RXEVENT_IDLE (0x00000002U) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Macros UART Exported Macros + * @{ + */ + +/** @brief Reset UART handle gstate & RxState + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \ + } while(0U) +#endif /*USE_HAL_UART_REGISTER_CALLBACKS */ + +/** @brief Flushes the UART DR register + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + */ +#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR) + +/** @brief Checks whether the specified UART flag is set or not. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) + * @arg UART_FLAG_LBD: LIN Break detection flag + * @arg UART_FLAG_TXE: Transmit data register empty flag + * @arg UART_FLAG_TC: Transmission Complete flag + * @arg UART_FLAG_RXNE: Receive data register not empty flag + * @arg UART_FLAG_IDLE: Idle Line detection flag + * @arg UART_FLAG_ORE: Overrun Error flag + * @arg UART_FLAG_NE: Noise Error flag + * @arg UART_FLAG_FE: Framing Error flag + * @arg UART_FLAG_PE: Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** @brief Clears the specified UART pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5). + * @arg UART_FLAG_LBD: LIN Break detection flag. + * @arg UART_FLAG_TC: Transmission Complete flag. + * @arg UART_FLAG_RXNE: Receive data register not empty flag. + * + * @note PE (Parity error), FE (Framing error), NE (Noise error), ORE (Overrun + * error) and IDLE (Idle line detected) flags are cleared by software + * sequence: a read operation to USART_SR register followed by a read + * operation to USART_DR register. + * @note RXNE flag can be also cleared by a read to the USART_DR register. + * @note TC flag can be also cleared by software sequence: a read operation to + * USART_SR register followed by a write operation to USART_DR register. + * @note TXE flag is cleared only by a write to the USART_DR register. + * + * @retval None + */ +#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Clears the UART PE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR; \ + tmpreg = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg); \ + } while(0U) + +/** @brief Clears the UART FE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clears the UART NE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clears the UART ORE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clears the UART IDLE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Enable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __INTERRUPT__ specifies the UART interrupt source to enable. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg UART_IT_PE: Parity Error interrupt + * @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK))) + +/** @brief Disable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __INTERRUPT__ specifies the UART interrupt source to disable. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg UART_IT_PE: Parity Error interrupt + * @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK))) + +/** @brief Checks whether the specified UART interrupt source is enabled or not. + * @param __HANDLE__ specifies the UART Handle. + * UART Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __IT__ specifies the UART interrupt source to check. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg UART_IT_ERR: Error interrupt + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == UART_CR1_REG_INDEX)? (__HANDLE__)->Instance->CR1:(((((uint32_t)(__IT__)) >> 28U) == UART_CR2_REG_INDEX)? \ + (__HANDLE__)->Instance->CR2 : (__HANDLE__)->Instance->CR3)) & (((uint32_t)(__IT__)) & UART_IT_MASK)) + +/** @brief Enable CTS flow control + * @note This macro allows to enable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * The Handle Instance can be any USARTx (supporting the HW Flow control feature). + * It is used to select the USART peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \ + do{ \ + ATOMIC_SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \ + } while(0U) + +/** @brief Disable CTS flow control + * @note This macro allows to disable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * The Handle Instance can be any USARTx (supporting the HW Flow control feature). + * It is used to select the USART peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \ + do{ \ + ATOMIC_CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \ + } while(0U) + +/** @brief Enable RTS flow control + * This macro allows to enable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * The Handle Instance can be any USARTx (supporting the HW Flow control feature). + * It is used to select the USART peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \ + do{ \ + ATOMIC_SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \ + } while(0U) + +/** @brief Disable RTS flow control + * This macro allows to disable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * The Handle Instance can be any USARTx (supporting the HW Flow control feature). + * It is used to select the USART peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \ + do{ \ + ATOMIC_CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \ + } while(0U) +#if defined(USART_CR3_ONEBIT) + +/** @brief Macro to enable the UART's one bit sample method + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT) + +/** @brief Macro to disable the UART's one bit sample method + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3\ + &= (uint16_t)~((uint16_t)USART_CR3_ONEBIT)) +#endif /* UART_ONE_BIT_SAMPLE_Feature */ + +/** @brief Enable UART + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable UART + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UART_Exported_Functions + * @{ + */ + +/** @addtogroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength); +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod); +HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart); +void HAL_UART_MspInit(UART_HandleTypeDef *huart); +void HAL_UART_MspDeInit(UART_HandleTypeDef *huart); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID, + pUART_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_UART_RegisterRxEventCallback(UART_HandleTypeDef *huart, pUART_RxEventCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_UART_UnRegisterRxEventCallback(UART_HandleTypeDef *huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); + +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen, + uint32_t Timeout); +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); + +HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart); + +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart); + +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart); + +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart); +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_UART_StateTypeDef HAL_UART_GetState(const UART_HandleTypeDef *huart); +uint32_t HAL_UART_GetError(const UART_HandleTypeDef *huart); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup UART_Private_Constants UART Private Constants + * @{ + */ +/** @brief UART interruptions flag mask + * + */ +#define UART_IT_MASK 0x0000FFFFU + +#define UART_CR1_REG_INDEX 1U +#define UART_CR2_REG_INDEX 2U +#define UART_CR3_REG_INDEX 3U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UART_Private_Macros UART Private Macros + * @{ + */ +#define IS_UART_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B) || \ + ((LENGTH) == UART_WORDLENGTH_9B)) +#define IS_UART_LIN_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B)) +#define IS_UART_STOPBITS(STOPBITS) (((STOPBITS) == UART_STOPBITS_1) || \ + ((STOPBITS) == UART_STOPBITS_2)) +#define IS_UART_PARITY(PARITY) (((PARITY) == UART_PARITY_NONE) || \ + ((PARITY) == UART_PARITY_EVEN) || \ + ((PARITY) == UART_PARITY_ODD)) +#define IS_UART_HARDWARE_FLOW_CONTROL(CONTROL)\ + (((CONTROL) == UART_HWCONTROL_NONE) || \ + ((CONTROL) == UART_HWCONTROL_RTS) || \ + ((CONTROL) == UART_HWCONTROL_CTS) || \ + ((CONTROL) == UART_HWCONTROL_RTS_CTS)) +#define IS_UART_MODE(MODE) ((((MODE) & 0x0000FFF3U) == 0x00U) && ((MODE) != 0x00U)) +#define IS_UART_STATE(STATE) (((STATE) == UART_STATE_DISABLE) || \ + ((STATE) == UART_STATE_ENABLE)) +#if defined(USART_CR1_OVER8) +#define IS_UART_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16) || \ + ((SAMPLING) == UART_OVERSAMPLING_8)) +#endif /* USART_CR1_OVER8 */ +#define IS_UART_LIN_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16)) +#define IS_UART_LIN_BREAK_DETECT_LENGTH(LENGTH) (((LENGTH) == UART_LINBREAKDETECTLENGTH_10B) || \ + ((LENGTH) == UART_LINBREAKDETECTLENGTH_11B)) +#define IS_UART_WAKEUPMETHOD(WAKEUP) (((WAKEUP) == UART_WAKEUPMETHOD_IDLELINE) || \ + ((WAKEUP) == UART_WAKEUPMETHOD_ADDRESSMARK)) +#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) <= 4500000U) +#define IS_UART_ADDRESS(ADDRESS) ((ADDRESS) <= 0x0FU) + +#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_) (((_PCLK_)*25U)/(4U*(_BAUD_))) +#define UART_DIVMANT_SAMPLING16(_PCLK_, _BAUD_) (UART_DIV_SAMPLING16((_PCLK_), (_BAUD_))/100U) +#define UART_DIVFRAQ_SAMPLING16(_PCLK_, _BAUD_) ((((UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) * 100U)) * 16U)\ + + 50U) / 100U) +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */ +#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_) (((UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) << 4U) + \ + (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0xF0U)) + \ + (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0x0FU)) + +#define UART_DIV_SAMPLING8(_PCLK_, _BAUD_) (((_PCLK_)*25U)/(2U*(_BAUD_))) +#define UART_DIVMANT_SAMPLING8(_PCLK_, _BAUD_) (UART_DIV_SAMPLING8((_PCLK_), (_BAUD_))/100U) +#define UART_DIVFRAQ_SAMPLING8(_PCLK_, _BAUD_) ((((UART_DIV_SAMPLING8((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) * 100U)) * 8U)\ + + 50U) / 100U) +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + ((UART DIVFRAQ & 0xF8) << 1) + (UART DIVFRAQ & 0x07U) */ +#define UART_BRR_SAMPLING8(_PCLK_, _BAUD_) (((UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) << 4U) + \ + ((UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0xF8U) << 1U)) + \ + (UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0x07U)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup UART_Private_Functions UART Private Functions + * @{ + */ + +HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_UART_H */ + diff --git a/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h new file mode 100644 index 0000000..6d37061 --- /dev/null +++ b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h @@ -0,0 +1,2569 @@ +/** + ****************************************************************************** + * @file stm32f1xx_ll_usart.h + * @author MCD Application Team + * @brief Header file of USART LL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_LL_USART_H +#define __STM32F1xx_LL_USART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx.h" + +/** @addtogroup STM32F1xx_LL_Driver + * @{ + */ + +#if defined (USART1) || defined (USART2) || defined (USART3) || defined (UART4) || defined (UART5) + +/** @defgroup USART_LL USART + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup USART_LL_Private_Constants USART Private Constants + * @{ + */ + +/* Defines used for the bit position in the register and perform offsets*/ +#define USART_POSITION_GTPR_GT USART_GTPR_GT_Pos +/** + * @} + */ + +/* 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_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_USART_ReadReg function + * @{ + */ +#define LL_USART_SR_PE USART_SR_PE /*!< Parity error flag */ +#define LL_USART_SR_FE USART_SR_FE /*!< Framing error flag */ +#define LL_USART_SR_NE USART_SR_NE /*!< Noise detected flag */ +#define LL_USART_SR_ORE USART_SR_ORE /*!< Overrun error flag */ +#define LL_USART_SR_IDLE USART_SR_IDLE /*!< Idle line detected flag */ +#define LL_USART_SR_RXNE USART_SR_RXNE /*!< Read data register not empty flag */ +#define LL_USART_SR_TC USART_SR_TC /*!< Transmission complete flag */ +#define LL_USART_SR_TXE USART_SR_TXE /*!< Transmit data register empty flag */ +#define LL_USART_SR_LBD USART_SR_LBD /*!< LIN break detection flag */ +#define LL_USART_SR_CTS USART_SR_CTS /*!< CTS flag */ +/** + * @} + */ + +/** @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_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 */ +/** + * @} + */ + +/** @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_8B 0x00000000U /*!< 8 bits word length : Start bit, 8 data bits, n stop bits */ +#define LL_USART_DATAWIDTH_9B USART_CR1_M /*!< 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 */ +#if defined(USART_CR1_OVER8) +#define LL_USART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +#endif /* USART_OverSampling_Feature */ +/** + * @} + */ + +#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_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_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 */ +/** + * @} + */ + +/** + * @} + */ + +/* 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_100(__PERIPHCLK__, __BAUDRATE__) (((__PERIPHCLK__)*25)/(2*(__BAUDRATE__))) +#define __LL_USART_DIVMANT_SAMPLING8(__PERIPHCLK__, __BAUDRATE__) (__LL_USART_DIV_SAMPLING8_100((__PERIPHCLK__), (__BAUDRATE__))/100) +#define __LL_USART_DIVFRAQ_SAMPLING8(__PERIPHCLK__, __BAUDRATE__) (((__LL_USART_DIV_SAMPLING8_100((__PERIPHCLK__), (__BAUDRATE__)) - (__LL_USART_DIVMANT_SAMPLING8((__PERIPHCLK__), (__BAUDRATE__)) * 100)) * 8\ + + 50) / 100) +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + ((UART DIVFRAQ & 0xF8) << 1) + (UART DIVFRAQ & 0x07) */ +#define __LL_USART_DIV_SAMPLING8(__PERIPHCLK__, __BAUDRATE__) (((__LL_USART_DIVMANT_SAMPLING8((__PERIPHCLK__), (__BAUDRATE__)) << 4) + \ + ((__LL_USART_DIVFRAQ_SAMPLING8((__PERIPHCLK__), (__BAUDRATE__)) & 0xF8) << 1)) + \ + (__LL_USART_DIVFRAQ_SAMPLING8((__PERIPHCLK__), (__BAUDRATE__)) & 0x07)) + +/** + * @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_100(__PERIPHCLK__, __BAUDRATE__) (((__PERIPHCLK__)*25)/(4*(__BAUDRATE__))) +#define __LL_USART_DIVMANT_SAMPLING16(__PERIPHCLK__, __BAUDRATE__) (__LL_USART_DIV_SAMPLING16_100((__PERIPHCLK__), (__BAUDRATE__))/100) +#define __LL_USART_DIVFRAQ_SAMPLING16(__PERIPHCLK__, __BAUDRATE__) ((((__LL_USART_DIV_SAMPLING16_100((__PERIPHCLK__), (__BAUDRATE__)) - (__LL_USART_DIVMANT_SAMPLING16((__PERIPHCLK__), (__BAUDRATE__)) * 100)) * 16)\ + + 50) / 100) +/* USART BRR = mantissa + overflow + fraction + = (USART DIVMANT << 4) + (USART DIVFRAQ & 0xF0) + (USART DIVFRAQ & 0x0F) */ +#define __LL_USART_DIV_SAMPLING16(__PERIPHCLK__, __BAUDRATE__) (((__LL_USART_DIVMANT_SAMPLING16((__PERIPHCLK__), (__BAUDRATE__)) << 4) + \ + (__LL_USART_DIVFRAQ_SAMPLING16((__PERIPHCLK__), (__BAUDRATE__)) & 0xF0)) + \ + (__LL_USART_DIVFRAQ_SAMPLING16((__PERIPHCLK__), (__BAUDRATE__)) & 0x0F)) + +/** + * @} + */ + +/** + * @} + */ + +/* 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_SR 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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_UE) == (USART_CR1_UE)); +} + +/** + * @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(const 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(const 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(const 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 M LL_USART_SetDataWidth + * @param USARTx USART Instance + * @param DataWidth This parameter can be one of the following values: + * @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 M LL_USART_GetDataWidth + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + */ +__STATIC_INLINE uint32_t LL_USART_GetDataWidth(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_M)); +} + +#if defined(USART_CR1_OVER8) +/** + * @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(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_OVER8)); +} + +#endif /* USART_OverSampling_Feature */ +/** + * @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(const 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(const 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(const 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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR2, USART_CR2_CLKEN) == (USART_CR2_CLKEN)); +} + +/** + * @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(const 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 M 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_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 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. + * @rmtoll CR2 ADD LL_USART_SetNodeAddress + * @param USARTx USART Instance + * @param NodeAddress 4 bit Address of the USART node. + * @retval None + */ +__STATIC_INLINE void LL_USART_SetNodeAddress(USART_TypeDef *USARTx, uint32_t NodeAddress) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_ADD, (NodeAddress & USART_CR2_ADD)); +} + +/** + * @brief Return 4 bit Address of the USART node as set in ADD field of CR2. + * @note only 4bits (b3-b0) of returned value are relevant (b31-b4 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(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ADD)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_RTSE | USART_CR3_CTSE)); +} + +#if defined(USART_CR3_ONEBIT) +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_ONEBIT) == (USART_CR3_ONEBIT)); +} +#endif /* USART_OneBitSampling_Feature */ + +#if defined(USART_CR1_OVER8) +/** + * @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) + * @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) +{ + if (OverSampling == LL_USART_OVERSAMPLING_8) + { + USARTx->BRR = (uint16_t)(__LL_USART_DIV_SAMPLING8(PeriphClk, BaudRate)); + } + 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. + * @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(const USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t OverSampling) +{ + uint32_t usartdiv = 0x0U; + uint32_t brrresult = 0x0U; + + usartdiv = USARTx->BRR; + + if (OverSampling == LL_USART_OVERSAMPLING_8) + { + if ((usartdiv & 0xFFF7U) != 0U) + { + usartdiv = (uint16_t)((usartdiv & 0xFFF0U) | ((usartdiv & 0x0007U) << 1U)) ; + brrresult = (PeriphClk * 2U) / usartdiv; + } + } + else + { + if ((usartdiv & 0xFFFFU) != 0U) + { + brrresult = PeriphClk / usartdiv; + } + } + return (brrresult); +} +#else +/** + * @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) + * @rmtoll BRR BRR LL_USART_SetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + * @param BaudRate Baud Rate + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBaudRate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t BaudRate) +{ + 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. + * @rmtoll BRR BRR LL_USART_GetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + * @retval Baud Rate + */ +__STATIC_INLINE uint32_t LL_USART_GetBaudRate(const USART_TypeDef *USARTx, uint32_t PeriphClk) +{ + uint32_t usartdiv = 0x0U; + uint32_t brrresult = 0x0U; + + usartdiv = USARTx->BRR; + + if ((usartdiv & 0xFFFFU) != 0U) + { + brrresult = PeriphClk / usartdiv; + } + return (brrresult); +} +#endif /* USART_OverSampling_Feature */ + +/** + * @} + */ + +/** @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_IREN) == (USART_CR3_IREN)); +} + +/** + * @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(const 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, USART_GTPR_PSC, 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(const 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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_NACK) == (USART_CR3_NACK)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_SCEN) == (USART_CR3_SCEN)); +} + +/** + * @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, USART_GTPR_PSC, 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(const 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, USART_GTPR_GT, GuardTime << USART_POSITION_GTPR_GT); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_GT) >> USART_POSITION_GTPR_GT); +} + +/** + * @} + */ + +/** @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_HDSEL) == (USART_CR3_HDSEL)); +} + +/** + * @} + */ + +/** @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(const 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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR2, USART_CR2_LINEN) == (USART_CR2_LINEN)); +} + +/** + * @} + */ + +/** @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 SR PE LL_USART_IsActiveFlag_PE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_PE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_PE) == (USART_SR_PE)); +} + +/** + * @brief Check if the USART Framing Error Flag is set or not + * @rmtoll SR FE LL_USART_IsActiveFlag_FE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_FE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_FE) == (USART_SR_FE)); +} + +/** + * @brief Check if the USART Noise error detected Flag is set or not + * @rmtoll SR NF LL_USART_IsActiveFlag_NE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_NE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_NE) == (USART_SR_NE)); +} + +/** + * @brief Check if the USART OverRun Error Flag is set or not + * @rmtoll SR ORE LL_USART_IsActiveFlag_ORE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ORE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_ORE) == (USART_SR_ORE)); +} + +/** + * @brief Check if the USART IDLE line detected Flag is set or not + * @rmtoll SR IDLE LL_USART_IsActiveFlag_IDLE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_IDLE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_IDLE) == (USART_SR_IDLE)); +} + +/** + * @brief Check if the USART Read Data Register Not Empty Flag is set or not + * @rmtoll SR RXNE LL_USART_IsActiveFlag_RXNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXNE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_RXNE) == (USART_SR_RXNE)); +} + +/** + * @brief Check if the USART Transmission Complete Flag is set or not + * @rmtoll SR TC LL_USART_IsActiveFlag_TC + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TC(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_TC) == (USART_SR_TC)); +} + +/** + * @brief Check if the USART Transmit Data Register Empty Flag is set or not + * @rmtoll SR TXE LL_USART_IsActiveFlag_TXE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXE(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_TXE) == (USART_SR_TXE)); +} + +/** + * @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 SR LBD LL_USART_IsActiveFlag_LBD + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_LBD(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_LBD) == (USART_SR_LBD)); +} + +/** + * @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 SR CTS LL_USART_IsActiveFlag_nCTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_nCTS(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->SR, USART_SR_CTS) == (USART_SR_CTS)); +} + +/** + * @brief Check if the USART Send Break Flag is set or not + * @rmtoll CR1 SBK LL_USART_IsActiveFlag_SBK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_SBK(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_SBK) == (USART_CR1_SBK)); +} + +/** + * @brief Check if the USART Receive Wake Up from mute mode Flag is set or not + * @rmtoll CR1 RWU LL_USART_IsActiveFlag_RWU + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RWU(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_RWU) == (USART_CR1_RWU)); +} + +/** + * @brief Clear Parity Error Flag + * @note Clearing this flag is done by a read access to the USARTx_SR + * register followed by a read access to the USARTx_DR register. + * @note Please also consider that when clearing this flag, other flags as + * NE, FE, ORE, IDLE would also be cleared. + * @rmtoll SR PE LL_USART_ClearFlag_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_PE(USART_TypeDef *USARTx) +{ + __IO uint32_t tmpreg; + tmpreg = USARTx->SR; + (void) tmpreg; + tmpreg = USARTx->DR; + (void) tmpreg; +} + +/** + * @brief Clear Framing Error Flag + * @note Clearing this flag is done by a read access to the USARTx_SR + * register followed by a read access to the USARTx_DR register. + * @note Please also consider that when clearing this flag, other flags as + * PE, NE, ORE, IDLE would also be cleared. + * @rmtoll SR FE LL_USART_ClearFlag_FE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_FE(USART_TypeDef *USARTx) +{ + __IO uint32_t tmpreg; + tmpreg = USARTx->SR; + (void) tmpreg; + tmpreg = USARTx->DR; + (void) tmpreg; +} + +/** + * @brief Clear Noise detected Flag + * @note Clearing this flag is done by a read access to the USARTx_SR + * register followed by a read access to the USARTx_DR register. + * @note Please also consider that when clearing this flag, other flags as + * PE, FE, ORE, IDLE would also be cleared. + * @rmtoll SR NF LL_USART_ClearFlag_NE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_NE(USART_TypeDef *USARTx) +{ + __IO uint32_t tmpreg; + tmpreg = USARTx->SR; + (void) tmpreg; + tmpreg = USARTx->DR; + (void) tmpreg; +} + +/** + * @brief Clear OverRun Error Flag + * @note Clearing this flag is done by a read access to the USARTx_SR + * register followed by a read access to the USARTx_DR register. + * @note Please also consider that when clearing this flag, other flags as + * PE, NE, FE, IDLE would also be cleared. + * @rmtoll SR ORE LL_USART_ClearFlag_ORE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_ORE(USART_TypeDef *USARTx) +{ + __IO uint32_t tmpreg; + tmpreg = USARTx->SR; + (void) tmpreg; + tmpreg = USARTx->DR; + (void) tmpreg; +} + +/** + * @brief Clear IDLE line detected Flag + * @note Clearing this flag is done by a read access to the USARTx_SR + * register followed by a read access to the USARTx_DR register. + * @note Please also consider that when clearing this flag, other flags as + * PE, NE, FE, ORE would also be cleared. + * @rmtoll SR IDLE LL_USART_ClearFlag_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_IDLE(USART_TypeDef *USARTx) +{ + __IO uint32_t tmpreg; + tmpreg = USARTx->SR; + (void) tmpreg; + tmpreg = USARTx->DR; + (void) tmpreg; +} + +/** + * @brief Clear Transmission Complete Flag + * @rmtoll SR TC LL_USART_ClearFlag_TC + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TC(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->SR, ~(USART_SR_TC)); +} + +/** + * @brief Clear RX Not Empty Flag + * @rmtoll SR RXNE LL_USART_ClearFlag_RXNE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_RXNE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->SR, ~(USART_SR_RXNE)); +} + +/** + * @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 SR LBD LL_USART_ClearFlag_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_LBD(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->SR, ~(USART_SR_LBD)); +} + +/** + * @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 SR CTS LL_USART_ClearFlag_nCTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_nCTS(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->SR, ~(USART_SR_CTS)); +} + +/** + * @} + */ + +/** @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 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_SR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_SR 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 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 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_SR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_SR 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 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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_IDLEIE) == (USART_CR1_IDLEIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_RXNEIE) == (USART_CR1_RXNEIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_TCIE) == (USART_CR1_TCIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_TXEIE) == (USART_CR1_TXEIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR1, USART_CR1_PEIE) == (USART_CR1_PEIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR2, USART_CR2_LBDIE) == (USART_CR2_LBDIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_EIE) == (USART_CR3_EIE)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_CTSIE) == (USART_CR3_CTSIE)); +} + +/** + * @} + */ + +/** @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_DMAR) == (USART_CR3_DMAR)); +} + +/** + * @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(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_DMAT) == (USART_CR3_DMAT)); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll DR DR LL_USART_DMA_GetRegAddr + * @note Address of Data Register is valid for both Transmit and Receive transfers. + * @param USARTx USART Instance + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_USART_DMA_GetRegAddr(const USART_TypeDef *USARTx) +{ + /* return address of DR register */ + return ((uint32_t) &(USARTx->DR)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Read Receiver Data register (Receive Data value, 8 bits) + * @rmtoll DR DR LL_USART_ReceiveData8 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_USART_ReceiveData8(const USART_TypeDef *USARTx) +{ + return (uint8_t)(READ_BIT(USARTx->DR, USART_DR_DR)); +} + +/** + * @brief Read Receiver Data register (Receive Data value, 9 bits) + * @rmtoll DR DR LL_USART_ReceiveData9 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x1FF + */ +__STATIC_INLINE uint16_t LL_USART_ReceiveData9(const USART_TypeDef *USARTx) +{ + return (uint16_t)(READ_BIT(USARTx->DR, USART_DR_DR)); +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 8 bits) + * @rmtoll DR DR 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->DR = Value; +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 9 bits) + * @rmtoll DR DR 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->DR = Value & 0x1FFU; +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Execution Execution + * @{ + */ + +/** + * @brief Request Break sending + * @rmtoll CR1 SBK LL_USART_RequestBreakSending + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestBreakSending(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR1, USART_CR1_SBK); +} + +/** + * @brief Put USART in Mute mode + * @rmtoll CR1 RWU LL_USART_RequestEnterMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestEnterMuteMode(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR1, USART_CR1_RWU); +} + +/** + * @brief Put USART in Active mode + * @rmtoll CR1 RWU LL_USART_RequestExitMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestExitMuteMode(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR1, USART_CR1_RWU); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EF_Init Initialization and de-initialization functions + * @{ + */ +ErrorStatus LL_USART_DeInit(const USART_TypeDef *USARTx); +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, const LL_USART_InitTypeDef *USART_InitStruct); +void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct); +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, const LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* USART1 || USART2 || USART3 || UART4 || UART5 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_LL_USART_H */ + diff --git a/diode_tester/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c new file mode 100644 index 0000000..b7cf66c --- /dev/null +++ b/diode_tester/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c @@ -0,0 +1,3771 @@ +/** + ****************************************************************************** + * @file stm32f1xx_hal_uart.c + * @author MCD Application Team + * @brief UART HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The UART HAL driver can be used as follows: + + (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart). + (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API: + (##) Enable the USARTx interface clock. + (##) UART pins configuration: + (+++) Enable the clock for the UART GPIOs. + (+++) Configure the UART TX/RX pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT() + and HAL_UART_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA() + and HAL_UART_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx channel. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required + Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx channel. + (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the DMA Tx/Rx channel. + (+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle + (used for last byte sending completion detection in DMA non circular mode) + + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware + flow control and Mode(Receiver/Transmitter) in the huart Init structure. + + (#) For the UART asynchronous mode, initialize the UART registers by calling + the HAL_UART_Init() API. + + (#) For the UART Half duplex mode, initialize the UART registers by calling + the HAL_HalfDuplex_Init() API. + + (#) For the LIN mode, initialize the UART registers by calling the HAL_LIN_Init() API. + + (#) For the Multi-Processor mode, initialize the UART registers by calling + the HAL_MultiProcessor_Init() API. + + [..] + (@) The specific UART interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit + and receive process. + + [..] + (@) These APIs (HAL_UART_Init() and HAL_HalfDuplex_Init()) configure also the + low level Hardware GPIO, CLOCK, CORTEX...etc) by calling the customized + HAL_UART_MspInit() API. + + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_UART_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function HAL_UART_RegisterCallback() to register a user callback. + Function HAL_UART_RegisterCallback() allows to register following callbacks: + (+) TxHalfCpltCallback : Tx Half Complete Callback. + (+) TxCpltCallback : Tx Complete Callback. + (+) RxHalfCpltCallback : Rx Half Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback. + (+) AbortReceiveCpltCallback : Abort Receive Complete Callback. + (+) MspInitCallback : UART MspInit. + (+) MspDeInitCallback : UART MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_UART_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_UART_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxHalfCpltCallback : Tx Half Complete Callback. + (+) TxCpltCallback : Tx Complete Callback. + (+) RxHalfCpltCallback : Rx Half Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback. + (+) AbortReceiveCpltCallback : Abort Receive Complete Callback. + (+) MspInitCallback : UART MspInit. + (+) MspDeInitCallback : UART MspDeInit. + + [..] + For specific callback RxEventCallback, use dedicated registration/reset functions: + respectively HAL_UART_RegisterRxEventCallback() , HAL_UART_UnRegisterRxEventCallback(). + + [..] + By default, after the HAL_UART_Init() and when the state is HAL_UART_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples HAL_UART_TxCpltCallback(), HAL_UART_RxHalfCpltCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_UART_Init() + and HAL_UART_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_UART_Init() and HAL_UART_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_UART_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_UART_STATE_READY or HAL_UART_STATE_RESET state, thus registered (user) + MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_UART_RegisterCallback() before calling HAL_UART_DeInit() + or HAL_UART_Init() function. + + [..] + When The compilation define USE_HAL_UART_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + [..] + Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_UART_Transmit() + (+) Receive an amount of data in blocking mode using HAL_UART_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT() + (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT() + (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxCpltCallback + (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_UART_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA() + (+) At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback + (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_UART_Receive_DMA() + (+) At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback + (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxCpltCallback + (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_UART_ErrorCallback + (+) Pause the DMA Transfer using HAL_UART_DMAPause() + (+) Resume the DMA Transfer using HAL_UART_DMAResume() + (+) Stop the DMA Transfer using HAL_UART_DMAStop() + + + [..] This subsection also provides a set of additional functions providing enhanced reception + services to user. (For example, these functions allow application to handle use cases + where number of data to be received is unknown). + + (#) Compared to standard reception services which only consider number of received + data elements as reception completion criteria, these functions also consider additional events + as triggers for updating reception status to caller : + (+) Detection of inactivity period (RX line has not been active for a given period). + (++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state) + for 1 frame time, after last received byte. + + (#) There are two mode of transfer: + (+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received, + or till IDLE event occurs. Reception is handled only during function execution. + When function exits, no data reception could occur. HAL status and number of actually received data elements, + are returned by function after finishing transfer. + (+) Non-Blocking mode: The reception is performed using Interrupts or DMA. + These API's return the HAL status. + The end of the data processing will be indicated through the + dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode. + The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process + The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected. + + (#) Blocking mode API: + (+) HAL_UARTEx_ReceiveToIdle() + + (#) Non-Blocking mode API with Interrupt: + (+) HAL_UARTEx_ReceiveToIdle_IT() + + (#) Non-Blocking mode API with DMA: + (+) HAL_UARTEx_ReceiveToIdle_DMA() + + + *** UART HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in UART HAL driver. + + (+) __HAL_UART_ENABLE: Enable the UART peripheral + (+) __HAL_UART_DISABLE: Disable the UART peripheral + (+) __HAL_UART_GET_FLAG : Check whether the specified UART flag is set or not + (+) __HAL_UART_CLEAR_FLAG : Clear the specified UART pending flag + (+) __HAL_UART_ENABLE_IT: Enable the specified UART interrupt + (+) __HAL_UART_DISABLE_IT: Disable the specified UART interrupt + (+) __HAL_UART_GET_IT_SOURCE: Check whether the specified UART interrupt has occurred or not + + [..] + (@) You can refer to the UART HAL driver header file for more useful macros + + @endverbatim + [..] + (@) Additional remark: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + Depending on the frame length defined by the M bit (8-bits or 9-bits), + the possible UART frame formats are as listed in the following table: + +-------------------------------------------------------------+ + | M bit | PCE bit | UART frame | + |---------------------|---------------------------------------| + | 0 | 0 | | SB | 8 bit data | STB | | + |---------|-----------|---------------------------------------| + | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|-----------|---------------------------------------| + | 1 | 0 | | SB | 9 bit data | STB | | + |---------|-----------|---------------------------------------| + | 1 | 1 | | SB | 8 bit data | PB | STB | | + +-------------------------------------------------------------+ + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal.h" + +/** @addtogroup STM32F1xx_HAL_Driver + * @{ + */ + +/** @defgroup UART UART + * @brief HAL UART module driver + * @{ + */ +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup UART_Private_Constants + * @{ + */ +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup UART_Private_Functions UART Private Functions + * @{ + */ + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart); +static void UART_EndRxTransfer(UART_HandleTypeDef *huart); +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout); +static void UART_SetConfig(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode only these parameters can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + Depending on the frame length defined by the M bit (8-bits or 9-bits), + please refer to Reference manual for possible UART frame formats. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + [..] + The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init() and HAL_MultiProcessor_Init() APIs + follow respectively the UART asynchronous, UART Half duplex, LIN and Multi-Processor configuration + procedures (details for the procedures are available in reference manuals + (RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the UART mode according to the specified parameters in + * the UART_InitTypeDef and create the associated handle. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if (huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE) + { + /* The hardware flow control is available only for USART1, USART2 and USART3 */ + assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance)); + assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl)); + } + else + { + assert_param(IS_UART_INSTANCE(huart->Instance)); + } + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); +#if defined(USART_CR1_OVER8) + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); +#endif /* USART_CR1_OVER8 */ + + if (huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + UART_InitCallbacksToDefault(huart); + + if (huart->MspInitCallback == NULL) + { + huart->MspInitCallback = HAL_UART_MspInit; + } + + /* Init the low level hardware */ + huart->MspInitCallback(huart); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); +#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */ + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In asynchronous mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + return HAL_OK; +} + +/** + * @brief Initializes the half-duplex mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if (huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); +#if defined(USART_CR1_OVER8) + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); +#endif /* USART_CR1_OVER8 */ + + if (huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + UART_InitCallbacksToDefault(huart); + + if (huart->MspInitCallback == NULL) + { + huart->MspInitCallback = HAL_UART_MspInit; + } + + /* Init the low level hardware */ + huart->MspInitCallback(huart); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); +#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */ + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* 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(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state*/ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + return HAL_OK; +} + +/** + * @brief Initializes the LIN mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param BreakDetectLength Specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection + * @arg UART_LINBREAKDETECTLENGTH_11B: 11-bit break detection + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength) +{ + /* Check the UART handle allocation */ + if (huart == NULL) + { + return HAL_ERROR; + } + + /* Check the LIN UART instance */ + assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); + + /* Check the Break detection length parameter */ + assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength)); + assert_param(IS_UART_LIN_WORD_LENGTH(huart->Init.WordLength)); +#if defined(USART_CR1_OVER8) + assert_param(IS_UART_LIN_OVERSAMPLING(huart->Init.OverSampling)); +#endif /* USART_CR1_OVER8 */ + + if (huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + UART_InitCallbacksToDefault(huart); + + if (huart->MspInitCallback == NULL) + { + huart->MspInitCallback = HAL_UART_MspInit; + } + + /* Init the low level hardware */ + huart->MspInitCallback(huart); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); +#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */ + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In LIN mode, the following bits must be kept cleared: + - CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ + SET_BIT(huart->Instance->CR2, USART_CR2_LINEN); + + /* Set the USART LIN Break detection length. */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_LBDL); + SET_BIT(huart->Instance->CR2, BreakDetectLength); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state*/ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + return HAL_OK; +} + +/** + * @brief Initializes the Multi-Processor mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param Address USART address + * @param WakeUpMethod specifies the USART wake-up method. + * This parameter can be one of the following values: + * @arg UART_WAKEUPMETHOD_IDLELINE: Wake-up by an idle line detection + * @arg UART_WAKEUPMETHOD_ADDRESSMARK: Wake-up by an address mark + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod) +{ + /* Check the UART handle allocation */ + if (huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Check the Address & wake up method parameters */ + assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod)); + assert_param(IS_UART_ADDRESS(Address)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); +#if defined(USART_CR1_OVER8) + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); +#endif /* USART_CR1_OVER8 */ + + if (huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + UART_InitCallbacksToDefault(huart); + + if (huart->MspInitCallback == NULL) + { + huart->MspInitCallback = HAL_UART_MspInit; + } + + /* Init the low level hardware */ + huart->MspInitCallback(huart); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); +#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */ + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In Multi-Processor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register */ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Set the USART address node */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_ADD); + SET_BIT(huart->Instance->CR2, Address); + + /* Set the wake up method by setting the WAKE bit in the CR1 register */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_WAKE); + SET_BIT(huart->Instance->CR1, WakeUpMethod); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + return HAL_OK; +} + +/** + * @brief DeInitializes the UART peripheral. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if (huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + if (huart->MspDeInitCallback == NULL) + { + huart->MspDeInitCallback = HAL_UART_MspDeInit; + } + /* DeInit the low level hardware */ + huart->MspDeInitCallback(huart); +#else + /* DeInit the low level hardware */ + HAL_UART_MspDeInit(huart); +#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */ + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_RESET; + huart->RxState = HAL_UART_STATE_RESET; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Process Unlock */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief UART MSP Init. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_MspInit could be implemented in the user file + */ +} + +/** + * @brief UART MSP DeInit. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User UART Callback + * To be used instead of the weak predefined callback + * @note The HAL_UART_RegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), + * HAL_MultiProcessor_Init() to register callbacks for HAL_UART_MSPINIT_CB_ID and HAL_UART_MSPDEINIT_CB_ID + * @param huart uart handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID, + pUART_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + if (huart->gState == HAL_UART_STATE_READY) + { + switch (CallbackID) + { + case HAL_UART_TX_HALFCOMPLETE_CB_ID : + huart->TxHalfCpltCallback = pCallback; + break; + + case HAL_UART_TX_COMPLETE_CB_ID : + huart->TxCpltCallback = pCallback; + break; + + case HAL_UART_RX_HALFCOMPLETE_CB_ID : + huart->RxHalfCpltCallback = pCallback; + break; + + case HAL_UART_RX_COMPLETE_CB_ID : + huart->RxCpltCallback = pCallback; + break; + + case HAL_UART_ERROR_CB_ID : + huart->ErrorCallback = pCallback; + break; + + case HAL_UART_ABORT_COMPLETE_CB_ID : + huart->AbortCpltCallback = pCallback; + break; + + case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID : + huart->AbortTransmitCpltCallback = pCallback; + break; + + case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID : + huart->AbortReceiveCpltCallback = pCallback; + break; + + case HAL_UART_MSPINIT_CB_ID : + huart->MspInitCallback = pCallback; + break; + + case HAL_UART_MSPDEINIT_CB_ID : + huart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (huart->gState == HAL_UART_STATE_RESET) + { + switch (CallbackID) + { + case HAL_UART_MSPINIT_CB_ID : + huart->MspInitCallback = pCallback; + break; + + case HAL_UART_MSPDEINIT_CB_ID : + huart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an UART Callback + * UART callaback is redirected to the weak predefined callback + * @note The HAL_UART_UnRegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(), + * HAL_LIN_Init(), HAL_MultiProcessor_Init() to un-register callbacks for HAL_UART_MSPINIT_CB_ID + * and HAL_UART_MSPDEINIT_CB_ID + * @param huart uart handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (HAL_UART_STATE_READY == huart->gState) + { + switch (CallbackID) + { + case HAL_UART_TX_HALFCOMPLETE_CB_ID : + huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_UART_TX_COMPLETE_CB_ID : + huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_UART_RX_HALFCOMPLETE_CB_ID : + huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_UART_RX_COMPLETE_CB_ID : + huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_UART_ERROR_CB_ID : + huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_UART_ABORT_COMPLETE_CB_ID : + huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID : + huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + break; + + case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID : + huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + break; + + case HAL_UART_MSPINIT_CB_ID : + huart->MspInitCallback = HAL_UART_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_UART_MSPDEINIT_CB_ID : + huart->MspDeInitCallback = HAL_UART_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_UART_STATE_RESET == huart->gState) + { + switch (CallbackID) + { + case HAL_UART_MSPINIT_CB_ID : + huart->MspInitCallback = HAL_UART_MspInit; + break; + + case HAL_UART_MSPDEINIT_CB_ID : + huart->MspDeInitCallback = HAL_UART_MspDeInit; + break; + + default : + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Register a User UART Rx Event Callback + * To be used instead of the weak predefined callback + * @param huart Uart handle + * @param pCallback Pointer to the Rx Event Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_RegisterRxEventCallback(UART_HandleTypeDef *huart, pUART_RxEventCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(huart); + + if (huart->gState == HAL_UART_STATE_READY) + { + huart->RxEventCallback = pCallback; + } + else + { + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(huart); + + return status; +} + +/** + * @brief UnRegister the UART Rx Event Callback + * UART Rx Event Callback is redirected to the weak HAL_UARTEx_RxEventCallback() predefined callback + * @param huart Uart handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_UnRegisterRxEventCallback(UART_HandleTypeDef *huart) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(huart); + + if (huart->gState == HAL_UART_STATE_READY) + { + huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak UART Rx Event Callback */ + } + else + { + huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK; + + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(huart); + return status; +} +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group2 IO operation functions + * @brief UART Transmit and Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of functions allowing to manage the UART asynchronous + and Half duplex data transfers. + + (#) There are two modes of transfer: + (+) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (+) Non-Blocking mode: The communication is performed using Interrupts + or DMA, these API's return the HAL status. + The end of the data processing will be indicated through the + dedicated UART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or receive process + The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected. + + (#) Blocking mode API's are : + (+) HAL_UART_Transmit() + (+) HAL_UART_Receive() + + (#) Non-Blocking mode API's with Interrupt are : + (+) HAL_UART_Transmit_IT() + (+) HAL_UART_Receive_IT() + (+) HAL_UART_IRQHandler() + + (#) Non-Blocking mode API's with DMA are : + (+) HAL_UART_Transmit_DMA() + (+) HAL_UART_Receive_DMA() + (+) HAL_UART_DMAPause() + (+) HAL_UART_DMAResume() + (+) HAL_UART_DMAStop() + + (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode: + (+) HAL_UART_TxHalfCpltCallback() + (+) HAL_UART_TxCpltCallback() + (+) HAL_UART_RxHalfCpltCallback() + (+) HAL_UART_RxCpltCallback() + (+) HAL_UART_ErrorCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_UART_Abort() + (+) HAL_UART_AbortTransmit() + (+) HAL_UART_AbortReceive() + (+) HAL_UART_Abort_IT() + (+) HAL_UART_AbortTransmit_IT() + (+) HAL_UART_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_UART_AbortCpltCallback() + (+) HAL_UART_AbortTransmitCpltCallback() + (+) HAL_UART_AbortReceiveCpltCallback() + + (#) A Rx Event Reception Callback (Rx event notification) is available for Non_Blocking modes of enhanced reception services: + (+) HAL_UARTEx_RxEventCallback() + + (#) In Non-Blocking mode transfers, possible errors are split into 2 categories. + Errors are handled as follows : + (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is + to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception . + Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type, + and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side. + If user wants to abort it, Abort services should be called by user. + (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted. + This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. + Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed. + + -@- In the Half duplex communication, it is forbidden to run the transmit + and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful. + +@endverbatim + * @{ + */ + +/** + * @brief Sends an amount of data in blocking mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + const uint8_t *pdata8bits; + const uint16_t *pdata16bits; + uint32_t tickstart = 0U; + + /* Check that a Tx process is not already ongoing */ + if (huart->gState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + pdata8bits = NULL; + pdata16bits = (const uint16_t *) pData; + } + else + { + pdata8bits = pData; + pdata16bits = NULL; + } + + while (huart->TxXferCount > 0U) + { + if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + huart->gState = HAL_UART_STATE_READY; + + return HAL_TIMEOUT; + } + if (pdata8bits == NULL) + { + huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU); + pdata16bits++; + } + else + { + huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU); + pdata8bits++; + } + huart->TxXferCount--; + } + + if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + huart->gState = HAL_UART_STATE_READY; + + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in blocking mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint8_t *pdata8bits; + uint16_t *pdata16bits; + uint32_t tickstart = 0U; + + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + pdata8bits = NULL; + pdata16bits = (uint16_t *) pData; + } + else + { + pdata8bits = pData; + pdata16bits = NULL; + } + + /* Check the remain data to be received */ + while (huart->RxXferCount > 0U) + { + if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + huart->RxState = HAL_UART_STATE_READY; + + return HAL_TIMEOUT; + } + if (pdata8bits == NULL) + { + *pdata16bits = (uint16_t)(huart->Instance->DR & 0x01FF); + pdata16bits++; + } + else + { + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE))) + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F); + } + pdata8bits++; + } + huart->RxXferCount--; + } + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sends an amount of data in non blocking mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if (huart->gState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Enable the UART Transmit data register empty Interrupt */ + __HAL_UART_ENABLE_IT(huart, UART_IT_TXE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in non blocking mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Set Reception type to Standard reception */ + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + return (UART_Start_Receive_IT(huart, pData, Size)); + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sends an amount of data in DMA mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) +{ + const uint32_t *tmp; + + /* Check that a Tx process is not already ongoing */ + if (huart->gState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmatx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmatx->XferAbortCallback = NULL; + + /* Enable the UART transmit DMA channel */ + tmp = (const uint32_t *)&pData; + HAL_DMA_Start_IT(huart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&huart->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in DMA mode. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pData. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @note When the UART parity is enabled (PCE = 1) the received data contains the parity bit. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Set Reception type to Standard reception */ + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + return (UART_Start_Receive_DMA(huart, pData, Size)); + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pauses the DMA Transfer. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart) +{ + uint32_t dmarequest = 0x00U; + + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + /* Disable the UART DMA Tx request */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + return HAL_OK; +} + +/** + * @brief Resumes the DMA Transfer. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart) +{ + + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + /* Enable the UART DMA Tx request */ + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + + if (huart->RxState == HAL_UART_STATE_BUSY_RX) + { + /* Clear the Overrun flag before resuming the Rx transfer*/ + __HAL_UART_CLEAR_OREFLAG(huart); + + /* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */ + if (huart->Init.Parity != UART_PARITY_NONE) + { + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + } + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART DMA Rx request */ + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + return HAL_OK; +} + +/** + * @brief Stops the DMA Transfer. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) +{ + uint32_t dmarequest = 0x00U; + /* The Lock is not implemented on this API to allow the user application + to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() + */ + + /* Stop UART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel */ + if (huart->hdmatx != NULL) + { + HAL_DMA_Abort(huart->hdmatx); + } + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if (huart->hdmarx != NULL) + { + HAL_DMA_Abort(huart->hdmarx); + } + UART_EndRxTransfer(huart); + } + + return HAL_OK; +} + +/** + * @brief Receive an amount of data in blocking mode till either the expected number of data is received or an IDLE event occurs. + * @note HAL_OK is returned if reception is completed (expected number of data has been received) + * or if reception is stopped after IDLE event (less than the expected number of data has been received) + * In this case, RxLen output parameter indicates number of data available in reception buffer. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01), + * the received data is handled as a set of uint16_t. In this case, Size must indicate the number + * of uint16_t available through pData. + * @param huart UART handle. + * @param pData Pointer to data buffer (uint8_t or uint16_t data elements). + * @param Size Amount of data elements (uint8_t or uint16_t) to be received. + * @param RxLen Number of data elements finally received (could be lower than Size, in case reception ends on IDLE event) + * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen, + uint32_t Timeout) +{ + uint8_t *pdata8bits; + uint16_t *pdata16bits; + uint32_t tickstart; + + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + pdata8bits = NULL; + pdata16bits = (uint16_t *) pData; + } + else + { + pdata8bits = pData; + pdata16bits = NULL; + } + + /* Initialize output number of received elements */ + *RxLen = 0U; + + /* as long as data have to be received */ + while (huart->RxXferCount > 0U) + { + /* Check if IDLE flag is set */ + if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) + { + /* Clear IDLE flag in ISR */ + __HAL_UART_CLEAR_IDLEFLAG(huart); + + /* If Set, but no data ever received, clear flag without exiting loop */ + /* If Set, and data has already been received, this means Idle Event is valid : End reception */ + if (*RxLen > 0U) + { + huart->RxEventType = HAL_UART_RXEVENT_IDLE; + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; + } + } + + /* Check if RXNE flag is set */ + if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE)) + { + if (pdata8bits == NULL) + { + *pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF); + pdata16bits++; + } + else + { + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE))) + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F); + } + + pdata8bits++; + } + /* Increment number of received elements */ + *RxLen += 1U; + huart->RxXferCount--; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + huart->RxState = HAL_UART_STATE_READY; + + return HAL_TIMEOUT; + } + } + } + + /* Set number of received elements in output parameter : RxLen */ + *RxLen = huart->RxXferSize - huart->RxXferCount; + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in interrupt mode till either the expected number of data is received or an IDLE event occurs. + * @note Reception is initiated by this function call. Further progress of reception is achieved thanks + * to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating + * number of received data elements. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01), + * the received data is handled as a set of uint16_t. In this case, Size must indicate the number + * of uint16_t available through pData. + * @param huart UART handle. + * @param pData Pointer to data buffer (uint8_t or uint16_t data elements). + * @param Size Amount of data elements (uint8_t or uint16_t) to be received. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef status; + + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Set Reception type to reception till IDLE Event*/ + huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + status = UART_Start_Receive_IT(huart, pData, Size); + + /* Check Rx process has been successfully started */ + if (status == HAL_OK) + { + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + __HAL_UART_CLEAR_IDLEFLAG(huart); + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + } + else + { + /* In case of errors already pending when reception is started, + Interrupts may have already been raised and lead to reception abortion. + (Overrun error for instance). + In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */ + status = HAL_ERROR; + } + } + + return status; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs. + * @note Reception is initiated by this function call. Further progress of reception is achieved thanks + * to DMA services, transferring automatically received data elements in user reception buffer and + * calling registered callbacks at half/end of reception. UART IDLE events are also used to consider + * reception phase as ended. In all cases, callback execution will indicate number of received data elements. + * @note When the UART parity is enabled (PCE = 1), the received data contain + * the parity bit (MSB position). + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01), + * the received data is handled as a set of uint16_t. In this case, Size must indicate the number + * of uint16_t available through pData. + * @param huart UART handle. + * @param pData Pointer to data buffer (uint8_t or uint16_t data elements). + * @param Size Amount of data elements (uint8_t or uint16_t) to be received. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef status; + + /* Check that a Rx process is not already ongoing */ + if (huart->RxState == HAL_UART_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Set Reception type to reception till IDLE Event*/ + huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + status = UART_Start_Receive_DMA(huart, pData, Size); + + /* Check Rx process has been successfully started */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + __HAL_UART_CLEAR_IDLEFLAG(huart); + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + } + else + { + /* In case of errors already pending when reception is started, + Interrupts may have already been raised and lead to reception abortion. + (Overrun error for instance). + In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */ + status = HAL_ERROR; + } + + return status; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Provide Rx Event type that has lead to RxEvent callback execution. + * @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress + * of reception process is provided to application through calls of Rx Event callback (either default one + * HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event, + * Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead + * to Rx Event callback execution. + * @note This function is expected to be called within the user implementation of Rx Event Callback, + * in order to provide the accurate value : + * In Interrupt Mode : + * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received) + * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of + * received data is lower than expected one) + * In DMA Mode : + * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received) + * - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received + * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of + * received data is lower than expected one). + * In DMA mode, RxEvent callback could be called several times; + * When DMA is configured in Normal Mode, HT event does not stop Reception process; + * When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process; + * @param huart UART handle. + * @retval Rx Event Type (returned value will be a value of @ref UART_RxEvent_Type_Values) + */ +HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart) +{ + /* Return Rx Event type value, as stored in UART handle */ + return(huart->RxEventType); +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE)); + } + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel: use blocking DMA Abort API (no callback) */ + if (huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK) + { + if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + huart->ErrorCode = HAL_UART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel: use blocking DMA Abort API (no callback) */ + if (huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK) + { + if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + huart->ErrorCode = HAL_UART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } + } + } + + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->RxState and huart->gState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->gState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if (huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK) + { + if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + huart->ErrorCode = HAL_UART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } + } + } + + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE)); + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if (huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK) + { + if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + huart->ErrorCode = HAL_UART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } + } + } + + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart) +{ + uint32_t AbortCplt = 0x01U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE)); + } + + /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if (huart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback; + } + else + { + huart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if (huart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback; + } + else + { + huart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at UART level */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if (huart->hdmatx != NULL) + { + /* UART Tx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + huart->hdmatx->XferAbortCallback = NULL; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if (huart->hdmarx != NULL) + { + /* UART Rx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + huart->hdmarx->XferAbortCallback = NULL; + AbortCplt = 0x01U; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ + if (AbortCplt == 0x01U) + { + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + huart->AbortCpltCallback(huart); +#else + /* Call legacy weak Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if (huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */ + huart->hdmatx->XferAbortCallback(huart->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + huart->AbortTransmitCpltCallback(huart); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + huart->AbortTransmitCpltCallback(huart); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE)); + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if (huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + huart->AbortReceiveCpltCallback(huart); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + huart->AbortReceiveCpltCallback(huart); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + + return HAL_OK; +} + +/** + * @brief This function handles UART interrupt request. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) +{ + uint32_t isrflags = READ_REG(huart->Instance->SR); + uint32_t cr1its = READ_REG(huart->Instance->CR1); + uint32_t cr3its = READ_REG(huart->Instance->CR3); + uint32_t errorflags = 0x00U; + uint32_t dmarequest = 0x00U; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); + if (errorflags == RESET) + { + /* UART in mode Receiver -------------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + UART_Receive_IT(huart); + return; + } + } + + /* If some errors occur */ + if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) + || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) + { + /* UART parity error interrupt occurred ----------------------------------*/ + if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_PE; + } + + /* UART noise error interrupt occurred -----------------------------------*/ + if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_NE; + } + + /* UART frame error interrupt occurred -----------------------------------*/ + if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_FE; + } + + /* UART Over-Run interrupt occurred --------------------------------------*/ + if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) + || ((cr3its & USART_CR3_EIE) != RESET))) + { + huart->ErrorCode |= HAL_UART_ERROR_ORE; + } + + /* Call UART Error Call back function if need be --------------------------*/ + if (huart->ErrorCode != HAL_UART_ERROR_NONE) + { + /* UART in mode Receiver -----------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + UART_Receive_IT(huart); + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest) + { + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + UART_EndRxTransfer(huart); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if (huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; + if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + huart->ErrorCallback(huart); +#else + /*Call legacy weak error callback*/ + HAL_UART_ErrorCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + huart->ErrorCallback(huart); +#else + /*Call legacy weak error callback*/ + HAL_UART_ErrorCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + huart->ErrorCallback(huart); +#else + /*Call legacy weak error callback*/ + HAL_UART_ErrorCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + + huart->ErrorCode = HAL_UART_ERROR_NONE; + } + } + return; + } /* End if some error occurs */ + + /* Check current reception Mode : + If Reception till IDLE event has been selected : */ + if ((huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + && ((isrflags & USART_SR_IDLE) != 0U) + && ((cr1its & USART_SR_IDLE) != 0U)) + { + __HAL_UART_CLEAR_IDLEFLAG(huart); + + /* Check if DMA mode is enabled in UART */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + /* DMA mode enabled */ + /* Check received length : If all expected data are received, do nothing, + (DMA cplt callback will be called). + Otherwise, if at least one data has already been received, IDLE event is to be notified to user */ + uint16_t nb_remaining_rx_data = (uint16_t) __HAL_DMA_GET_COUNTER(huart->hdmarx); + if ((nb_remaining_rx_data > 0U) + && (nb_remaining_rx_data < huart->RxXferSize)) + { + /* Reception is not complete */ + huart->RxXferCount = nb_remaining_rx_data; + + /* In Normal mode, end DMA xfer and HAL UART Rx process*/ + if (huart->hdmarx->Init.Mode != DMA_CIRCULAR) + { + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by resetting the DMAR bit + in the UART CR3 register */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + + /* Last bytes received, so no need as the abort is immediate */ + (void)HAL_DMA_Abort(huart->hdmarx); + } + + /* Initialize type of RxEvent that correspond to RxEvent callback execution; + In this case, Rx Event type is Idle Event */ + huart->RxEventType = HAL_UART_RXEVENT_IDLE; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx Event callback*/ + huart->RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount)); +#else + /*Call legacy weak Rx Event callback*/ + HAL_UARTEx_RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount)); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + return; + } + else + { + /* DMA mode not enabled */ + /* Check received length : If all expected data are received, do nothing. + Otherwise, if at least one data has already been received, IDLE event is to be notified to user */ + uint16_t nb_rx_data = huart->RxXferSize - huart->RxXferCount; + if ((huart->RxXferCount > 0U) + && (nb_rx_data > 0U)) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + + /* Initialize type of RxEvent that correspond to RxEvent callback execution; + In this case, Rx Event type is Idle Event */ + huart->RxEventType = HAL_UART_RXEVENT_IDLE; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx complete callback*/ + huart->RxEventCallback(huart, nb_rx_data); +#else + /*Call legacy weak Rx Event callback*/ + HAL_UARTEx_RxEventCallback(huart, nb_rx_data); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + return; + } + } + + /* UART in mode Transmitter ------------------------------------------------*/ + if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) + { + UART_Transmit_IT(huart); + return; + } + + /* UART in mode Transmitter end --------------------------------------------*/ + if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + UART_EndTransmit_IT(huart); + return; + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callbacks. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callbacks. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief UART error callbacks. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Receive Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Reception Event Callback (Rx event notification called after use of advanced reception service). + * @param huart UART handle + * @param Size Number of data available in application reception buffer (indicates a position in + * reception buffer until which, data are available) + * @retval None + */ +__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + UNUSED(Size); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_RxEventCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions + * @brief UART control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the UART: + (+) HAL_LIN_SendBreak() API can be helpful to transmit the break character. + (+) HAL_MultiProcessor_EnterMuteMode() API can be helpful to enter the UART in mute mode. + (+) HAL_MultiProcessor_ExitMuteMode() API can be helpful to exit the UART mute mode by software. + (+) HAL_HalfDuplex_EnableTransmitter() API to enable the UART transmitter and disables the UART receiver in Half Duplex mode + (+) HAL_HalfDuplex_EnableReceiver() API to enable the UART receiver and disables the UART transmitter in Half Duplex mode + +@endverbatim + * @{ + */ + +/** + * @brief Transmits break characters. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Send break characters */ + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_SBK); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enters the UART in mute mode. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Enable the USART mute mode by setting the RWU bit in the CR1 register */ + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_RWU); + + huart->gState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Exits the UART mute mode: wake up software. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the USART mute mode by clearing the RWU bit in the CR1 register */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_RWU); + + huart->gState = HAL_UART_STATE_READY; + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enables the UART transmitter and disables the UART receiver. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00U; + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = huart->Instance->CR1; + + /* Clear TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */ + tmpreg |= (uint32_t)USART_CR1_TE; + + /* Write to USART CR1 */ + WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enables the UART receiver and disables the UART transmitter. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00U; + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = huart->Instance->CR1; + + /* Clear TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */ + tmpreg |= (uint32_t)USART_CR1_RE; + + /* Write to USART CR1 */ + WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief UART State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + UART communication process, return Peripheral Errors occurred during communication + process + (+) HAL_UART_GetState() API can be helpful to check in run-time the state of the UART peripheral. + (+) HAL_UART_GetError() check in run-time errors that could be occurred during communication. + +@endverbatim + * @{ + */ + +/** + * @brief Returns the UART state. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL state + */ +HAL_UART_StateTypeDef HAL_UART_GetState(const UART_HandleTypeDef *huart) +{ + uint32_t temp1 = 0x00U, temp2 = 0x00U; + temp1 = huart->gState; + temp2 = huart->RxState; + + return (HAL_UART_StateTypeDef)(temp1 | temp2); +} + +/** + * @brief Return the UART error code + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. + * @retval UART Error Code + */ +uint32_t HAL_UART_GetError(const UART_HandleTypeDef *huart) +{ + return huart->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup UART_Private_Functions UART Private Functions + * @{ + */ + +/** + * @brief Initialize the callbacks to their default values. + * @param huart UART handle. + * @retval none + */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) +void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart) +{ + /* Init the UART Callback settings */ + huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */ + huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak RxEventCallback */ + +} +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +/** + * @brief DMA UART transmit process complete callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* DMA Normal mode*/ + if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) + { + huart->TxXferCount = 0x00U; + + /* Disable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the UART Transmit Complete Interrupt */ + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + } + /* DMA Circular mode */ + else + { +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Tx complete callback*/ + huart->TxCpltCallback(huart); +#else + /*Call legacy weak Tx complete callback*/ + HAL_UART_TxCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } +} + +/** + * @brief DMA UART transmit process half complete callback + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Tx complete callback*/ + huart->TxHalfCpltCallback(huart); +#else + /*Call legacy weak Tx complete callback*/ + HAL_UART_TxHalfCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA UART receive process complete callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* DMA Normal mode*/ + if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) + { + huart->RxXferCount = 0U; + + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* If Reception till IDLE event has been selected, Disable IDLE Interrupt */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + } + } + + /* Initialize type of RxEvent that correspond to RxEvent callback execution; + In this case, Rx Event type is Transfer Complete */ + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Check current reception Mode : + If Reception till IDLE event has been selected : use Rx Event callback */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx Event callback*/ + huart->RxEventCallback(huart, huart->RxXferSize); +#else + /*Call legacy weak Rx Event callback*/ + HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + else + { + /* In other cases : use Rx Complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx complete callback*/ + huart->RxCpltCallback(huart); +#else + /*Call legacy weak Rx complete callback*/ + HAL_UART_RxCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } +} + +/** + * @brief DMA UART receive process half complete callback + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Initialize type of RxEvent that correspond to RxEvent callback execution; + In this case, Rx Event type is Half Transfer */ + huart->RxEventType = HAL_UART_RXEVENT_HT; + + /* Check current reception Mode : + If Reception till IDLE event has been selected : use Rx Event callback */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx Event callback*/ + huart->RxEventCallback(huart, huart->RxXferSize / 2U); +#else + /*Call legacy weak Rx Event callback*/ + HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize / 2U); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + else + { + /* In other cases : use Rx Half Complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx Half complete callback*/ + huart->RxHalfCpltCallback(huart); +#else + /*Call legacy weak Rx Half complete callback*/ + HAL_UART_RxHalfCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } +} + +/** + * @brief DMA UART communication error callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t dmarequest = 0x00U; + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Stop UART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + huart->TxXferCount = 0x00U; + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + huart->RxXferCount = 0x00U; + UART_EndRxTransfer(huart); + } + + huart->ErrorCode |= HAL_UART_ERROR_DMA; +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + huart->ErrorCallback(huart); +#else + /*Call legacy weak error callback*/ + HAL_UART_ErrorCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief This function handles UART Communication Timeout. It waits + * until a flag is no longer in the specified status. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param Flag specifies the UART flag to check. + * @param Status The actual Flag status (SET or RESET). + * @param Tickstart Tick start value + * @param Timeout Timeout duration + * @retval HAL status + */ +static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + + return HAL_TIMEOUT; + } + + if ((READ_BIT(huart->Instance->CR1, USART_CR1_RE) != 0U) && (Flag != UART_FLAG_TXE) && (Flag != UART_FLAG_TC)) + { + if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) == SET) + { + /* Clear Overrun Error flag*/ + __HAL_UART_CLEAR_OREFLAG(huart); + + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts if ongoing */ + UART_EndRxTransfer(huart); + + huart->ErrorCode = HAL_UART_ERROR_ORE; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief Start Receive operation in interrupt mode. + * @note This function could be called by all HAL UART API providing reception in Interrupt mode. + * @note When calling this function, parameters validity is considered as already checked, + * i.e. Rx State, buffer address, ... + * UART Handle is assumed as Locked. + * @param huart UART handle. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @retval HAL status + */ +HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + if (huart->Init.Parity != UART_PARITY_NONE) + { + /* Enable the UART Parity Error Interrupt */ + __HAL_UART_ENABLE_IT(huart, UART_IT_PE); + } + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + __HAL_UART_ENABLE_IT(huart, UART_IT_ERR); + + /* Enable the UART Data Register not empty Interrupt */ + __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); + + return HAL_OK; +} + +/** + * @brief Start Receive operation in DMA mode. + * @note This function could be called by all HAL UART API providing reception in DMA mode. + * @note When calling this function, parameters validity is considered as already checked, + * i.e. Rx State, buffer address, ... + * UART Handle is assumed as Locked. + * @param huart UART handle. + * @param pData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @retval HAL status + */ +HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + uint32_t *tmp; + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmarx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + tmp = (uint32_t *)&pData; + HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t *)tmp, Size); + + /* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */ + __HAL_UART_CLEAR_OREFLAG(huart); + + if (huart->Init.Parity != UART_PARITY_NONE) + { + /* Enable the UART Parity Error Interrupt */ + ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + } + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; +} + +/** + * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; +} + +/** + * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndRxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* In case of reception waiting for IDLE event, disable also the IDLE IE interrupt source */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + } + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; +} + +/** + * @brief DMA UART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + huart->RxXferCount = 0x00U; + huart->TxXferCount = 0x00U; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + huart->ErrorCallback(huart); +#else + /*Call legacy weak error callback*/ + HAL_UART_ErrorCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + huart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (huart->hdmarx != NULL) + { + if (huart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* Call user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + huart->AbortCpltCallback(huart); +#else + /* Call legacy weak Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + huart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (huart->hdmatx != NULL) + { + if (huart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* Call user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + huart->AbortCpltCallback(huart); +#else + /* Call legacy weak Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer) + * (This callback is executed at end of DMA Tx Abort procedure following user abort request, + * and leads to user Tx Abort Complete callback execution). + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + huart->AbortTransmitCpltCallback(huart); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortReceive_IT API (Abort only Rx transfer) + * (This callback is executed at end of DMA Rx Abort procedure following user abort request, + * and leads to user Rx Abort Complete callback execution). + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* Call user Abort complete callback */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + huart->AbortReceiveCpltCallback(huart); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +} + +/** + * @brief Sends an amount of data in non blocking mode. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart) +{ + const uint16_t *tmp; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (const uint16_t *) huart->pTxBuffPtr; + huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF); + huart->pTxBuffPtr += 2U; + } + else + { + huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF); + } + + if (--huart->TxXferCount == 0U) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ + __HAL_UART_DISABLE_IT(huart, UART_IT_TXE); + + /* Enable the UART Transmit Complete Interrupt */ + __HAL_UART_ENABLE_IT(huart, UART_IT_TC); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Wraps up transmission in non blocking mode. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable the UART Transmit Complete Interrupt */ + __HAL_UART_DISABLE_IT(huart, UART_IT_TC); + + /* Tx process is ended, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Tx complete callback*/ + huart->TxCpltCallback(huart); +#else + /*Call legacy weak Tx complete callback*/ + HAL_UART_TxCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + + return HAL_OK; +} + +/** + * @brief Receives an amount of data in non blocking mode + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) +{ + uint8_t *pdata8bits; + uint16_t *pdata16bits; + + /* Check that a Rx process is ongoing */ + if (huart->RxState == HAL_UART_STATE_BUSY_RX) + { + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + pdata8bits = NULL; + pdata16bits = (uint16_t *) huart->pRxBuffPtr; + *pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF); + huart->pRxBuffPtr += 2U; + } + else + { + pdata8bits = (uint8_t *) huart->pRxBuffPtr; + pdata16bits = NULL; + + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE))) + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F); + } + huart->pRxBuffPtr += 1U; + } + + if (--huart->RxXferCount == 0U) + { + /* Disable the UART Data Register not empty Interrupt */ + __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); + + /* Disable the UART Parity Error Interrupt */ + __HAL_UART_DISABLE_IT(huart, UART_IT_PE); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Initialize type of RxEvent to Transfer Complete */ + huart->RxEventType = HAL_UART_RXEVENT_TC; + + /* Check current reception Mode : + If Reception till IDLE event has been selected : */ + if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) + { + /* Set reception type to Standard */ + huart->ReceptionType = HAL_UART_RECEPTION_STANDARD; + + /* Disable IDLE interrupt */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); + + /* Check if IDLE flag is set */ + if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) + { + /* Clear IDLE flag in ISR */ + __HAL_UART_CLEAR_IDLEFLAG(huart); + } + +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx Event callback*/ + huart->RxEventCallback(huart, huart->RxXferSize); +#else + /*Call legacy weak Rx Event callback*/ + HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + else + { + /* Standard reception API called */ +#if (USE_HAL_UART_REGISTER_CALLBACKS == 1) + /*Call registered Rx complete callback*/ + huart->RxCpltCallback(huart); +#else + /*Call legacy weak Rx complete callback*/ + HAL_UART_RxCpltCallback(huart); +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + } + + return HAL_OK; + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures the UART peripheral. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +static void UART_SetConfig(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg; + uint32_t pclk; + + /* Check the parameters */ + assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); + assert_param(IS_UART_STOPBITS(huart->Init.StopBits)); + assert_param(IS_UART_PARITY(huart->Init.Parity)); + assert_param(IS_UART_MODE(huart->Init.Mode)); + + /*-------------------------- USART CR2 Configuration -----------------------*/ + /* Configure the UART Stop Bits: Set STOP[13:12] bits + according to huart->Init.StopBits value */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits); + + /*-------------------------- USART CR1 Configuration -----------------------*/ + /* Configure the UART Word Length, Parity and mode: + Set the M bits according to huart->Init.WordLength value + Set PCE and PS bits according to huart->Init.Parity value + Set TE and RE bits according to huart->Init.Mode value + Set OVER8 bit according to huart->Init.OverSampling value */ + +#if defined(USART_CR1_OVER8) + tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling; + MODIFY_REG(huart->Instance->CR1, + (uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8), + tmpreg); +#else + tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode; + MODIFY_REG(huart->Instance->CR1, + (uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE), + tmpreg); +#endif /* USART_CR1_OVER8 */ + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */ + MODIFY_REG(huart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE), huart->Init.HwFlowCtl); + + + if(huart->Instance == USART1) + { + pclk = HAL_RCC_GetPCLK2Freq(); + } + else + { + pclk = HAL_RCC_GetPCLK1Freq(); + } + + /*-------------------------- USART BRR Configuration ---------------------*/ +#if defined(USART_CR1_OVER8) + if (huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate); + } + else + { + huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate); + } +#else + huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate); +#endif /* USART_CR1_OVER8 */ +} + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/diode_tester/MDK-ARM/EventRecorderStub.scvd b/diode_tester/MDK-ARM/EventRecorderStub.scvd new file mode 100644 index 0000000..2956b29 --- /dev/null +++ b/diode_tester/MDK-ARM/EventRecorderStub.scvd @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/diode_tester/MDK-ARM/diode_tester.uvoptx b/diode_tester/MDK-ARM/diode_tester.uvoptx index 7c2f36b..26c819a 100644 --- a/diode_tester/MDK-ARM/diode_tester.uvoptx +++ b/diode_tester/MDK-ARM/diode_tester.uvoptx @@ -117,6 +117,26 @@ STLink\ST-LINKIII-KEIL_SWO.dll + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + 0 UL2CM3 @@ -125,10 +145,34 @@ 0 ST-LINKIII-KEIL_SWO - -U-O142 -O2254 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128 -FS08000000 -FL08000 -FP0($$Device:STM32F103C6$Flash\STM32F10x_128.FLM) + -U53FF72064980555724221187 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL08000 -FP0($$Device:STM32F103C6$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2 + + + 0 + 1 + tester_adc,0x10 + + + 1 + 1 + ADC_DMA_HalfBuff,0x0A + + + + + 0 + 2 + before_pulse_delay + + + 1 + 2 + pulse_delay + + 0 @@ -171,6 +215,24 @@ + + + System Viewer\ADC1 + 35903 + + + System Viewer\DMA1 + 35902 + + + System Viewer\GPIOA + 35904 + + + System Viewer\GPIOC + 35905 + + 1 0 @@ -182,14 +244,250 @@ - Application/MDK-ARM - 0 + Configs + 1 0 0 0 1 1 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_config.h + mylibs_config.h + 0 + 0 + + + 1 + 2 + 5 + 0 + 0 + 0 + ..\Core\Interfaces\interface_config.h + interface_config.h + 0 + 0 + + + 1 + 3 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_include.h + mylibs_include.h + 0 + 0 + + + 1 + 4 + 5 + 0 + 0 + 0 + ..\Core\Tester_main\tester_config.h + tester_config.h + 0 + 0 + + + + + Tester Main + 1 + 0 + 0 + 0 + + 2 + 5 + 1 + 0 + 0 + 0 + ..\Core\Tester_main\tester_adc_func.c + tester_adc_func.c + 0 + 0 + + + 2 + 6 + 5 + 0 + 0 + 0 + ..\Core\Tester_main\tester_adc_func.h + tester_adc_func.h + 0 + 0 + + + + + Interfaces + 1 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\Core\Interfaces\crc_algs.c + crc_algs.c + 0 + 0 + + + 3 + 8 + 5 + 0 + 0 + 0 + ..\Core\Interfaces\crc_algs.h + crc_algs.h + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\Core\Interfaces\modbus.c + modbus.c + 0 + 0 + + + 3 + 10 + 5 + 0 + 0 + 0 + ..\Core\Interfaces\modbus.h + modbus.h + 0 + 0 + + + 3 + 11 + 5 + 0 + 0 + 0 + ..\Core\Interfaces\modbus_data.h + modbus_data.h + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\Core\Interfaces\rs_message.c + rs_message.c + 0 + 0 + + + 3 + 13 + 5 + 0 + 0 + 0 + ..\Core\Interfaces\rs_message.h + rs_message.h + 0 + 0 + + + + + MyLibs + 0 + 0 + 0 + 0 + + 4 + 14 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\bit_access.h + bit_access.h + 0 + 0 + + + 4 + 15 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\mylibs_defs.h + mylibs_defs.h + 0 + 0 + + + 4 + 16 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\trace.h + trace.h + 0 + 0 + + + 4 + 17 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\trackers.h + trackers.h + 0 + 0 + + + + + Application/MDK-ARM + 0 + 0 + 0 + 0 + + 5 + 18 2 0 0 @@ -208,8 +506,8 @@ 0 0 - 2 - 2 + 6 + 19 1 0 0 @@ -220,8 +518,8 @@ 0 - 2 - 3 + 6 + 20 1 0 0 @@ -232,8 +530,8 @@ 0 - 2 - 4 + 6 + 21 1 0 0 @@ -244,8 +542,8 @@ 0 - 2 - 5 + 6 + 22 1 0 0 @@ -256,8 +554,8 @@ 0 - 2 - 6 + 6 + 23 1 0 0 @@ -268,8 +566,20 @@ 0 - 2 - 7 + 6 + 24 + 1 + 0 + 0 + 0 + ../Core/Src/usart.c + usart.c + 0 + 0 + + + 6 + 25 1 0 0 @@ -280,8 +590,8 @@ 0 - 2 - 8 + 6 + 26 1 0 0 @@ -300,8 +610,8 @@ 0 0 - 3 - 9 + 7 + 27 1 0 0 @@ -312,8 +622,8 @@ 0 - 3 - 10 + 7 + 28 1 0 0 @@ -324,8 +634,8 @@ 0 - 3 - 11 + 7 + 29 1 0 0 @@ -336,8 +646,8 @@ 0 - 3 - 12 + 7 + 30 1 0 0 @@ -348,8 +658,8 @@ 0 - 3 - 13 + 7 + 31 1 0 0 @@ -360,8 +670,8 @@ 0 - 3 - 14 + 7 + 32 1 0 0 @@ -372,8 +682,8 @@ 0 - 3 - 15 + 7 + 33 1 0 0 @@ -384,8 +694,8 @@ 0 - 3 - 16 + 7 + 34 1 0 0 @@ -396,8 +706,8 @@ 0 - 3 - 17 + 7 + 35 1 0 0 @@ -408,8 +718,8 @@ 0 - 3 - 18 + 7 + 36 1 0 0 @@ -420,8 +730,8 @@ 0 - 3 - 19 + 7 + 37 1 0 0 @@ -432,8 +742,8 @@ 0 - 3 - 20 + 7 + 38 1 0 0 @@ -444,8 +754,8 @@ 0 - 3 - 21 + 7 + 39 1 0 0 @@ -456,8 +766,8 @@ 0 - 3 - 22 + 7 + 40 1 0 0 @@ -468,8 +778,8 @@ 0 - 3 - 23 + 7 + 41 1 0 0 @@ -479,6 +789,18 @@ 0 0 + + 7 + 42 + 1 + 0 + 0 + 0 + ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c + stm32f1xx_hal_uart.c + 0 + 0 + @@ -488,8 +810,8 @@ 0 0 - 4 - 24 + 8 + 43 1 0 0 diff --git a/diode_tester/MDK-ARM/diode_tester.uvprojx b/diode_tester/MDK-ARM/diode_tester.uvprojx index bf720a9..6fe95c4 100644 --- a/diode_tester/MDK-ARM/diode_tester.uvprojx +++ b/diode_tester/MDK-ARM/diode_tester.uvprojx @@ -82,7 +82,7 @@ 0 - 0 + 1 0 @@ -341,7 +341,7 @@ USE_HAL_DRIVER,STM32F103x6 - ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include + ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Core/MyLibs;../Core/Interfaces;../Core/Tester_main @@ -382,6 +382,111 @@ + + Configs + + + mylibs_config.h + 5 + ..\Core\MyLibs\mylibs_config.h + + + interface_config.h + 5 + ..\Core\Interfaces\interface_config.h + + + mylibs_include.h + 5 + ..\Core\MyLibs\mylibs_include.h + + + tester_config.h + 5 + ..\Core\Tester_main\tester_config.h + + + + + Tester Main + + + tester_adc_func.c + 1 + ..\Core\Tester_main\tester_adc_func.c + + + tester_adc_func.h + 5 + ..\Core\Tester_main\tester_adc_func.h + + + + + Interfaces + + + crc_algs.c + 1 + ..\Core\Interfaces\crc_algs.c + + + crc_algs.h + 5 + ..\Core\Interfaces\crc_algs.h + + + modbus.c + 1 + ..\Core\Interfaces\modbus.c + + + modbus.h + 5 + ..\Core\Interfaces\modbus.h + + + modbus_data.h + 5 + ..\Core\Interfaces\modbus_data.h + + + rs_message.c + 1 + ..\Core\Interfaces\rs_message.c + + + rs_message.h + 5 + ..\Core\Interfaces\rs_message.h + + + + + MyLibs + + + bit_access.h + 5 + ..\Core\MyLibs\bit_access.h + + + mylibs_defs.h + 5 + ..\Core\MyLibs\mylibs_defs.h + + + trace.h + 5 + ..\Core\MyLibs\trace.h + + + trackers.h + 5 + ..\Core\MyLibs\trackers.h + + + Application/MDK-ARM @@ -522,6 +627,62 @@ + + usart.c + 1 + ../Core/Src/usart.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + stm32f1xx_it.c 1 @@ -612,6 +773,62 @@ 1 ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c + + stm32f1xx_hal_uart.c + 1 + ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + diff --git a/diode_tester/diode_tester.ioc b/diode_tester/diode_tester.ioc index 735b3be..3148886 100644 --- a/diode_tester/diode_tester.ioc +++ b/diode_tester/diode_tester.ioc @@ -1,7 +1,8 @@ #MicroXplorer Configuration settings - do not modify ADC1.Channel-3\#ChannelRegularConversion=ADC_CHANNEL_0 -ADC1.ExternalTrigConv=ADC_EXTERNALTRIGCONV_T3_TRGO -ADC1.IPParameters=Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,NbrOfConversionFlag,master,ExternalTrigConv +ADC1.ContinuousConvMode=ENABLE +ADC1.ExternalTrigConv=ADC_SOFTWARE_START +ADC1.IPParameters=Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,NbrOfConversionFlag,master,ExternalTrigConv,ContinuousConvMode ADC1.NbrOfConversionFlag=1 ADC1.Rank-3\#ChannelRegularConversion=1 ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_1CYCLE_5 @@ -13,7 +14,7 @@ Dma.ADC1.0.Direction=DMA_PERIPH_TO_MEMORY Dma.ADC1.0.Instance=DMA1_Channel1 Dma.ADC1.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD Dma.ADC1.0.MemInc=DMA_MINC_ENABLE -Dma.ADC1.0.Mode=DMA_NORMAL +Dma.ADC1.0.Mode=DMA_CIRCULAR Dma.ADC1.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD Dma.ADC1.0.PeriphInc=DMA_PINC_DISABLE Dma.ADC1.0.Priority=DMA_PRIORITY_LOW @@ -30,18 +31,24 @@ Mcu.IP1=DMA Mcu.IP2=NVIC Mcu.IP3=RCC Mcu.IP4=SYS -Mcu.IP5=TIM3 -Mcu.IPNb=6 +Mcu.IP5=TIM2 +Mcu.IP6=TIM3 +Mcu.IP7=USART1 +Mcu.IPNb=8 Mcu.Name=STM32F103C(4-6)Tx Mcu.Package=LQFP48 -Mcu.Pin0=PD0-OSC_IN -Mcu.Pin1=PD1-OSC_OUT -Mcu.Pin2=PA0-WKUP -Mcu.Pin3=PA13 -Mcu.Pin4=PA14 -Mcu.Pin5=VP_SYS_VS_Systick -Mcu.Pin6=VP_TIM3_VS_ClockSourceINT -Mcu.PinsNb=7 +Mcu.Pin0=PC13-TAMPER-RTC +Mcu.Pin1=PD0-OSC_IN +Mcu.Pin10=VP_TIM3_VS_ClockSourceINT +Mcu.Pin2=PD1-OSC_OUT +Mcu.Pin3=PA0-WKUP +Mcu.Pin4=PA9 +Mcu.Pin5=PA10 +Mcu.Pin6=PA13 +Mcu.Pin7=PA14 +Mcu.Pin8=VP_SYS_VS_Systick +Mcu.Pin9=VP_TIM2_VS_ClockSourceINT +Mcu.PinsNb=11 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F103C6Tx @@ -58,13 +65,21 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.TIM3_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false PA0-WKUP.Signal=ADCx_IN0 +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PC13-TAMPER-RTC.Locked=true +PC13-TAMPER-RTC.Signal=GPIO_Output PD0-OSC_IN.Mode=HSE-External-Oscillator PD0-OSC_IN.Signal=RCC_OSC_IN PD1-OSC_OUT.Mode=HSE-External-Oscillator @@ -100,7 +115,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC1_Init-ADC1-false-HAL-true,5-MX_TIM3_Init-TIM3-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC1_Init-ADC1-false-HAL-true,5-MX_TIM3_Init-TIM3-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_TIM2_Init-TIM2-false-HAL-true RCC.ADCFreqValue=12000000 RCC.ADCPresc=RCC_ADCPCLK2_DIV6 RCC.AHBFreq_Value=72000000 @@ -129,8 +144,12 @@ TIM3.IPParameters=Period,Prescaler,TIM_MasterOutputTrigger TIM3.Period=8999 TIM3.Prescaler=0 TIM3.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE +USART1.IPParameters=VirtualMode +USART1.VirtualMode=VM_ASYNC VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM2_VS_ClockSourceINT.Mode=Internal +VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT VP_TIM3_VS_ClockSourceINT.Mode=Internal VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT board=custom